diff --git a/.gitignore b/.gitignore
index f8c6c2e..d3670a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,43 +1,2 @@
-# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
-
-# dependencies
-node_modules/
-
-# Expo
-.expo/
-dist/
-web-build/
-expo-env.d.ts
-
-# Native
-.kotlin/
-*.orig.*
-*.jks
-*.p8
-*.p12
-*.key
-*.mobileprovision
-
-# Metro
-.metro-health-check*
-
-# debug
-npm-debug.*
-yarn-debug.*
-yarn-error.*
-
-# macOS
.DS_Store
-*.pem
-
-# local env files
-.env*.local
-
-# typescript
-*.tsbuildinfo
-
-app-example
-
-# generated native folders
-/ios
-/android
+*.env
diff --git a/native-route/android/.gitignore b/android/.gitignore
similarity index 100%
rename from native-route/android/.gitignore
rename to android/.gitignore
diff --git a/native-route/android/build.gradle.kts b/android/build.gradle.kts
similarity index 100%
rename from native-route/android/build.gradle.kts
rename to android/build.gradle.kts
diff --git a/native-route/android/gradle.properties b/android/gradle.properties
similarity index 100%
rename from native-route/android/gradle.properties
rename to android/gradle.properties
diff --git a/native-route/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar
similarity index 100%
rename from native-route/android/gradle/wrapper/gradle-wrapper.jar
rename to android/gradle/wrapper/gradle-wrapper.jar
diff --git a/native-route/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
similarity index 100%
rename from native-route/android/gradle/wrapper/gradle-wrapper.properties
rename to android/gradle/wrapper/gradle-wrapper.properties
diff --git a/native-route/android/gradlew b/android/gradlew
similarity index 100%
rename from native-route/android/gradlew
rename to android/gradlew
diff --git a/native-route/android/settings.gradle.kts b/android/settings.gradle.kts
similarity index 100%
rename from native-route/android/settings.gradle.kts
rename to android/settings.gradle.kts
diff --git a/native-route/android/src/main/java/com/rssuper/converters/DateConverter.kt b/android/src/main/java/com/rssuper/converters/DateConverter.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/converters/DateConverter.kt
rename to android/src/main/java/com/rssuper/converters/DateConverter.kt
diff --git a/native-route/android/src/main/java/com/rssuper/converters/FeedItemListConverter.kt b/android/src/main/java/com/rssuper/converters/FeedItemListConverter.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/converters/FeedItemListConverter.kt
rename to android/src/main/java/com/rssuper/converters/FeedItemListConverter.kt
diff --git a/native-route/android/src/main/java/com/rssuper/converters/StringListConverter.kt b/android/src/main/java/com/rssuper/converters/StringListConverter.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/converters/StringListConverter.kt
rename to android/src/main/java/com/rssuper/converters/StringListConverter.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/RssDatabase.kt b/android/src/main/java/com/rssuper/database/RssDatabase.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/RssDatabase.kt
rename to android/src/main/java/com/rssuper/database/RssDatabase.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/daos/BookmarkDao.kt b/android/src/main/java/com/rssuper/database/daos/BookmarkDao.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/daos/BookmarkDao.kt
rename to android/src/main/java/com/rssuper/database/daos/BookmarkDao.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/daos/FeedItemDao.kt b/android/src/main/java/com/rssuper/database/daos/FeedItemDao.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/daos/FeedItemDao.kt
rename to android/src/main/java/com/rssuper/database/daos/FeedItemDao.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/daos/SearchHistoryDao.kt b/android/src/main/java/com/rssuper/database/daos/SearchHistoryDao.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/daos/SearchHistoryDao.kt
rename to android/src/main/java/com/rssuper/database/daos/SearchHistoryDao.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/daos/SubscriptionDao.kt b/android/src/main/java/com/rssuper/database/daos/SubscriptionDao.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/daos/SubscriptionDao.kt
rename to android/src/main/java/com/rssuper/database/daos/SubscriptionDao.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/entities/BookmarkEntity.kt b/android/src/main/java/com/rssuper/database/entities/BookmarkEntity.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/entities/BookmarkEntity.kt
rename to android/src/main/java/com/rssuper/database/entities/BookmarkEntity.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/entities/FeedItemEntity.kt b/android/src/main/java/com/rssuper/database/entities/FeedItemEntity.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/entities/FeedItemEntity.kt
rename to android/src/main/java/com/rssuper/database/entities/FeedItemEntity.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/entities/SearchHistoryEntity.kt b/android/src/main/java/com/rssuper/database/entities/SearchHistoryEntity.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/entities/SearchHistoryEntity.kt
rename to android/src/main/java/com/rssuper/database/entities/SearchHistoryEntity.kt
diff --git a/native-route/android/src/main/java/com/rssuper/database/entities/SubscriptionEntity.kt b/android/src/main/java/com/rssuper/database/entities/SubscriptionEntity.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/database/entities/SubscriptionEntity.kt
rename to android/src/main/java/com/rssuper/database/entities/SubscriptionEntity.kt
diff --git a/native-route/android/src/main/java/com/rssuper/model/Error.kt b/android/src/main/java/com/rssuper/model/Error.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/model/Error.kt
rename to android/src/main/java/com/rssuper/model/Error.kt
diff --git a/native-route/android/src/main/java/com/rssuper/model/State.kt b/android/src/main/java/com/rssuper/model/State.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/model/State.kt
rename to android/src/main/java/com/rssuper/model/State.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/Feed.kt b/android/src/main/java/com/rssuper/models/Feed.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/Feed.kt
rename to android/src/main/java/com/rssuper/models/Feed.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/FeedItem.kt b/android/src/main/java/com/rssuper/models/FeedItem.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/FeedItem.kt
rename to android/src/main/java/com/rssuper/models/FeedItem.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/FeedSubscription.kt b/android/src/main/java/com/rssuper/models/FeedSubscription.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/FeedSubscription.kt
rename to android/src/main/java/com/rssuper/models/FeedSubscription.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/NotificationPreferences.kt b/android/src/main/java/com/rssuper/models/NotificationPreferences.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/NotificationPreferences.kt
rename to android/src/main/java/com/rssuper/models/NotificationPreferences.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/ReadingPreferences.kt b/android/src/main/java/com/rssuper/models/ReadingPreferences.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/ReadingPreferences.kt
rename to android/src/main/java/com/rssuper/models/ReadingPreferences.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/SearchFilters.kt b/android/src/main/java/com/rssuper/models/SearchFilters.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/SearchFilters.kt
rename to android/src/main/java/com/rssuper/models/SearchFilters.kt
diff --git a/native-route/android/src/main/java/com/rssuper/models/SearchResult.kt b/android/src/main/java/com/rssuper/models/SearchResult.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/models/SearchResult.kt
rename to android/src/main/java/com/rssuper/models/SearchResult.kt
diff --git a/native-route/android/src/main/java/com/rssuper/parsing/AtomParser.kt b/android/src/main/java/com/rssuper/parsing/AtomParser.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/parsing/AtomParser.kt
rename to android/src/main/java/com/rssuper/parsing/AtomParser.kt
diff --git a/native-route/android/src/main/java/com/rssuper/parsing/FeedParser.kt b/android/src/main/java/com/rssuper/parsing/FeedParser.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/parsing/FeedParser.kt
rename to android/src/main/java/com/rssuper/parsing/FeedParser.kt
diff --git a/native-route/android/src/main/java/com/rssuper/parsing/FeedType.kt b/android/src/main/java/com/rssuper/parsing/FeedType.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/parsing/FeedType.kt
rename to android/src/main/java/com/rssuper/parsing/FeedType.kt
diff --git a/native-route/android/src/main/java/com/rssuper/parsing/ParseResult.kt b/android/src/main/java/com/rssuper/parsing/ParseResult.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/parsing/ParseResult.kt
rename to android/src/main/java/com/rssuper/parsing/ParseResult.kt
diff --git a/native-route/android/src/main/java/com/rssuper/parsing/RSSParser.kt b/android/src/main/java/com/rssuper/parsing/RSSParser.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/parsing/RSSParser.kt
rename to android/src/main/java/com/rssuper/parsing/RSSParser.kt
diff --git a/native-route/android/src/main/java/com/rssuper/parsing/XmlParsingUtilities.kt b/android/src/main/java/com/rssuper/parsing/XmlParsingUtilities.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/parsing/XmlParsingUtilities.kt
rename to android/src/main/java/com/rssuper/parsing/XmlParsingUtilities.kt
diff --git a/native-route/android/src/main/java/com/rssuper/repository/BookmarkRepository.kt b/android/src/main/java/com/rssuper/repository/BookmarkRepository.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/repository/BookmarkRepository.kt
rename to android/src/main/java/com/rssuper/repository/BookmarkRepository.kt
diff --git a/native-route/android/src/main/java/com/rssuper/repository/FeedRepository.kt b/android/src/main/java/com/rssuper/repository/FeedRepository.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/repository/FeedRepository.kt
rename to android/src/main/java/com/rssuper/repository/FeedRepository.kt
diff --git a/native-route/android/src/main/java/com/rssuper/repository/Repositories.kt b/android/src/main/java/com/rssuper/repository/Repositories.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/repository/Repositories.kt
rename to android/src/main/java/com/rssuper/repository/Repositories.kt
diff --git a/native-route/android/src/main/java/com/rssuper/repository/RepositoriesImpl.kt b/android/src/main/java/com/rssuper/repository/RepositoriesImpl.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/repository/RepositoriesImpl.kt
rename to android/src/main/java/com/rssuper/repository/RepositoriesImpl.kt
diff --git a/native-route/android/src/main/java/com/rssuper/repository/SubscriptionRepository.kt b/android/src/main/java/com/rssuper/repository/SubscriptionRepository.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/repository/SubscriptionRepository.kt
rename to android/src/main/java/com/rssuper/repository/SubscriptionRepository.kt
diff --git a/native-route/android/src/main/java/com/rssuper/search/SearchQuery.kt b/android/src/main/java/com/rssuper/search/SearchQuery.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/search/SearchQuery.kt
rename to android/src/main/java/com/rssuper/search/SearchQuery.kt
diff --git a/native-route/android/src/main/java/com/rssuper/search/SearchResult.kt b/android/src/main/java/com/rssuper/search/SearchResult.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/search/SearchResult.kt
rename to android/src/main/java/com/rssuper/search/SearchResult.kt
diff --git a/native-route/android/src/main/java/com/rssuper/search/SearchResultProvider.kt b/android/src/main/java/com/rssuper/search/SearchResultProvider.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/search/SearchResultProvider.kt
rename to android/src/main/java/com/rssuper/search/SearchResultProvider.kt
diff --git a/native-route/android/src/main/java/com/rssuper/search/SearchService.kt b/android/src/main/java/com/rssuper/search/SearchService.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/search/SearchService.kt
rename to android/src/main/java/com/rssuper/search/SearchService.kt
diff --git a/native-route/android/src/main/java/com/rssuper/services/FeedFetcher.kt b/android/src/main/java/com/rssuper/services/FeedFetcher.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/services/FeedFetcher.kt
rename to android/src/main/java/com/rssuper/services/FeedFetcher.kt
diff --git a/native-route/android/src/main/java/com/rssuper/services/FetchResult.kt b/android/src/main/java/com/rssuper/services/FetchResult.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/services/FetchResult.kt
rename to android/src/main/java/com/rssuper/services/FetchResult.kt
diff --git a/native-route/android/src/main/java/com/rssuper/services/HTTPAuthCredentials.kt b/android/src/main/java/com/rssuper/services/HTTPAuthCredentials.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/services/HTTPAuthCredentials.kt
rename to android/src/main/java/com/rssuper/services/HTTPAuthCredentials.kt
diff --git a/native-route/android/src/main/java/com/rssuper/services/NetworkError.kt b/android/src/main/java/com/rssuper/services/NetworkError.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/services/NetworkError.kt
rename to android/src/main/java/com/rssuper/services/NetworkError.kt
diff --git a/native-route/android/src/main/java/com/rssuper/state/BookmarkState.kt b/android/src/main/java/com/rssuper/state/BookmarkState.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/state/BookmarkState.kt
rename to android/src/main/java/com/rssuper/state/BookmarkState.kt
diff --git a/native-route/android/src/main/java/com/rssuper/state/ErrorType.kt b/android/src/main/java/com/rssuper/state/ErrorType.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/state/ErrorType.kt
rename to android/src/main/java/com/rssuper/state/ErrorType.kt
diff --git a/native-route/android/src/main/java/com/rssuper/state/State.kt b/android/src/main/java/com/rssuper/state/State.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/state/State.kt
rename to android/src/main/java/com/rssuper/state/State.kt
diff --git a/native-route/android/src/main/java/com/rssuper/viewmodel/FeedViewModel.kt b/android/src/main/java/com/rssuper/viewmodel/FeedViewModel.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/viewmodel/FeedViewModel.kt
rename to android/src/main/java/com/rssuper/viewmodel/FeedViewModel.kt
diff --git a/native-route/android/src/main/java/com/rssuper/viewmodel/SubscriptionViewModel.kt b/android/src/main/java/com/rssuper/viewmodel/SubscriptionViewModel.kt
similarity index 100%
rename from native-route/android/src/main/java/com/rssuper/viewmodel/SubscriptionViewModel.kt
rename to android/src/main/java/com/rssuper/viewmodel/SubscriptionViewModel.kt
diff --git a/native-route/android/src/test/java/com/rssuper/database/FeedItemDaoTest.kt b/android/src/test/java/com/rssuper/database/FeedItemDaoTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/database/FeedItemDaoTest.kt
rename to android/src/test/java/com/rssuper/database/FeedItemDaoTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/database/RssDatabaseTest.kt b/android/src/test/java/com/rssuper/database/RssDatabaseTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/database/RssDatabaseTest.kt
rename to android/src/test/java/com/rssuper/database/RssDatabaseTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/database/SearchHistoryDaoTest.kt b/android/src/test/java/com/rssuper/database/SearchHistoryDaoTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/database/SearchHistoryDaoTest.kt
rename to android/src/test/java/com/rssuper/database/SearchHistoryDaoTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/database/SubscriptionDaoTest.kt b/android/src/test/java/com/rssuper/database/SubscriptionDaoTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/database/SubscriptionDaoTest.kt
rename to android/src/test/java/com/rssuper/database/SubscriptionDaoTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/FeedItemTest.kt b/android/src/test/java/com/rssuper/models/FeedItemTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/FeedItemTest.kt
rename to android/src/test/java/com/rssuper/models/FeedItemTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/FeedSubscriptionTest.kt b/android/src/test/java/com/rssuper/models/FeedSubscriptionTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/FeedSubscriptionTest.kt
rename to android/src/test/java/com/rssuper/models/FeedSubscriptionTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/FeedTest.kt b/android/src/test/java/com/rssuper/models/FeedTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/FeedTest.kt
rename to android/src/test/java/com/rssuper/models/FeedTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/NotificationPreferencesTest.kt b/android/src/test/java/com/rssuper/models/NotificationPreferencesTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/NotificationPreferencesTest.kt
rename to android/src/test/java/com/rssuper/models/NotificationPreferencesTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/ReadingPreferencesTest.kt b/android/src/test/java/com/rssuper/models/ReadingPreferencesTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/ReadingPreferencesTest.kt
rename to android/src/test/java/com/rssuper/models/ReadingPreferencesTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/SearchFiltersTest.kt b/android/src/test/java/com/rssuper/models/SearchFiltersTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/SearchFiltersTest.kt
rename to android/src/test/java/com/rssuper/models/SearchFiltersTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/models/SearchResultTest.kt b/android/src/test/java/com/rssuper/models/SearchResultTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/models/SearchResultTest.kt
rename to android/src/test/java/com/rssuper/models/SearchResultTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/parsing/AtomParserTest.kt b/android/src/test/java/com/rssuper/parsing/AtomParserTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/parsing/AtomParserTest.kt
rename to android/src/test/java/com/rssuper/parsing/AtomParserTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/parsing/FeedParserTest.kt b/android/src/test/java/com/rssuper/parsing/FeedParserTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/parsing/FeedParserTest.kt
rename to android/src/test/java/com/rssuper/parsing/FeedParserTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/parsing/RSSParserTest.kt b/android/src/test/java/com/rssuper/parsing/RSSParserTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/parsing/RSSParserTest.kt
rename to android/src/test/java/com/rssuper/parsing/RSSParserTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/repository/FeedRepositoryTest.kt b/android/src/test/java/com/rssuper/repository/FeedRepositoryTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/repository/FeedRepositoryTest.kt
rename to android/src/test/java/com/rssuper/repository/FeedRepositoryTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/repository/SubscriptionRepositoryTest.kt b/android/src/test/java/com/rssuper/repository/SubscriptionRepositoryTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/repository/SubscriptionRepositoryTest.kt
rename to android/src/test/java/com/rssuper/repository/SubscriptionRepositoryTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/services/FeedFetcherIntegrationTest.kt b/android/src/test/java/com/rssuper/services/FeedFetcherIntegrationTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/services/FeedFetcherIntegrationTest.kt
rename to android/src/test/java/com/rssuper/services/FeedFetcherIntegrationTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/services/FeedFetcherTest.kt b/android/src/test/java/com/rssuper/services/FeedFetcherTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/services/FeedFetcherTest.kt
rename to android/src/test/java/com/rssuper/services/FeedFetcherTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/services/FetchResultTest.kt b/android/src/test/java/com/rssuper/services/FetchResultTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/services/FetchResultTest.kt
rename to android/src/test/java/com/rssuper/services/FetchResultTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/services/HTTPAuthCredentialsTest.kt b/android/src/test/java/com/rssuper/services/HTTPAuthCredentialsTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/services/HTTPAuthCredentialsTest.kt
rename to android/src/test/java/com/rssuper/services/HTTPAuthCredentialsTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/state/StateTest.kt b/android/src/test/java/com/rssuper/state/StateTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/state/StateTest.kt
rename to android/src/test/java/com/rssuper/state/StateTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/viewmodel/FeedViewModelTest.kt b/android/src/test/java/com/rssuper/viewmodel/FeedViewModelTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/viewmodel/FeedViewModelTest.kt
rename to android/src/test/java/com/rssuper/viewmodel/FeedViewModelTest.kt
diff --git a/native-route/android/src/test/java/com/rssuper/viewmodel/SubscriptionViewModelTest.kt b/android/src/test/java/com/rssuper/viewmodel/SubscriptionViewModelTest.kt
similarity index 100%
rename from native-route/android/src/test/java/com/rssuper/viewmodel/SubscriptionViewModelTest.kt
rename to android/src/test/java/com/rssuper/viewmodel/SubscriptionViewModelTest.kt
diff --git a/app.json b/app.json
deleted file mode 100644
index c382511..0000000
--- a/app.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
- "expo": {
- "name": "rssuper",
- "slug": "rssuper",
- "version": "1.0.0",
- "orientation": "portrait",
- "icon": "./assets/images/icon.png",
- "scheme": "rssuper",
- "userInterfaceStyle": "automatic",
- "ios": {
- "icon": "./assets/expo.icon"
- },
- "android": {
- "adaptiveIcon": {
- "backgroundColor": "#E6F4FE",
- "foregroundImage": "./assets/images/android-icon-foreground.png",
- "backgroundImage": "./assets/images/android-icon-background.png",
- "monochromeImage": "./assets/images/android-icon-monochrome.png"
- },
- "predictiveBackGestureEnabled": false
- },
- "web": {
- "output": "static",
- "favicon": "./assets/images/favicon.png"
- },
- "plugins": [
- "expo-router",
- [
- "expo-splash-screen",
- {
- "backgroundColor": "#208AEF",
- "android": {
- "image": "./assets/images/splash-icon.png",
- "imageWidth": 76
- }
- }
- ],
- "expo-localization",
- "expo-sqlite"
- ],
- "experiments": {
- "typedRoutes": true,
- "reactCompiler": true
- },
- "extra": {
- "router": {},
- "eas": {
- "projectId": "006dd772-380c-4e20-9754-42a15ad83fc9"
- }
- },
- "owner": "mikefrenodev"
- }
-}
diff --git a/assets/expo.icon/Assets/expo-symbol 2.svg b/assets/expo.icon/Assets/expo-symbol 2.svg
deleted file mode 100644
index 51d3676..0000000
--- a/assets/expo.icon/Assets/expo-symbol 2.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/assets/expo.icon/Assets/grid.png b/assets/expo.icon/Assets/grid.png
deleted file mode 100644
index eefea24..0000000
Binary files a/assets/expo.icon/Assets/grid.png and /dev/null differ
diff --git a/assets/expo.icon/icon.json b/assets/expo.icon/icon.json
deleted file mode 100644
index 7a2c33c..0000000
--- a/assets/expo.icon/icon.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "fill" : {
- "automatic-gradient" : "extended-srgb:0.00000,0.47843,1.00000,1.00000"
- },
- "groups" : [
- {
- "layers" : [
- {
- "image-name" : "expo-symbol 2.svg",
- "name" : "expo-symbol 2",
- "position" : {
- "scale" : 1,
- "translation-in-points" : [
- 1.1008400065293245e-05,
- -16.046875
- ]
- }
- },
- {
- "image-name" : "grid.png",
- "name" : "grid"
- }
- ],
- "shadow" : {
- "kind" : "neutral",
- "opacity" : 0.5
- },
- "translucency" : {
- "enabled" : true,
- "value" : 0.5
- }
- }
- ],
- "supported-platforms" : {
- "circles" : [
- "watchOS"
- ],
- "squares" : "shared"
- }
-}
\ No newline at end of file
diff --git a/assets/images/android-icon-background.png b/assets/images/android-icon-background.png
deleted file mode 100644
index 5ffefc5..0000000
Binary files a/assets/images/android-icon-background.png and /dev/null differ
diff --git a/assets/images/android-icon-foreground.png b/assets/images/android-icon-foreground.png
deleted file mode 100644
index 3a9e501..0000000
Binary files a/assets/images/android-icon-foreground.png and /dev/null differ
diff --git a/assets/images/android-icon-monochrome.png b/assets/images/android-icon-monochrome.png
deleted file mode 100644
index 77484eb..0000000
Binary files a/assets/images/android-icon-monochrome.png and /dev/null differ
diff --git a/assets/images/expo-badge-white.png b/assets/images/expo-badge-white.png
deleted file mode 100644
index 2863067..0000000
Binary files a/assets/images/expo-badge-white.png and /dev/null differ
diff --git a/assets/images/expo-badge.png b/assets/images/expo-badge.png
deleted file mode 100644
index 5d5c5bb..0000000
Binary files a/assets/images/expo-badge.png and /dev/null differ
diff --git a/assets/images/expo-logo.png b/assets/images/expo-logo.png
deleted file mode 100644
index 6b1642a..0000000
Binary files a/assets/images/expo-logo.png and /dev/null differ
diff --git a/assets/images/favicon.png b/assets/images/favicon.png
deleted file mode 100644
index 408bd74..0000000
Binary files a/assets/images/favicon.png and /dev/null differ
diff --git a/assets/images/icon.png b/assets/images/icon.png
deleted file mode 100644
index 67c777a..0000000
Binary files a/assets/images/icon.png and /dev/null differ
diff --git a/assets/images/logo-glow.png b/assets/images/logo-glow.png
deleted file mode 100644
index edc99be..0000000
Binary files a/assets/images/logo-glow.png and /dev/null differ
diff --git a/assets/images/react-logo.png b/assets/images/react-logo.png
deleted file mode 100644
index 9d72a9f..0000000
Binary files a/assets/images/react-logo.png and /dev/null differ
diff --git a/assets/images/react-logo@2x.png b/assets/images/react-logo@2x.png
deleted file mode 100644
index 2229b13..0000000
Binary files a/assets/images/react-logo@2x.png and /dev/null differ
diff --git a/assets/images/react-logo@3x.png b/assets/images/react-logo@3x.png
deleted file mode 100644
index a99b203..0000000
Binary files a/assets/images/react-logo@3x.png and /dev/null differ
diff --git a/assets/images/splash-icon.png b/assets/images/splash-icon.png
deleted file mode 100644
index 6b1642a..0000000
Binary files a/assets/images/splash-icon.png and /dev/null differ
diff --git a/assets/images/tabIcons/explore.png b/assets/images/tabIcons/explore.png
deleted file mode 100644
index 73d8258..0000000
Binary files a/assets/images/tabIcons/explore.png and /dev/null differ
diff --git a/assets/images/tabIcons/explore@2x.png b/assets/images/tabIcons/explore@2x.png
deleted file mode 100644
index 21b9bd2..0000000
Binary files a/assets/images/tabIcons/explore@2x.png and /dev/null differ
diff --git a/assets/images/tabIcons/explore@3x.png b/assets/images/tabIcons/explore@3x.png
deleted file mode 100644
index 422202d..0000000
Binary files a/assets/images/tabIcons/explore@3x.png and /dev/null differ
diff --git a/assets/images/tabIcons/home.png b/assets/images/tabIcons/home.png
deleted file mode 100644
index ad5699c..0000000
Binary files a/assets/images/tabIcons/home.png and /dev/null differ
diff --git a/assets/images/tabIcons/home@2x.png b/assets/images/tabIcons/home@2x.png
deleted file mode 100644
index 22a1f2c..0000000
Binary files a/assets/images/tabIcons/home@2x.png and /dev/null differ
diff --git a/assets/images/tabIcons/home@3x.png b/assets/images/tabIcons/home@3x.png
deleted file mode 100644
index f5d1f9a..0000000
Binary files a/assets/images/tabIcons/home@3x.png and /dev/null differ
diff --git a/assets/images/tabIcons/search.png b/assets/images/tabIcons/search.png
deleted file mode 100644
index d5ca21e..0000000
Binary files a/assets/images/tabIcons/search.png and /dev/null differ
diff --git a/assets/images/tabIcons/search@2x.png b/assets/images/tabIcons/search@2x.png
deleted file mode 100644
index 566d4e7..0000000
Binary files a/assets/images/tabIcons/search@2x.png and /dev/null differ
diff --git a/assets/images/tabIcons/search@3x.png b/assets/images/tabIcons/search@3x.png
deleted file mode 100644
index bdfe117..0000000
Binary files a/assets/images/tabIcons/search@3x.png and /dev/null differ
diff --git a/assets/images/tabIcons/settings.png b/assets/images/tabIcons/settings.png
deleted file mode 100644
index 7c3673f..0000000
Binary files a/assets/images/tabIcons/settings.png and /dev/null differ
diff --git a/assets/images/tabIcons/settings@2x.png b/assets/images/tabIcons/settings@2x.png
deleted file mode 100644
index cb59117..0000000
Binary files a/assets/images/tabIcons/settings@2x.png and /dev/null differ
diff --git a/assets/images/tabIcons/settings@3x.png b/assets/images/tabIcons/settings@3x.png
deleted file mode 100644
index 1b693b8..0000000
Binary files a/assets/images/tabIcons/settings@3x.png and /dev/null differ
diff --git a/assets/images/tutorial-web.png b/assets/images/tutorial-web.png
deleted file mode 100644
index e4a8c58..0000000
Binary files a/assets/images/tutorial-web.png and /dev/null differ
diff --git a/bun.lock b/bun.lock
deleted file mode 100644
index 9ca0187..0000000
--- a/bun.lock
+++ /dev/null
@@ -1,2033 +0,0 @@
-{
- "lockfileVersion": 1,
- "configVersion": 1,
- "workspaces": {
- "": {
- "name": "rssuper",
- "dependencies": {
- "@react-native-async-storage/async-storage": "^3.0.2",
- "@react-navigation/bottom-tabs": "^7.15.5",
- "@react-navigation/elements": "^2.9.10",
- "@react-navigation/native": "^7.1.33",
- "@tanstack/react-query": "^5.95.2",
- "axios": "^1.14.0",
- "buffer": "^6.0.3",
- "events": "^3.3.0",
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "expo-device": "55.0.11-canary-20260328-2049187",
- "expo-font": "55.0.5-canary-20260328-2049187",
- "expo-glass-effect": "55.0.9-canary-20260328-2049187",
- "expo-image": "55.0.7-canary-20260328-2049187",
- "expo-linking": "55.0.10-canary-20260328-2049187",
- "expo-localization": "55.0.10-canary-20260328-2049187",
- "expo-notifications": "55.0.15-canary-20260328-2049187",
- "expo-router": "55.0.9-canary-20260328-2049187",
- "expo-splash-screen": "55.0.14-canary-20260328-2049187",
- "expo-sqlite": "55.0.12-canary-20260328-2049187",
- "expo-status-bar": "55.0.5-canary-20260328-2049187",
- "expo-symbols": "55.0.6-canary-20260328-2049187",
- "expo-system-ui": "55.0.12-canary-20260328-2049187",
- "expo-task-manager": "55.0.11-canary-20260328-2049187",
- "expo-web-browser": "55.0.11-canary-20260328-2049187",
- "fast-xml-parser": "^5.5.9",
- "react": "19.2.0",
- "react-dom": "19.2.0",
- "react-native": "0.83.4",
- "react-native-gesture-handler": "~2.30.0",
- "react-native-reanimated": "4.2.1",
- "react-native-render-html": "^6.3.4",
- "react-native-safe-area-context": "~5.6.2",
- "react-native-screens": "~4.23.0",
- "react-native-web": "~0.21.0",
- "react-native-worklets": "0.7.2",
- "stream-browserify": "^3.0.0",
- "zustand": "^5.0.12",
- },
- "devDependencies": {
- "@types/react": "~19.2.2",
- "@types/xml2js": "^0.4.14",
- "eslint": "^9.0.0",
- "eslint-config-expo": "55.0.1-canary-20260328-2049187",
- "typescript": "~5.9.2",
- },
- },
- },
- "packages": {
- "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
-
- "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="],
-
- "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],
-
- "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
-
- "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="],
-
- "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
-
- "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="],
-
- "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw=="],
-
- "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.8", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA=="],
-
- "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
-
- "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="],
-
- "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
-
- "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="],
-
- "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="],
-
- "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="],
-
- "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-wrap-function": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA=="],
-
- "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="],
-
- "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="],
-
- "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
-
- "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
-
- "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
-
- "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ=="],
-
- "@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="],
-
- "@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
-
- "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.29.0", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-syntax-decorators": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA=="],
-
- "@babel/plugin-proposal-export-default-from": ["@babel/plugin-proposal-export-default-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hjlsMBl1aJc5lp8MoCDEZCiYzlgdRAShOjAfRw6X+GlpLpUPU7c3XNLsKFZbQk/1cRzBlJ7CXg3xJAJMrFa1Uw=="],
-
- "@babel/plugin-syntax-async-generators": ["@babel/plugin-syntax-async-generators@7.8.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw=="],
-
- "@babel/plugin-syntax-bigint": ["@babel/plugin-syntax-bigint@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg=="],
-
- "@babel/plugin-syntax-class-properties": ["@babel/plugin-syntax-class-properties@7.12.13", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA=="],
-
- "@babel/plugin-syntax-class-static-block": ["@babel/plugin-syntax-class-static-block@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw=="],
-
- "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA=="],
-
- "@babel/plugin-syntax-dynamic-import": ["@babel/plugin-syntax-dynamic-import@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ=="],
-
- "@babel/plugin-syntax-export-default-from": ["@babel/plugin-syntax-export-default-from@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Svlx1fjJFnNz0LZeUaybRukSxZI3KkpApUmIRzEdXC5k8ErTOz0OD0kNrICi5Vc3GlpP5ZCeRyRO+mfWTSz+iQ=="],
-
- "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew=="],
-
- "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw=="],
-
- "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="],
-
- "@babel/plugin-syntax-json-strings": ["@babel/plugin-syntax-json-strings@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA=="],
-
- "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="],
-
- "@babel/plugin-syntax-logical-assignment-operators": ["@babel/plugin-syntax-logical-assignment-operators@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig=="],
-
- "@babel/plugin-syntax-nullish-coalescing-operator": ["@babel/plugin-syntax-nullish-coalescing-operator@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ=="],
-
- "@babel/plugin-syntax-numeric-separator": ["@babel/plugin-syntax-numeric-separator@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug=="],
-
- "@babel/plugin-syntax-object-rest-spread": ["@babel/plugin-syntax-object-rest-spread@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA=="],
-
- "@babel/plugin-syntax-optional-catch-binding": ["@babel/plugin-syntax-optional-catch-binding@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q=="],
-
- "@babel/plugin-syntax-optional-chaining": ["@babel/plugin-syntax-optional-chaining@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg=="],
-
- "@babel/plugin-syntax-private-property-in-object": ["@babel/plugin-syntax-private-property-in-object@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg=="],
-
- "@babel/plugin-syntax-top-level-await": ["@babel/plugin-syntax-top-level-await@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw=="],
-
- "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="],
-
- "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA=="],
-
- "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", "@babel/traverse": "^7.29.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w=="],
-
- "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g=="],
-
- "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw=="],
-
- "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.27.1", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA=="],
-
- "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ=="],
-
- "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.28.4", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/traverse": "^7.28.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA=="],
-
- "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/template": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ=="],
-
- "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw=="],
-
- "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ=="],
-
- "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/plugin-syntax-flow": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-G5eDKsu50udECw7DL2AcsysXiQyB7Nfg521t2OAJ4tbfTJ27doHLeF/vlI1NZGlLdbb/v+ibvtL1YBQqYOwJGg=="],
-
- "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw=="],
-
- "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.27.1", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ=="],
-
- "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA=="],
-
- "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A=="],
-
- "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="],
-
- "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.0", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ=="],
-
- "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA=="],
-
- "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w=="],
-
- "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.28.6", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA=="],
-
- "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ=="],
-
- "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg=="],
-
- "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg=="],
-
- "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg=="],
-
- "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA=="],
-
- "@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.28.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA=="],
-
- "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-syntax-jsx": "^7.28.6", "@babel/types": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow=="],
-
- "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.27.1", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q=="],
-
- "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
-
- "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
-
- "@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA=="],
-
- "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog=="],
-
- "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.29.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w=="],
-
- "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ=="],
-
- "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA=="],
-
- "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g=="],
-
- "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg=="],
-
- "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="],
-
- "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.27.1", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw=="],
-
- "@babel/preset-react": ["@babel/preset-react@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-transform-react-display-name": "^7.28.0", "@babel/plugin-transform-react-jsx": "^7.27.1", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ=="],
-
- "@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="],
-
- "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
-
- "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
-
- "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
-
- "@babel/traverse--for-generate-function-map": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
-
- "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
-
- "@egjs/hammerjs": ["@egjs/hammerjs@2.0.17", "", { "dependencies": { "@types/hammerjs": "^2.0.36" } }, "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A=="],
-
- "@emnapi/core": ["@emnapi/core@1.9.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.0", "tslib": "^2.4.0" } }, "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA=="],
-
- "@emnapi/runtime": ["@emnapi/runtime@1.9.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA=="],
-
- "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg=="],
-
- "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
-
- "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
-
- "@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
-
- "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
-
- "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
-
- "@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="],
-
- "@eslint/js": ["@eslint/js@9.39.4", "", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="],
-
- "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
-
- "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
-
- "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.27", "", {}, "sha512-cnb3DZnWUWpezGFkJ8y4MT5f/lw6FcgDzeJzic+T+vpQHLHG1cg3SC3i1w1i8Bk4xKR4HPY3t9iIRNvtr5ml8A=="],
-
- "@expo/cli": ["@expo/cli@55.0.20-canary-20260328-2049187", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "55.0.12-canary-20260328-2049187", "@expo/config-plugins": "55.0.8-canary-20260328-2049187", "@expo/devcert": "^1.2.1", "@expo/env": "2.1.2-canary-20260328-2049187", "@expo/image-utils": "0.8.13-canary-20260328-2049187", "@expo/json-file": "10.0.13-canary-20260328-2049187", "@expo/log-box": "55.0.9-canary-20260328-2049187", "@expo/metro": "~54.2.0", "@expo/metro-config": "55.0.12-canary-20260328-2049187", "@expo/osascript": "2.4.3-canary-20260328-2049187", "@expo/package-manager": "1.10.4-canary-20260328-2049187", "@expo/plist": "0.5.3-canary-20260328-2049187", "@expo/prebuild-config": "55.0.12-canary-20260328-2049187", "@expo/require-utils": "55.0.4-canary-20260328-2049187", "@expo/router-server": "55.0.12-canary-20260328-2049187", "@expo/schema-utils": "55.0.3-canary-20260328-2049187", "@expo/spawn-async": "^1.7.2", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.0", "@react-native/dev-middleware": "0.83.4", "accepts": "^1.3.8", "arg": "^5.0.2", "better-opn": "~3.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.3", "expo-server": "55.0.7-canary-20260328-2049187", "fetch-nodeshim": "^0.4.6", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.0", "multitars": "^0.2.3", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.3", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "source-map-support": "~0.5.21", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "expo-router": "55.0.9-canary-20260328-2049187", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "build/bin/cli" } }, "sha512-drj/Gg7BpGeqCNBTxPeQR7kfiW4EFTOHRmrtcnXtT1qC96LVlpzOrkwcCLRdumvmeARGA055HFqKdHNxvwsCmg=="],
-
- "@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="],
-
- "@expo/config": ["@expo/config@55.0.12-canary-20260328-2049187", "", { "dependencies": { "@expo/config-plugins": "55.0.8-canary-20260328-2049187", "@expo/config-types": "55.0.6-canary-20260328-2049187", "@expo/json-file": "10.0.13-canary-20260328-2049187", "@expo/require-utils": "55.0.4-canary-20260328-2049187", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-PV5QVwrxNBQ8vb3/wecKMLIuiU+Yx8pNRdDHU+5EAaykKIfvkLh6aHEJQCDwG3tMOHGgtTYs5jjtEoJoWWMQ+g=="],
-
- "@expo/config-plugins": ["@expo/config-plugins@55.0.8-canary-20260328-2049187", "", { "dependencies": { "@expo/config-types": "55.0.6-canary-20260328-2049187", "@expo/json-file": "10.0.13-canary-20260328-2049187", "@expo/plist": "0.5.3-canary-20260328-2049187", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-from": "^5.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-FJ81ylIzcIXEIt2VHTr23YixsqVWOErwwYhpf0+mGv4Rrnqkae97fTROUjeQEcKlB2uIkfe/gqwA5grwSF0c5A=="],
-
- "@expo/config-types": ["@expo/config-types@55.0.6-canary-20260328-2049187", "", {}, "sha512-Pc+bPfbyHGrvcg70XnkHY1ffemjDcBzFn+y6/nsS5aZCrhehtSRX6jrxujyJSa0zRnPxXTBO646NVa/kGZ5UrQ=="],
-
- "@expo/devcert": ["@expo/devcert@1.2.1", "", { "dependencies": { "@expo/sudo-prompt": "^9.3.1", "debug": "^3.1.0" } }, "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA=="],
-
- "@expo/devtools": ["@expo/devtools@55.0.3-canary-20260328-2049187", "", { "dependencies": { "chalk": "^4.1.2" }, "peerDependencies": { "react": "*", "react-native": "*" }, "optionalPeers": ["react", "react-native"] }, "sha512-dC5wZWTMpRTKj/ZQFAfe32wioowXOmb2v6CF55Qz6YQyWlZBmdw4zz8e1htio/s4esuewUMOrbNpzGG+s+wKGQ=="],
-
- "@expo/dom-webview": ["@expo/dom-webview@55.0.4-canary-20260328-2049187", "", { "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-esptcjUTCe2GDkyD8GbM8YzvWiJAw/SIb+OfpIfshNAkAx/2dsPhJKYQpOungASqC9G/yJRmVYH0qp1cMNF/8g=="],
-
- "@expo/env": ["@expo/env@2.1.2-canary-20260328-2049187", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "getenv": "^2.0.0" } }, "sha512-mmJOdhPNnB+hIh0v/1uLVwB9rc1N+mpbFZNLcGXFvful/RDbJgbCXvSg5BbQ/4LWyquairZ2AArNDHqe0Y4RPA=="],
-
- "@expo/fingerprint": ["@expo/fingerprint@0.16.7-canary-20260328-2049187", "", { "dependencies": { "@expo/env": "2.1.2-canary-20260328-2049187", "@expo/spawn-async": "^1.7.2", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "minimatch": "^10.2.2", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-NuZJpNoqbflsB8S4GfEpJARqQTVqduRq0IiBCrIwa2Rfv9VyhTUFku37Qo/+s5rms60sS5+q+lOh9x2O3RaEKw=="],
-
- "@expo/image-utils": ["@expo/image-utils@0.8.13-canary-20260328-2049187", "", { "dependencies": { "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "resolve-from": "^5.0.0", "semver": "^7.6.0" } }, "sha512-p3AyR5fgcOOBRglKh7akw94IeY9DHrY2oPfhTMsNxlTsk1ShDlnpkOozlubwC9XXdPewG0RTuIhLmeyQ9kw77A=="],
-
- "@expo/json-file": ["@expo/json-file@10.0.13-canary-20260328-2049187", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-a1lKlVUu5QnKzC0RVCH9Fwwbx4W1g9g9Uw63gah3V+D+PGiXkOpIH3rMTMEnj3wesBcMj5JouBAoxFWnh5PLSw=="],
-
- "@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@55.0.8-canary-20260328-2049187", "", { "dependencies": { "@expo/config": "55.0.12-canary-20260328-2049187", "chalk": "^4.1.2" } }, "sha512-4PiIk7LNqzV+xTsFLRBG/FhJeh+7MF4sXrAQUPIeJEFDPRo8qlapqcHaiXhwsYrHmnpbZ+DaJ5mf7p9T5f0ijg=="],
-
- "@expo/log-box": ["@expo/log-box@55.0.9-canary-20260328-2049187", "", { "dependencies": { "@expo/dom-webview": "55.0.4-canary-20260328-2049187", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-7Ar4ZQeq1bAhHZUx7eZrmhLFsfV3MPZmhlHdbzI+1FxTd5Ctsp/aRmrWGASTyxIKrLqGnBMEuXWOo60znGddBA=="],
-
- "@expo/metro": ["@expo/metro@54.2.0", "", { "dependencies": { "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-minify-terser": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3" } }, "sha512-h68TNZPGsk6swMmLm9nRSnE2UXm48rWwgcbtAHVMikXvbxdS41NDHHeqg1rcQ9AbznDRp6SQVC2MVpDnsRKU1w=="],
-
- "@expo/metro-config": ["@expo/metro-config@55.0.12-canary-20260328-2049187", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "55.0.12-canary-20260328-2049187", "@expo/env": "2.1.2-canary-20260328-2049187", "@expo/json-file": "10.0.13-canary-20260328-2049187", "@expo/metro": "~54.2.0", "@expo/spawn-async": "^1.7.2", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.32.0", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.3", "postcss": "~8.4.32", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187" }, "optionalPeers": ["expo"] }, "sha512-dKOEKSIrVzkYVd36HpGSf0hWyhEHY19VyOh/isGN1DlNrQNWXkKIlsTpDJTHEUUFILdWJWtWdJDhZVmEQ8aYDw=="],
-
- "@expo/metro-runtime": ["@expo/metro-runtime@55.0.8-canary-20260328-2049187", "", { "dependencies": { "@expo/log-box": "55.0.9-canary-20260328-2049187", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-7mJ36gDCoKehvnhmkRcSyh2dhSZ4l/d2kdd0TIgHEesyX08L0BHetck0TTc1TnqG+iIOPUPYGw55d4jn49R83g=="],
-
- "@expo/osascript": ["@expo/osascript@2.4.3-canary-20260328-2049187", "", { "dependencies": { "@expo/spawn-async": "^1.7.2" } }, "sha512-QyeIXAZvGc7FFVMaZ8QzWaNFqOWIUZtHSGgp4BW6W8F/1jnEhwIKTLS/EBW1284HY/rHzanFIU9gXb2X1mJn2A=="],
-
- "@expo/package-manager": ["@expo/package-manager@1.10.4-canary-20260328-2049187", "", { "dependencies": { "@expo/json-file": "10.0.13-canary-20260328-2049187", "@expo/spawn-async": "^1.7.2", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-svISoZOJzdlssVPrpP8OyVtWLuxvIHk3RzkDJKSHZlzuMepCNSbkme8Ec/5KkQt9oK1jQMOTRsk2hCkpYK+Y1g=="],
-
- "@expo/plist": ["@expo/plist@0.5.3-canary-20260328-2049187", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-2lyc4DpjRwz9yNcJn82pfC3AKarzJUt7fjPl/4qrn8KROPmq9xb4A2DBk7tgYCPKPUlBocEViVQ+zB4l9t2YFQ=="],
-
- "@expo/prebuild-config": ["@expo/prebuild-config@55.0.12-canary-20260328-2049187", "", { "dependencies": { "@expo/config": "55.0.12-canary-20260328-2049187", "@expo/config-plugins": "55.0.8-canary-20260328-2049187", "@expo/config-types": "55.0.6-canary-20260328-2049187", "@expo/image-utils": "0.8.13-canary-20260328-2049187", "@expo/json-file": "10.0.13-canary-20260328-2049187", "@react-native/normalize-colors": "0.83.4", "debug": "^4.3.1", "resolve-from": "^5.0.0", "semver": "^7.6.0", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187" } }, "sha512-btOLRQh3a5bI1bKFWXd3JWfUFDp2TdNjy5crXJh1uBa0uXnw83ZDrcqrLZY0mMA1ocUN3ES61DamjwSMukDhGg=="],
-
- "@expo/require-utils": ["@expo/require-utils@55.0.4-canary-20260328-2049187", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0" }, "optionalPeers": ["typescript"] }, "sha512-xjShWGciKtN5mOiiDABPrwaXlmfmhn7H5OSnoWN1D5u2SzfJomazGdez4KkBf65QjVCL3HY/oC6ErGqjzVKH+Q=="],
-
- "@expo/router-server": ["@expo/router-server@55.0.12-canary-20260328-2049187", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "55.0.8-canary-20260328-2049187", "expo": "55.0.10-canary-20260328-2049187", "expo-constants": "55.0.10-canary-20260328-2049187", "expo-font": "55.0.5-canary-20260328-2049187", "expo-router": "55.0.9-canary-20260328-2049187", "expo-server": "55.0.7-canary-20260328-2049187", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-eMZUTTdyBSC7kaBnbhm3NTAxHnCyhdSaR1cxiBUpwdWSORldBUp+5TxWYLdseXeWGgr4D/2prjWf8i0Lp4uQfw=="],
-
- "@expo/schema-utils": ["@expo/schema-utils@55.0.3-canary-20260328-2049187", "", {}, "sha512-17klALt2lnW/sZm1e4jKwOhh+Bl/QLFAuPcW05e4M/Z8CuT4n7nSxAPvM2bI5TQUaEeB7aPGoOUHeKbGgWkWNQ=="],
-
- "@expo/sdk-runtime-versions": ["@expo/sdk-runtime-versions@1.0.0", "", {}, "sha512-Doz2bfiPndXYFPMRwPyGa1k5QaKDVpY806UJj570epIiMzWaYyCtobasyfC++qfIXVb5Ocy7r3tP9d62hAQ7IQ=="],
-
- "@expo/spawn-async": ["@expo/spawn-async@1.7.2", "", { "dependencies": { "cross-spawn": "^7.0.3" } }, "sha512-QdWi16+CHB9JYP7gma19OVVg0BFkvU8zNj9GjWorYI8Iv8FUxjOCcYRuAmX4s/h91e4e7BPsskc8cSrZYho9Ew=="],
-
- "@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="],
-
- "@expo/vector-icons": ["@expo/vector-icons@15.1.1", "", { "peerDependencies": { "expo-font": ">=14.0.4", "react": "*", "react-native": "*" } }, "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw=="],
-
- "@expo/ws-tunnel": ["@expo/ws-tunnel@1.0.6", "", {}, "sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q=="],
-
- "@expo/xcpretty": ["@expo/xcpretty@4.4.1", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-KZNxZvnGCtiM2aYYZ6Wz0Ix5r47dAvpNLApFtZWnSoERzAdOMzVBOPysBoM0JlF6FKWZ8GPqgn6qt3dV/8Zlpg=="],
-
- "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
-
- "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
-
- "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
-
- "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
-
- "@isaacs/ttlcache": ["@isaacs/ttlcache@1.4.1", "", {}, "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA=="],
-
- "@istanbuljs/load-nyc-config": ["@istanbuljs/load-nyc-config@1.1.0", "", { "dependencies": { "camelcase": "^5.3.1", "find-up": "^4.1.0", "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" } }, "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ=="],
-
- "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
-
- "@jest/create-cache-key-function": ["@jest/create-cache-key-function@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3" } }, "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA=="],
-
- "@jest/environment": ["@jest/environment@29.7.0", "", { "dependencies": { "@jest/fake-timers": "^29.7.0", "@jest/types": "^29.6.3", "@types/node": "*", "jest-mock": "^29.7.0" } }, "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw=="],
-
- "@jest/fake-timers": ["@jest/fake-timers@29.7.0", "", { "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" } }, "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ=="],
-
- "@jest/schemas": ["@jest/schemas@29.6.3", "", { "dependencies": { "@sinclair/typebox": "^0.27.8" } }, "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA=="],
-
- "@jest/transform": ["@jest/transform@29.7.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" } }, "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw=="],
-
- "@jest/types": ["@jest/types@29.6.3", "", { "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" } }, "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw=="],
-
- "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
-
- "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
-
- "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
-
- "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="],
-
- "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
-
- "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
-
- "@jsamr/counter-style": ["@jsamr/counter-style@2.0.2", "", {}, "sha512-2mXudGVtSzVxWEA7B9jZLKjoXUeUFYDDtFrQoC0IFX9/Dszz4t1vZOmafi3JSw/FxD+udMQ+4TAFR8Qs0J3URQ=="],
-
- "@jsamr/react-native-li": ["@jsamr/react-native-li@2.3.1", "", { "peerDependencies": { "@jsamr/counter-style": "^1.0.0 || ^2.0.0", "react": "*", "react-native": "*" } }, "sha512-Qbo4NEj48SQ4k8FZJHFE2fgZDKTWaUGmVxcIQh3msg5JezLdTMMHuRRDYctfdHI6L0FZGObmEv3haWbIvmol8w=="],
-
- "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
-
- "@native-html/css-processor": ["@native-html/css-processor@1.11.0", "", { "dependencies": { "css-to-react-native": "^3.0.0", "csstype": "^3.0.8" }, "peerDependencies": { "@types/react": "*", "@types/react-native": "*" } }, "sha512-NnhBEbJX5M2gBGltPKOetiLlKhNf3OHdRafc8//e2ZQxXN8JaSW/Hy8cm94pnIckQxwaMKxrtaNT3x4ZcffoNQ=="],
-
- "@native-html/transient-render-engine": ["@native-html/transient-render-engine@11.2.3", "", { "dependencies": { "@native-html/css-processor": "1.11.0", "@types/ramda": "^0.27.44", "csstype": "^3.0.9", "domelementtype": "^2.2.0", "domhandler": "^4.2.2", "domutils": "^2.8.0", "htmlparser2": "^7.1.2", "ramda": "^0.27.2" }, "peerDependencies": { "@types/react-native": "*", "react-native": "^*" } }, "sha512-zXwgA3gPUEmFs3I3syfnvDvS6WiUHXEE6jY09OBzK+trq7wkweOSFWIoyXiGkbXrozGYG0KY90YgPyr8Tg8Uyg=="],
-
- "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
-
- "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
-
- "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="],
-
- "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
-
- "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
-
- "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="],
-
- "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="],
-
- "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
-
- "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="],
-
- "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="],
-
- "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
-
- "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
-
- "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
-
- "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
-
- "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="],
-
- "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
-
- "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="],
-
- "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
-
- "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
-
- "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
-
- "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
-
- "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
-
- "@react-native-async-storage/async-storage": ["@react-native-async-storage/async-storage@3.0.2", "", { "dependencies": { "idb": "8.0.3" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-XP0zDIl+1XoeuQ7f878qXKdl77zLwzLALPpxvNRc7ZtDh9ew36WSvOdQOhFkexMySapFAWxEbZxS8K8J2DU4eg=="],
-
- "@react-native/assets-registry": ["@react-native/assets-registry@0.83.4", "", {}, "sha512-aqKtpbJDSQeSX/Dwv0yMe1/Rd2QfXi12lnyZDXNn/OEKz59u6+LuPBVgO/9CRyclHmdlvwg8c7PJ9eX2ZMnjWg=="],
-
- "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.83.4", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.83.4" } }, "sha512-UFsK+c1rvT84XZfzpmwKePsc5nTr5LK7hh18TI0DooNlVcztDbMDsQZpDnhO/gmk7aTbWEqO5AB3HJ7tvGp+Jg=="],
-
- "@react-native/babel-preset": ["@react-native/babel-preset@0.83.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.83.4", "babel-plugin-syntax-hermes-parser": "0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-SXPFn3Jp4gOzlBDnDOKPzMfxQPKJMYJs05EmEeFB/6km46xZ9l+2YKXwAwxfNhHnmwNf98U/bnVndU95I0TMCw=="],
-
- "@react-native/codegen": ["@react-native/codegen@0.83.4", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.32.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "yargs": "^17.6.2" } }, "sha512-CJ7XutzIqJPz3Lp/5TOiRWlU/JAjTboMT1BHNLSXjYHXwTmgHM3iGEbpCOtBMjWvsojRTJyRO/G3ghInIIXEYg=="],
-
- "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.83.4", "", { "dependencies": { "@react-native/dev-middleware": "0.83.4", "debug": "^4.4.0", "invariant": "^2.2.4", "metro": "^0.83.3", "metro-config": "^0.83.3", "metro-core": "^0.83.3", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*", "@react-native/metro-config": "*" }, "optionalPeers": ["@react-native-community/cli", "@react-native/metro-config"] }, "sha512-8os0weQEnjUhWy7Db881+JKRwNHVGM40VtTRvltAyA/YYkrGg4kPCqiTybMxQDEcF3rnviuxHyI+ITiglfmgmQ=="],
-
- "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.83.4", "", {}, "sha512-mCE2s/S7SEjax3gZb6LFAraAI3x13gRVWJWqT0HIm71e4ITObENNTDuMw4mvZ/wr4Gz2wv4FcBH5/Nla9LXOcg=="],
-
- "@react-native/debugger-shell": ["@react-native/debugger-shell@0.83.4", "", { "dependencies": { "cross-spawn": "^7.0.6", "fb-dotslash": "0.5.8" } }, "sha512-FtAnrvXqy1xeZ+onwilvxEeeBsvBlhtfrHVIC2R/BOJAK9TbKEtFfjio0wsn3DQIm+UZq48DSa+p9jJZ2aJUww=="],
-
- "@react-native/dev-middleware": ["@react-native/dev-middleware@0.83.4", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.83.4", "@react-native/debugger-shell": "0.83.4", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^4.4.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "serve-static": "^1.16.2", "ws": "^7.5.10" } }, "sha512-3s9nXZc/kj986nI2RPqxiIJeTS3o7pvZDxbHu7GE9WVIGX9YucA1l/tEiXd7BAm3TBFOfefDOT08xD46wH+R3Q=="],
-
- "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.83.4", "", {}, "sha512-AhaSWw2k3eMKqZ21IUdM7rpyTYOpAfsBbIIiom1QQii3QccX0uW2AWTcRhfuWRxqr2faGFaOBYedWl2fzp5hgw=="],
-
- "@react-native/js-polyfills": ["@react-native/js-polyfills@0.83.4", "", {}, "sha512-wYUdv0rt4MjhKhQloO1AnGDXhZQOFZHDxm86dEtEA0WcsCdVrFdRULFM+rKUC/QQtJW2rS6WBqtBusgtrsDADg=="],
-
- "@react-native/normalize-colors": ["@react-native/normalize-colors@0.83.4", "", {}, "sha512-9ezxaHjxqTkTOLg62SGg7YhFaE+fxa/jlrWP0nwf7eGFHlGOiTAaRR2KUfiN3K05e+EMbEhgcH/c7bgaXeGyJw=="],
-
- "@react-native/virtualized-lists": ["@react-native/virtualized-lists@0.83.4", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^19.2.0", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-vNF/8kokMW8JEjG4n+j7veLTjHRRABlt4CaTS6+wtqzvWxCJHNIC8fhCqrDPn9fIn8sNePd8DyiFVX5L9TBBRA=="],
-
- "@react-navigation/bottom-tabs": ["@react-navigation/bottom-tabs@7.15.9", "", { "dependencies": { "@react-navigation/elements": "^2.9.14", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0" }, "peerDependencies": { "@react-navigation/native": "^7.2.2", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-Ou28A1aZLj5wiFQ3F93aIsrI4NCwn3IJzkkjNo9KLFXsc0Yks+UqrVaFlffHFLsrbajuGRG/OQpnMA1ljayY5Q=="],
-
- "@react-navigation/core": ["@react-navigation/core@7.17.2", "", { "dependencies": { "@react-navigation/routers": "^7.5.3", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-Rt2OZwcgOmjv401uLGAKaRM6xo0fiBce/A7LfRHI1oe5FV+KooWcgAoZ2XOtgKj6UzVMuQWt3b2e6rxo/mDJRA=="],
-
- "@react-navigation/elements": ["@react-navigation/elements@2.9.14", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.2.2", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-lKqzu+su2pI/YIZmR7L7xdOs4UL+rVXKJAMpRMBrwInEy96SjIFst6QDGpE89Dunnu3VjVpjWfByo9f2GWBHDQ=="],
-
- "@react-navigation/native": ["@react-navigation/native@7.2.2", "", { "dependencies": { "@react-navigation/core": "^7.17.2", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-kem1Ko2BcbAjmbQIv66dNmr6EtfDut3QU0qjsVhMnLLhktwyXb6FzZYp8gTrUb6AvkAbaJoi+BF5Pl55pAUa5w=="],
-
- "@react-navigation/native-stack": ["@react-navigation/native-stack@7.14.10", "", { "dependencies": { "@react-navigation/elements": "^2.9.14", "color": "^4.2.3", "sf-symbols-typescript": "^2.1.0", "warn-once": "^0.1.1" }, "peerDependencies": { "@react-navigation/native": "^7.2.2", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0", "react-native-screens": ">= 4.0.0" } }, "sha512-mCbYbYhi7Em2R2nEgwYGdLU38smy+KK+HMMVcwuzllWsF3Qb+jOUEYbB6Or7LvE7SS77BZ6sHdx4HptCEv50hQ=="],
-
- "@react-navigation/routers": ["@react-navigation/routers@7.5.3", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-1tJHg4KKRJuQ1/EvJxatrMef3NZXEPzwUIUZ3n1yJ2t7Q97siwRtbynRpQG9/69ebbtiZ8W3ScOZF/OmhvM4Rg=="],
-
- "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
-
- "@sinclair/typebox": ["@sinclair/typebox@0.27.10", "", {}, "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA=="],
-
- "@sinonjs/commons": ["@sinonjs/commons@3.0.1", "", { "dependencies": { "type-detect": "4.0.8" } }, "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ=="],
-
- "@sinonjs/fake-timers": ["@sinonjs/fake-timers@10.3.0", "", { "dependencies": { "@sinonjs/commons": "^3.0.0" } }, "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA=="],
-
- "@tanstack/query-core": ["@tanstack/query-core@5.95.2", "", {}, "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ=="],
-
- "@tanstack/react-query": ["@tanstack/react-query@5.95.2", "", { "dependencies": { "@tanstack/query-core": "5.95.2" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA=="],
-
- "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
-
- "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
-
- "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
-
- "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
-
- "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
-
- "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
-
- "@types/graceful-fs": ["@types/graceful-fs@4.1.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ=="],
-
- "@types/hammerjs": ["@types/hammerjs@2.0.46", "", {}, "sha512-ynRvcq6wvqexJ9brDMS4BnBLzmr0e14d6ZJTEShTBWKymQiHwlAyGu0ZPEFI2Fh1U53F7tN9ufClWM5KvqkKOw=="],
-
- "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="],
-
- "@types/istanbul-lib-report": ["@types/istanbul-lib-report@3.0.3", "", { "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA=="],
-
- "@types/istanbul-reports": ["@types/istanbul-reports@3.0.4", "", { "dependencies": { "@types/istanbul-lib-report": "*" } }, "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ=="],
-
- "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
-
- "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
-
- "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
-
- "@types/ramda": ["@types/ramda@0.27.66", "", { "dependencies": { "ts-toolbelt": "^6.15.1" } }, "sha512-i2YW+E2U6NfMt3dp0RxNcejox+bxJUNDjB7BpYuRuoHIzv5juPHkJkNgcUOu+YSQEmaWu8cnAo/8r63C0NnuVA=="],
-
- "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
-
- "@types/react-native": ["@types/react-native@0.73.0", "", { "dependencies": { "react-native": "*" } }, "sha512-6ZRPQrYM72qYKGWidEttRe6M5DZBEV5F+MHMHqd4TTYx0tfkcdrUFGdef6CCxY0jXU7wldvd/zA/b0A/kTeJmA=="],
-
- "@types/stack-utils": ["@types/stack-utils@2.0.3", "", {}, "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="],
-
- "@types/urijs": ["@types/urijs@1.19.26", "", {}, "sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg=="],
-
- "@types/xml2js": ["@types/xml2js@0.4.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ=="],
-
- "@types/yargs": ["@types/yargs@17.0.35", "", { "dependencies": { "@types/yargs-parser": "*" } }, "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg=="],
-
- "@types/yargs-parser": ["@types/yargs-parser@21.0.3", "", {}, "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="],
-
- "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.2", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/type-utils": "8.57.2", "@typescript-eslint/utils": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.2", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-NZZgp0Fm2IkD+La5PR81sd+g+8oS6JwJje+aRWsDocxHkjyRw0J5L5ZTlN3LI1LlOcGL7ph3eaIUmTXMIjLk0w=="],
-
- "@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.2", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-30ScMRHIAD33JJQkgfGW1t8CURZtjc2JpTrq5n2HFhOefbAhb7ucc7xJwdWcrEtqUIYJ73Nybpsggii6GtAHjA=="],
-
- "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.2", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.2", "@typescript-eslint/types": "^8.57.2", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-FuH0wipFywXRTHf+bTTjNyuNQQsQC3qh/dYzaM4I4W0jrCqjCVuUh99+xd9KamUfmCGPvbO8NDngo/vsnNVqgw=="],
-
- "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.2", "", { "dependencies": { "@typescript-eslint/types": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2" } }, "sha512-snZKH+W4WbWkrBqj4gUNRIGb/jipDW3qMqVJ4C9rzdFc+wLwruxk+2a5D+uoFcKPAqyqEnSb4l2ULuZf95eSkw=="],
-
- "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.2", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-3Lm5DSM+DCowsUOJC+YqHHnKEfFh5CoGkj5Z31NQSNF4l5wdOwqGn99wmwN/LImhfY3KJnmordBq/4+VDe2eKw=="],
-
- "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.2", "", { "dependencies": { "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2", "@typescript-eslint/utils": "8.57.2", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Co6ZCShm6kIbAM/s+oYVpKFfW7LBc6FXoPXjTRQ449PPNBY8U0KZXuevz5IFuuUj2H9ss40atTaf9dlGLzbWZg=="],
-
- "@typescript-eslint/types": ["@typescript-eslint/types@8.57.2", "", {}, "sha512-/iZM6FnM4tnx9csuTxspMW4BOSegshwX5oBDznJ7S4WggL7Vczz5d2W11ecc4vRrQMQHXRSxzrCsyG5EsPPTbA=="],
-
- "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.2", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.2", "@typescript-eslint/tsconfig-utils": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/visitor-keys": "8.57.2", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-2MKM+I6g8tJxfSmFKOnHv2t8Sk3T6rF20A1Puk0svLK+uVapDZB/4pfAeB7nE83uAZrU6OxW+HmOd5wHVdXwXA=="],
-
- "@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.2", "@typescript-eslint/types": "8.57.2", "@typescript-eslint/typescript-estree": "8.57.2" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-krRIbvPK1ju1WBKIefiX+bngPs+odIQUtR7kymzPfo1POVw3jlF+nLkmexdSSd4UCbDcQn+wMBATOOmpBbqgKg=="],
-
- "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.2", "", { "dependencies": { "@typescript-eslint/types": "8.57.2", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zhahknjobV2FiD6Ee9iLbS7OV9zi10rG26odsQdfBO/hjSzUQbkIYgda+iNKK1zNiW2ey+Lf8MU5btN17V3dUw=="],
-
- "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
-
- "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
-
- "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="],
-
- "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="],
-
- "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="],
-
- "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="],
-
- "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="],
-
- "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="],
-
- "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="],
-
- "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="],
-
- "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="],
-
- "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="],
-
- "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="],
-
- "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="],
-
- "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="],
-
- "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="],
-
- "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="],
-
- "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="],
-
- "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="],
-
- "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="],
-
- "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="],
-
- "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
-
- "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
-
- "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
-
- "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
-
- "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
-
- "ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
-
- "anser": ["anser@1.4.10", "", {}, "sha512-hCv9AqTQ8ycjpSd3upOJd7vFwW1JaoYQ7tpham03GJ1ca8/65rqn0RpaWpItOAd6ylW9wAw6luXYPJIyPFVOww=="],
-
- "ansi-escapes": ["ansi-escapes@4.3.2", "", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="],
-
- "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
-
- "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
-
- "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
-
- "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
-
- "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
-
- "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="],
-
- "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
-
- "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="],
-
- "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="],
-
- "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="],
-
- "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
-
- "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
-
- "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="],
-
- "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
-
- "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="],
-
- "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
-
- "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
-
- "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
-
- "await-lock": ["await-lock@2.2.2", "", {}, "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw=="],
-
- "axios": ["axios@1.14.0", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" } }, "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ=="],
-
- "babel-jest": ["babel-jest@29.7.0", "", { "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" }, "peerDependencies": { "@babel/core": "^7.8.0" } }, "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg=="],
-
- "babel-plugin-istanbul": ["babel-plugin-istanbul@6.1.1", "", { "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" } }, "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA=="],
-
- "babel-plugin-jest-hoist": ["babel-plugin-jest-hoist@29.6.3", "", { "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" } }, "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg=="],
-
- "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.17", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w=="],
-
- "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.13.0", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.5", "core-js-compat": "^3.43.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A=="],
-
- "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.8", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg=="],
-
- "babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="],
-
- "babel-plugin-react-native-web": ["babel-plugin-react-native-web@0.21.2", "", {}, "sha512-SPD0J6qjJn8231i0HZhlAGH6NORe+QvRSQM2mwQEzJ2Fb3E4ruWTiiicPlHjmeWShDXLcvoorOCXjeR7k/lyWA=="],
-
- "babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.32.0", "", { "dependencies": { "hermes-parser": "0.32.0" } }, "sha512-m5HthL++AbyeEA2FcdwOLfVFvWYECOBObLHNqdR8ceY4TsEdn4LdX2oTvbB2QJSSElE2AWA/b2MXZ/PF/CqLZg=="],
-
- "babel-plugin-transform-flow-enums": ["babel-plugin-transform-flow-enums@0.0.2", "", { "dependencies": { "@babel/plugin-syntax-flow": "^7.12.1" } }, "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ=="],
-
- "babel-preset-current-node-syntax": ["babel-preset-current-node-syntax@1.2.0", "", { "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0 || ^8.0.0-0" } }, "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg=="],
-
- "babel-preset-expo": ["babel-preset-expo@55.0.14-canary-20260328-2049187", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/preset-react": "^7.22.15", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-preset": "0.83.4", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.32.0", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4", "resolve-from": "^5.0.0" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "55.0.10-canary-20260328-2049187", "expo-widgets": "55.0.9-canary-20260328-2049187", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-LIKMEc9bKg972lkYGr9WgHwg5T2g1GfD7wK6nW/ueBtCTdtGDrFm2jsthVzQFuHuJ3WIHmgO0BwZQ1CViwUS1Q=="],
-
- "babel-preset-jest": ["babel-preset-jest@29.6.3", "", { "dependencies": { "babel-plugin-jest-hoist": "^29.6.3", "babel-preset-current-node-syntax": "^1.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA=="],
-
- "badgin": ["badgin@1.2.3", "", {}, "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw=="],
-
- "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
-
- "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
-
- "baseline-browser-mapping": ["baseline-browser-mapping@2.10.12", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ=="],
-
- "better-opn": ["better-opn@3.0.2", "", { "dependencies": { "open": "^8.0.4" } }, "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ=="],
-
- "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="],
-
- "bplist-creator": ["bplist-creator@0.1.0", "", { "dependencies": { "stream-buffers": "2.2.x" } }, "sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg=="],
-
- "bplist-parser": ["bplist-parser@0.3.1", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA=="],
-
- "brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="],
-
- "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
-
- "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
-
- "bser": ["bser@2.1.1", "", { "dependencies": { "node-int64": "^0.4.0" } }, "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ=="],
-
- "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="],
-
- "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="],
-
- "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
-
- "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
-
- "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
-
- "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
-
- "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
-
- "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
-
- "camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="],
-
- "caniuse-lite": ["caniuse-lite@1.0.30001781", "", {}, "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw=="],
-
- "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
-
- "character-entities-html4": ["character-entities-html4@1.1.4", "", {}, "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g=="],
-
- "character-entities-legacy": ["character-entities-legacy@1.1.4", "", {}, "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA=="],
-
- "chrome-launcher": ["chrome-launcher@0.15.2", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0" }, "bin": { "print-chrome-path": "bin/print-chrome-path.js" } }, "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ=="],
-
- "chromium-edge-launcher": ["chromium-edge-launcher@0.2.0", "", { "dependencies": { "@types/node": "*", "escape-string-regexp": "^4.0.0", "is-wsl": "^2.2.0", "lighthouse-logger": "^1.0.0", "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-JfJjUnq25y9yg4FABRRVPmBGWPZZi+AQXT4mxupb67766/0UlhG8PAZCz6xzEMXTbW3CsSoE8PcCWA49n35mKg=="],
-
- "ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
-
- "cli-cursor": ["cli-cursor@2.1.0", "", { "dependencies": { "restore-cursor": "^2.0.0" } }, "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw=="],
-
- "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
-
- "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
-
- "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
-
- "clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
-
- "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
-
- "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
-
- "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
-
- "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
-
- "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
-
- "commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
-
- "compressible": ["compressible@2.0.18", "", { "dependencies": { "mime-db": ">= 1.43.0 < 2" } }, "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg=="],
-
- "compression": ["compression@1.8.1", "", { "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" } }, "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w=="],
-
- "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
-
- "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="],
-
- "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
-
- "core-js-compat": ["core-js-compat@3.49.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA=="],
-
- "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="],
-
- "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
-
- "css-color-keywords": ["css-color-keywords@1.0.0", "", {}, "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="],
-
- "css-in-js-utils": ["css-in-js-utils@3.1.0", "", { "dependencies": { "hyphenate-style-name": "^1.0.3" } }, "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A=="],
-
- "css-to-react-native": ["css-to-react-native@3.2.0", "", { "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", "postcss-value-parser": "^4.0.2" } }, "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ=="],
-
- "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
-
- "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
-
- "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
-
- "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
-
- "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
-
- "decode-uri-component": ["decode-uri-component@0.2.2", "", {}, "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ=="],
-
- "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
-
- "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
-
- "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="],
-
- "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
-
- "define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="],
-
- "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
-
- "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
-
- "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
-
- "destroy": ["destroy@1.2.0", "", {}, "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="],
-
- "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
-
- "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="],
-
- "dnssd-advertise": ["dnssd-advertise@1.1.4", "", {}, "sha512-AmGyK9WpNf06WeP5TjHZq/wNzP76OuEeaiTlKr9E/EEelYLczywUKoqRz+DPRq/ErssjT4lU+/W7wzJW+7K/ZA=="],
-
- "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
-
- "dom-serializer": ["dom-serializer@1.4.1", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" } }, "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag=="],
-
- "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
-
- "domhandler": ["domhandler@4.3.1", "", { "dependencies": { "domelementtype": "^2.2.0" } }, "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ=="],
-
- "domutils": ["domutils@2.8.0", "", { "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" } }, "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A=="],
-
- "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
-
- "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
-
- "electron-to-chromium": ["electron-to-chromium@1.5.328", "", {}, "sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w=="],
-
- "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
-
- "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
-
- "entities": ["entities@3.0.1", "", {}, "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q=="],
-
- "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="],
-
- "es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="],
-
- "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
-
- "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
-
- "es-iterator-helpers": ["es-iterator-helpers@1.3.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.1", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0", "safe-array-concat": "^1.1.3" } }, "sha512-zWwRvqWiuBPr0muUG/78cW3aHROFCNIQ3zpmYDpwdbnt2m+xlNyRWpHBpa2lJjSBit7BQ+RXA1iwbSmu5yJ/EQ=="],
-
- "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
-
- "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
-
- "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
-
- "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
-
- "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
-
- "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
-
- "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
-
- "eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
-
- "eslint-config-expo": ["eslint-config-expo@55.0.1-canary-20260328-2049187", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "^8.18.2", "@typescript-eslint/parser": "^8.18.2", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-expo": "1.0.1-canary-20260328-2049187", "eslint-plugin-import": "^2.30.0", "eslint-plugin-react": "^7.37.3", "eslint-plugin-react-hooks": "^5.1.0", "globals": "^16.0.0" }, "peerDependencies": { "eslint": ">=8.10" } }, "sha512-JlC49CdX65Zbs3gKX/4y6fOXSfr98eZEK0hnRUVv5MwqyZRTFcK/73AE0U9M5ILSfIh5Pxel0N5MH+oxZXhJEw=="],
-
- "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
-
- "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="],
-
- "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="],
-
- "eslint-plugin-expo": ["eslint-plugin-expo@1.0.1-canary-20260328-2049187", "", { "dependencies": { "@typescript-eslint/types": "^8.29.1", "@typescript-eslint/utils": "^8.29.1", "eslint": "^9.24.0" } }, "sha512-jCZIQZ3B6C5G4V4sujKaHc9rQTZ1mEy5N6iVVz3BV2s2ApY35ww/w+4BroAU8TT2kZisBDLJeUV5jO7O6nKx4g=="],
-
- "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="],
-
- "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
-
- "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
-
- "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
-
- "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
-
- "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
-
- "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="],
-
- "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
-
- "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
-
- "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
-
- "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
-
- "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
-
- "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="],
-
- "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="],
-
- "expo": ["expo@55.0.10-canary-20260328-2049187", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "55.0.20-canary-20260328-2049187", "@expo/config": "55.0.12-canary-20260328-2049187", "@expo/config-plugins": "55.0.8-canary-20260328-2049187", "@expo/devtools": "55.0.3-canary-20260328-2049187", "@expo/fingerprint": "0.16.7-canary-20260328-2049187", "@expo/local-build-cache-provider": "55.0.8-canary-20260328-2049187", "@expo/log-box": "55.0.9-canary-20260328-2049187", "@expo/metro": "~54.2.0", "@expo/metro-config": "55.0.12-canary-20260328-2049187", "@expo/vector-icons": "^15.0.2", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "55.0.14-canary-20260328-2049187", "expo-asset": "55.0.11-canary-20260328-2049187", "expo-constants": "55.0.10-canary-20260328-2049187", "expo-file-system": "55.0.13-canary-20260328-2049187", "expo-font": "55.0.5-canary-20260328-2049187", "expo-keep-awake": "55.0.5-canary-20260328-2049187", "expo-modules-autolinking": "55.0.13-canary-20260328-2049187", "expo-modules-core": "55.0.19-canary-20260328-2049187", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.1" }, "peerDependencies": { "@expo/dom-webview": "55.0.4-canary-20260328-2049187", "@expo/metro-runtime": "55.0.8-canary-20260328-2049187", "react": "*", "react-native": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/dom-webview", "@expo/metro-runtime", "react-native-webview"], "bin": { "expo": "bin/cli", "expo-modules-autolinking": "bin/autolinking", "fingerprint": "bin/fingerprint" } }, "sha512-98gWHe8BWedTDs3f4pK7qjEz58rrJhyByOVPWhdKbmEKmU5xNCS/XUxXV5t2QiLDybR7EWesrOspWiHFSV5eLw=="],
-
- "expo-application": ["expo-application@55.0.11-canary-20260328-2049187", "", { "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187" } }, "sha512-XrWghJefOb3fTdxK0B3RKuz9l31nZn2SIPqn2qhYx4kOPXa/CytaUvH5wG5gHJ2ZGtonk4JPmw+a69OiDj7MfQ=="],
-
- "expo-asset": ["expo-asset@55.0.11-canary-20260328-2049187", "", { "dependencies": { "@expo/image-utils": "0.8.13-canary-20260328-2049187", "expo-constants": "55.0.10-canary-20260328-2049187" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-HxNLQFWAs/NNh1gfHjVFH926bozPtv5vEeMiGKhh6unysaW3B85s9aoogram3Y9S8Wk3vcgrkS01/W2DQIE7Fw=="],
-
- "expo-constants": ["expo-constants@55.0.10-canary-20260328-2049187", "", { "dependencies": { "@expo/config": "55.0.12-canary-20260328-2049187", "@expo/env": "2.1.2-canary-20260328-2049187" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react-native": "*" } }, "sha512-PzwmIKGUME5eLi/D+rkD2eL5Ce8Y7ZF7pdMsZpnjky0IvBiJwcJa+/muM8/YIsLjmO2VbndWUGhdWde3iz4pQQ=="],
-
- "expo-device": ["expo-device@55.0.11-canary-20260328-2049187", "", { "dependencies": { "ua-parser-js": "^0.7.33" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187" } }, "sha512-UoJ7HztgEc8AsBVB+tnt6vIMPbN/8YClgeCEflwqJjAJ2KaAMfV+RGrjo32SyhV2/LeG+I3gTTEC0M/oSNsfLA=="],
-
- "expo-file-system": ["expo-file-system@55.0.13-canary-20260328-2049187", "", { "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react-native": "*" } }, "sha512-DOFYy9AvSFVeUlGfArwDaBujThpqK9w2NEpdCSK3sVSfvdedJpAT9jerU4c7Yufw+EcGWqqOHn8iqPoN7Ft4cQ=="],
-
- "expo-font": ["expo-font@55.0.5-canary-20260328-2049187", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-y460Cm6gSuh1ytQPMwt/9RtnIHIwQNw6oHceXbQ2G4lw/+QnVX32/rRkNmJKvS2lnbXwJHNAERKLzxga+Cn6gg=="],
-
- "expo-glass-effect": ["expo-glass-effect@55.0.9-canary-20260328-2049187", "", { "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-xCkKnm7AsmcU38tJKUH29XzYY1UunObcSUn6x4Nk6tawUXryfeE6p7+GsdT7W+bjutD7AFZHMn4Hm3eLh3FDPA=="],
-
- "expo-image": ["expo-image@55.0.7-canary-20260328-2049187", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-eZ4aJ08cmhHiWvPyfztJX/cJhLZT3MFUiwMDij33+RRl08YDZ0QlniLTYgBeAknNfiGxw+kM0CQ0eORf8eGHRg=="],
-
- "expo-keep-awake": ["expo-keep-awake@55.0.5-canary-20260328-2049187", "", { "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*" } }, "sha512-kFvj0NHBYGAl+Au3qv0pLLDsy/eefLI/dTXDIphnQu1KR6YVCp7qpXs0d7CH7Ird1Zd3sqOiaHKDSNmEeb2rGQ=="],
-
- "expo-linking": ["expo-linking@55.0.10-canary-20260328-2049187", "", { "dependencies": { "expo-constants": "55.0.10-canary-20260328-2049187", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-ONFRYb8Qw+vPRyml/qvFUeWtxb1MwGDJfNbunxfeRSxOmepoXe61BK+f0ViT/Q69jkmFawfR81LOn1j05ujlnw=="],
-
- "expo-localization": ["expo-localization@55.0.10-canary-20260328-2049187", "", { "dependencies": { "rtl-detect": "^1.0.2" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*" } }, "sha512-4ZxHWAssJzQzkzcEGNzSxB/BpoN5IWE/FvMbJExByYqh2/x7EVJqamT8lNvFmfTdwrVCwGX6AhzMB6MGmf38Yg=="],
-
- "expo-modules-autolinking": ["expo-modules-autolinking@55.0.13-canary-20260328-2049187", "", { "dependencies": { "@expo/require-utils": "55.0.4-canary-20260328-2049187", "@expo/spawn-async": "^1.7.2", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-u+v56qUCe3pRdA71OTJE5YS4KCpuD4Cn/GuJFAszdNnP9WEpkl3lzoYKBktjIalx7X/rvJ+18Pa4AQwA2IKrzA=="],
-
- "expo-modules-core": ["expo-modules-core@55.0.19-canary-20260328-2049187", "", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-CCEwUfQSyJYPXpghqLUOymITO1AZMnpTEP+Ft+051K2T6be2r1jG0o77tpryWdzR+hR2MmYOMvizz8j6P9xTDA=="],
-
- "expo-notifications": ["expo-notifications@55.0.15-canary-20260328-2049187", "", { "dependencies": { "@expo/image-utils": "0.8.13-canary-20260328-2049187", "abort-controller": "^3.0.0", "badgin": "^1.1.5", "expo-application": "55.0.11-canary-20260328-2049187", "expo-constants": "55.0.10-canary-20260328-2049187" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-Z6eQ5HPs2q71O+tt+dmINigAT+WxB2pCp/EAmvhtIPVYhopSuxJDmPGd+sMjeUe/npiwJqbr2agDLPcH8NxsHA=="],
-
- "expo-router": ["expo-router@55.0.9-canary-20260328-2049187", "", { "dependencies": { "@expo/metro-runtime": "55.0.8-canary-20260328-2049187", "@expo/schema-utils": "55.0.3-canary-20260328-2049187", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-navigation/bottom-tabs": "^7.15.5", "@react-navigation/native": "^7.1.33", "@react-navigation/native-stack": "^7.14.5", "client-only": "^0.0.1", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "55.0.9-canary-20260328-2049187", "expo-image": "55.0.7-canary-20260328-2049187", "expo-server": "55.0.7-canary-20260328-2049187", "expo-symbols": "55.0.6-canary-20260328-2049187", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-native-is-edge-to-edge": "^1.2.1", "semver": "~7.6.3", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "use-latest-callback": "^0.2.1", "vaul": "^1.1.2" }, "peerDependencies": { "@expo/log-box": "55.0.9-canary-20260328-2049187", "@react-navigation/drawer": "^7.9.4", "@testing-library/react-native": ">= 13.2.0", "expo": "55.0.10-canary-20260328-2049187", "expo-constants": "55.0.10-canary-20260328-2049187", "expo-linking": "55.0.10-canary-20260328-2049187", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-screens": "*", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@react-navigation/drawer", "@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-b4N6WfC8jsmQTVB3bMsBpdX1jO4JyAzNO9dGvOYS5u1dcaqpws43hLN4WKSqKQueCSmxCrTd4EHcgmAgTY7z1Q=="],
-
- "expo-server": ["expo-server@55.0.7-canary-20260328-2049187", "", {}, "sha512-pOcQ2/eAj7iDQivh97OQSkDyboj+W/tGJ+Ie13C/HKaAv//6NnquzsVbMOwDO498tVjvYvSdriMqrMj+XfoWmA=="],
-
- "expo-splash-screen": ["expo-splash-screen@55.0.14-canary-20260328-2049187", "", { "dependencies": { "@expo/prebuild-config": "55.0.12-canary-20260328-2049187" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187" } }, "sha512-p3XlISAt4lUZDD28J8ctYVw0ThD3Nze3XD1I2pr8HrUb90io43xT7Yj0cJaqHcax93dYLxUrNh+PCC122dCL4Q=="],
-
- "expo-sqlite": ["expo-sqlite@55.0.12-canary-20260328-2049187", "", { "dependencies": { "await-lock": "^2.2.2" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-pzcd8T1A1a/SKDkFrUXQP/VQXdmsSRpE1XJwFps6Jt3+7DT1kQlFuQEp1xx7hqko/Qhjo7i1X0s67b1pt0lYWg=="],
-
- "expo-status-bar": ["expo-status-bar@55.0.5-canary-20260328-2049187", "", { "dependencies": { "react-native-is-edge-to-edge": "^1.2.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-jarQoeI181A5okZq+Es/arDKqaZKm4eCim/d9tHdngh8Oy0kBfFMPNzhvx6SPqp9iNTBtwrg07bBz0Fxh0wlvw=="],
-
- "expo-symbols": ["expo-symbols@55.0.6-canary-20260328-2049187", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "expo-font": "55.0.5-canary-20260328-2049187", "react": "*", "react-native": "*" } }, "sha512-5n1IvkDVY/HoWwmxVGEI71L/YSsQ4MyN+0/OTxO+rXC7R65J2WzcgP5TQAM1CI00NA4D8oZ+xbwKEC2WyYdgig=="],
-
- "expo-system-ui": ["expo-system-ui@55.0.12-canary-20260328-2049187", "", { "dependencies": { "@react-native/normalize-colors": "0.83.4", "debug": "^4.3.2" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-jIXBAOwkc3yax4Q0XQycOceLXg3GFHOSkUzT9Oppyn3/qnjcGuHePuFNR/Sn3udKGPR4suo3zDsF6oqiFxHl3w=="],
-
- "expo-task-manager": ["expo-task-manager@55.0.11-canary-20260328-2049187", "", { "dependencies": { "unimodules-app-loader": "55.0.3-canary-20260328-2049187" }, "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react-native": "*" } }, "sha512-eneHR2t2WLWeRKfFuY2UDREh9OSryVDGWXy2V+IBlAKdOEQBQ1FlJESbLrYCEkhu6qiLUYMd61e0tgn3fbRhWQ=="],
-
- "expo-web-browser": ["expo-web-browser@55.0.11-canary-20260328-2049187", "", { "peerDependencies": { "expo": "55.0.10-canary-20260328-2049187", "react-native": "*" } }, "sha512-eLBGDO15oYed5EuKk6yzCyQKYO+w5MC7tk2AaniO41pUuu0j0621ic5Lb2bOLCLGHtnMl/HHJELnO1qkrxH0Eg=="],
-
- "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
-
- "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
-
- "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
-
- "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
-
- "fast-xml-builder": ["fast-xml-builder@1.1.4", "", { "dependencies": { "path-expression-matcher": "^1.1.3" } }, "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg=="],
-
- "fast-xml-parser": ["fast-xml-parser@5.5.9", "", { "dependencies": { "fast-xml-builder": "^1.1.4", "path-expression-matcher": "^1.2.0", "strnum": "^2.2.2" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-jldvxr1MC6rtiZKgrFnDSvT8xuH+eJqxqOBThUVjYrxssYTo1avZLGql5l0a0BAERR01CadYzZ83kVEkbyDg+g=="],
-
- "fb-dotslash": ["fb-dotslash@0.5.8", "", { "bin": { "dotslash": "bin/dotslash" } }, "sha512-XHYLKk9J4BupDxi9bSEhkfss0m+Vr9ChTrjhf9l2iw3jB5C7BnY4GVPoMcqbrTutsKJso6yj2nAB6BI/F2oZaA=="],
-
- "fb-watchman": ["fb-watchman@2.0.2", "", { "dependencies": { "bser": "2.1.1" } }, "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA=="],
-
- "fbjs": ["fbjs@3.0.5", "", { "dependencies": { "cross-fetch": "^3.1.5", "fbjs-css-vars": "^1.0.0", "loose-envify": "^1.0.0", "object-assign": "^4.1.0", "promise": "^7.1.1", "setimmediate": "^1.0.5", "ua-parser-js": "^1.0.35" } }, "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg=="],
-
- "fbjs-css-vars": ["fbjs-css-vars@1.0.2", "", {}, "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ=="],
-
- "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
-
- "fetch-nodeshim": ["fetch-nodeshim@0.4.10", "", {}, "sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w=="],
-
- "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
-
- "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
-
- "filter-obj": ["filter-obj@1.1.0", "", {}, "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ=="],
-
- "finalhandler": ["finalhandler@1.1.2", "", { "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", "parseurl": "~1.3.3", "statuses": "~1.5.0", "unpipe": "~1.0.0" } }, "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA=="],
-
- "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
-
- "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
-
- "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
-
- "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="],
-
- "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
-
- "fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="],
-
- "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
-
- "form-data": ["form-data@4.0.5", "", { "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" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
-
- "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="],
-
- "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="],
-
- "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
-
- "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
-
- "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
-
- "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
-
- "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
-
- "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
-
- "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
-
- "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
-
- "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="],
-
- "get-package-type": ["get-package-type@0.1.0", "", {}, "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q=="],
-
- "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
-
- "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
-
- "get-tsconfig": ["get-tsconfig@4.13.7", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q=="],
-
- "getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="],
-
- "glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
-
- "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
-
- "globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="],
-
- "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
-
- "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
-
- "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
-
- "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
-
- "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
-
- "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
-
- "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
-
- "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
-
- "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
-
- "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
-
- "hermes-compiler": ["hermes-compiler@0.14.1", "", {}, "sha512-+RPPQlayoZ9n6/KXKt5SFILWXCGJ/LV5d24L5smXrvTDrPS4L6dSctPczXauuvzFP3QEJbD1YO7Z3Ra4a+4IhA=="],
-
- "hermes-estree": ["hermes-estree@0.32.1", "", {}, "sha512-ne5hkuDxheNBAikDjqvCZCwihnz0vVu9YsBzAEO1puiyFR4F1+PAz/SiPHSsNTuOveCYGRMX8Xbx4LOubeC0Qg=="],
-
- "hermes-parser": ["hermes-parser@0.32.1", "", { "dependencies": { "hermes-estree": "0.32.1" } }, "sha512-175dz634X/W5AiwrpLdoMl/MOb17poLHyIqgyExlE8D9zQ1OPnoORnGMB5ltRKnpvQzBjMYvT2rN/sHeIfZW5Q=="],
-
- "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
-
- "hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="],
-
- "htmlparser2": ["htmlparser2@7.2.0", "", { "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.2", "domutils": "^2.8.0", "entities": "^3.0.1" } }, "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog=="],
-
- "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
-
- "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
-
- "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="],
-
- "idb": ["idb@8.0.3", "", {}, "sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg=="],
-
- "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
-
- "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
-
- "image-size": ["image-size@1.2.1", "", { "dependencies": { "queue": "6.0.2" }, "bin": { "image-size": "bin/image-size.js" } }, "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw=="],
-
- "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
-
- "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
-
- "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
-
- "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
-
- "inline-style-prefixer": ["inline-style-prefixer@7.0.1", "", { "dependencies": { "css-in-js-utils": "^3.1.0" } }, "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw=="],
-
- "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
-
- "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
-
- "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
-
- "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
-
- "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
-
- "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
-
- "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
-
- "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="],
-
- "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
-
- "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
-
- "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
-
- "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
-
- "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="],
-
- "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
-
- "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
-
- "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
-
- "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
-
- "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
-
- "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
-
- "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
-
- "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
-
- "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
-
- "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
-
- "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
-
- "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
-
- "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
-
- "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
-
- "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
-
- "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
-
- "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
-
- "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
-
- "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="],
-
- "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
-
- "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
-
- "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
-
- "istanbul-lib-instrument": ["istanbul-lib-instrument@5.2.1", "", { "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" } }, "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg=="],
-
- "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
-
- "jest-environment-node": ["jest-environment-node@29.7.0", "", { "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" } }, "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw=="],
-
- "jest-get-type": ["jest-get-type@29.6.3", "", {}, "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw=="],
-
- "jest-haste-map": ["jest-haste-map@29.7.0", "", { "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" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA=="],
-
- "jest-message-util": ["jest-message-util@29.7.0", "", { "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" } }, "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w=="],
-
- "jest-mock": ["jest-mock@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "jest-util": "^29.7.0" } }, "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw=="],
-
- "jest-regex-util": ["jest-regex-util@29.6.3", "", {}, "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg=="],
-
- "jest-util": ["jest-util@29.7.0", "", { "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" } }, "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA=="],
-
- "jest-validate": ["jest-validate@29.7.0", "", { "dependencies": { "@jest/types": "^29.6.3", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.6.3", "leven": "^3.1.0", "pretty-format": "^29.7.0" } }, "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw=="],
-
- "jest-worker": ["jest-worker@29.7.0", "", { "dependencies": { "@types/node": "*", "jest-util": "^29.7.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw=="],
-
- "jimp-compact": ["jimp-compact@0.16.1", "", {}, "sha512-dZ6Ra7u1G8c4Letq/B5EzAxj4tLFHL+cGtdpR+PVm4yzPDj+lCk+AbivWt1eOM+ikzkowtyV7qSqX6qr3t71Ww=="],
-
- "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
-
- "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
-
- "jsc-safe-url": ["jsc-safe-url@0.2.4", "", {}, "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q=="],
-
- "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
-
- "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
-
- "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
-
- "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
-
- "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
-
- "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
-
- "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
-
- "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="],
-
- "lan-network": ["lan-network@0.2.0", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-EZgbsXMrGS+oK+Ta12mCjzBFse+SIewGdwrSTr5g+MSymnjpox2x05ceI20PQejJOFvOgzcXrfDk/SdY7dSCtw=="],
-
- "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
-
- "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
-
- "lighthouse-logger": ["lighthouse-logger@1.4.2", "", { "dependencies": { "debug": "^2.6.9", "marky": "^1.2.2" } }, "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g=="],
-
- "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
-
- "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
-
- "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
-
- "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
-
- "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
-
- "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
-
- "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
-
- "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
-
- "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
-
- "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
-
- "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
-
- "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
-
- "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
-
- "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
-
- "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
-
- "lodash.throttle": ["lodash.throttle@4.1.1", "", {}, "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="],
-
- "log-symbols": ["log-symbols@2.2.0", "", { "dependencies": { "chalk": "^2.0.1" } }, "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg=="],
-
- "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
-
- "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
-
- "makeerror": ["makeerror@1.0.12", "", { "dependencies": { "tmpl": "1.0.5" } }, "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg=="],
-
- "marky": ["marky@1.3.0", "", {}, "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ=="],
-
- "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
-
- "memoize-one": ["memoize-one@5.2.1", "", {}, "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q=="],
-
- "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
-
- "metro": ["metro@0.83.3", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^4.4.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.32.0", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-config": "0.83.3", "metro-core": "0.83.3", "metro-file-map": "0.83.3", "metro-resolver": "0.83.3", "metro-runtime": "0.83.3", "metro-source-map": "0.83.3", "metro-symbolicate": "0.83.3", "metro-transform-plugins": "0.83.3", "metro-transform-worker": "0.83.3", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-+rP+/GieOzkt97hSJ0MrPOuAH/jpaS21ZDvL9DJ35QYRDlQcwzcvUlGUf79AnQxq/2NPiS/AULhhM4TKutIt8Q=="],
-
- "metro-babel-transformer": ["metro-babel-transformer@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.32.0", "nullthrows": "^1.1.1" } }, "sha512-1vxlvj2yY24ES1O5RsSIvg4a4WeL7PFXgKOHvXTXiW0deLvQr28ExXj6LjwCCDZ4YZLhq6HddLpZnX4dEdSq5g=="],
-
- "metro-cache": ["metro-cache@0.83.3", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "https-proxy-agent": "^7.0.5", "metro-core": "0.83.3" } }, "sha512-3jo65X515mQJvKqK3vWRblxDEcgY55Sk3w4xa6LlfEXgQ9g1WgMh9m4qVZVwgcHoLy0a2HENTPCCX4Pk6s8c8Q=="],
-
- "metro-cache-key": ["metro-cache-key@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-59ZO049jKzSmvBmG/B5bZ6/dztP0ilp0o988nc6dpaDsU05Cl1c/lRf+yx8m9WW/JVgbmfO5MziBU559XjI5Zw=="],
-
- "metro-config": ["metro-config@0.83.3", "", { "dependencies": { "connect": "^3.6.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.83.3", "metro-cache": "0.83.3", "metro-core": "0.83.3", "metro-runtime": "0.83.3", "yaml": "^2.6.1" } }, "sha512-mTel7ipT0yNjKILIan04bkJkuCzUUkm2SeEaTads8VfEecCh+ltXchdq6DovXJqzQAXuR2P9cxZB47Lg4klriA=="],
-
- "metro-core": ["metro-core@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.83.3" } }, "sha512-M+X59lm7oBmJZamc96usuF1kusd5YimqG/q97g4Ac7slnJ3YiGglW5CsOlicTR5EWf8MQFxxjDoB6ytTqRe8Hw=="],
-
- "metro-file-map": ["metro-file-map@0.83.3", "", { "dependencies": { "debug": "^4.4.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-jg5AcyE0Q9Xbbu/4NAwwZkmQn7doJCKGW0SLeSJmzNB9Z24jBe0AL2PHNMy4eu0JiKtNWHz9IiONGZWq7hjVTA=="],
-
- "metro-minify-terser": ["metro-minify-terser@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-O2BmfWj6FSfzBLrNCXt/rr2VYZdX5i6444QJU0fFoc7Ljg+Q+iqebwE3K0eTvkI6TRjELsXk1cjU+fXwAR4OjQ=="],
-
- "metro-resolver": ["metro-resolver@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-0js+zwI5flFxb1ktmR///bxHYg7OLpRpWZlBBruYG8OKYxeMP7SV0xQ/o/hUelrEMdK4LJzqVtHAhBm25LVfAQ=="],
-
- "metro-runtime": ["metro-runtime@0.83.3", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-JHCJb9ebr9rfJ+LcssFYA2x1qPYuSD/bbePupIGhpMrsla7RCwC/VL3yJ9cSU+nUhU4c9Ixxy8tBta+JbDeZWw=="],
-
- "metro-source-map": ["metro-source-map@0.83.3", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.83.3", "nullthrows": "^1.1.1", "ob1": "0.83.3", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-xkC3qwUBh2psVZgVavo8+r2C9Igkk3DibiOXSAht1aYRRcztEZNFtAMtfSB7sdO2iFMx2Mlyu++cBxz/fhdzQg=="],
-
- "metro-symbolicate": ["metro-symbolicate@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.83.3", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-F/YChgKd6KbFK3eUR5HdUsfBqVsanf5lNTwFd4Ca7uuxnHgBC3kR/Hba/RGkenR3pZaGNp5Bu9ZqqP52Wyhomw=="],
-
- "metro-transform-plugins": ["metro-transform-plugins@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-eRGoKJU6jmqOakBMH5kUB7VitEWiNrDzBHpYbkBXW7C5fUGeOd2CyqrosEzbMK5VMiZYyOcNFEphvxk3OXey2A=="],
-
- "metro-transform-worker": ["metro-transform-worker@0.83.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.83.3", "metro-babel-transformer": "0.83.3", "metro-cache": "0.83.3", "metro-cache-key": "0.83.3", "metro-minify-terser": "0.83.3", "metro-source-map": "0.83.3", "metro-transform-plugins": "0.83.3", "nullthrows": "^1.1.1" } }, "sha512-Ztekew9t/gOIMZX1tvJOgX7KlSLL5kWykl0Iwu2cL2vKMKVALRl1hysyhUw0vjpAvLFx+Kfq9VLjnHIkW32fPA=="],
-
- "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
-
- "mime": ["mime@1.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="],
-
- "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
-
- "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
-
- "mimic-fn": ["mimic-fn@1.2.0", "", {}, "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="],
-
- "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
-
- "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
-
- "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
-
- "mkdirp": ["mkdirp@1.0.4", "", { "bin": { "mkdirp": "bin/cmd.js" } }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="],
-
- "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
-
- "multitars": ["multitars@0.2.4", "", {}, "sha512-XgLbg1HHchFauMCQPRwMj6MSyDd5koPlTA1hM3rUFkeXzGpjU/I9fP3to7yrObE9jcN8ChIOQGrM0tV0kUZaKg=="],
-
- "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
-
- "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="],
-
- "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
-
- "negotiator": ["negotiator@0.6.3", "", {}, "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="],
-
- "node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="],
-
- "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
-
- "node-forge": ["node-forge@1.4.0", "", {}, "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ=="],
-
- "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="],
-
- "node-releases": ["node-releases@2.0.36", "", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="],
-
- "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
-
- "npm-package-arg": ["npm-package-arg@11.0.3", "", { "dependencies": { "hosted-git-info": "^7.0.0", "proc-log": "^4.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^5.0.0" } }, "sha512-sHGJy8sOC1YraBywpzQlIKBE4pBbGbiF95U6Auspzyem956E0+FtDtsx1ZxlOJkQCZ1AFXAY/yuvtFYrOxF+Bw=="],
-
- "nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="],
-
- "ob1": ["ob1@0.83.3", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA=="],
-
- "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
-
- "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
-
- "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
-
- "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
-
- "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="],
-
- "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
-
- "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="],
-
- "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
-
- "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
-
- "on-headers": ["on-headers@1.1.0", "", {}, "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A=="],
-
- "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
-
- "onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="],
-
- "open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="],
-
- "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
-
- "ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="],
-
- "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
-
- "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
-
- "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
-
- "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
-
- "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
-
- "parse-png": ["parse-png@2.1.0", "", { "dependencies": { "pngjs": "^3.3.0" } }, "sha512-Nt/a5SfCLiTnQAjx3fHlqp8hRgTL3z7kTQZzvIMS9uCAepnCyjpdEc6M/sz69WqMBdaDBw9sF1F1UaHROYzGkQ=="],
-
- "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
-
- "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
-
- "path-expression-matcher": ["path-expression-matcher@1.2.0", "", {}, "sha512-DwmPWeFn+tq7TiyJ2CxezCAirXjFxvaiD03npak3cRjlP9+OjTmSy1EpIrEbh+l6JgUundniloMLDQ/6VTdhLQ=="],
-
- "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
-
- "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
-
- "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
-
- "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
-
- "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
-
- "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
-
- "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
-
- "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="],
-
- "pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="],
-
- "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
-
- "postcss": ["postcss@8.4.49", "", { "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA=="],
-
- "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
-
- "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
-
- "pretty-format": ["pretty-format@29.7.0", "", { "dependencies": { "@jest/schemas": "^29.6.3", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" } }, "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ=="],
-
- "proc-log": ["proc-log@4.2.0", "", {}, "sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA=="],
-
- "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
-
- "promise": ["promise@8.3.0", "", { "dependencies": { "asap": "~2.0.6" } }, "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg=="],
-
- "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="],
-
- "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
-
- "proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="],
-
- "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
-
- "query-string": ["query-string@7.1.3", "", { "dependencies": { "decode-uri-component": "^0.2.2", "filter-obj": "^1.1.0", "split-on-first": "^1.0.0", "strict-uri-encode": "^2.0.0" } }, "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg=="],
-
- "queue": ["queue@6.0.2", "", { "dependencies": { "inherits": "~2.0.3" } }, "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA=="],
-
- "ramda": ["ramda@0.27.2", "", {}, "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA=="],
-
- "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
-
- "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="],
-
- "react-devtools-core": ["react-devtools-core@6.1.5", "", { "dependencies": { "shell-quote": "^1.6.1", "ws": "^7" } }, "sha512-ePrwPfxAnB+7hgnEr8vpKxL9cmnp7F322t8oqcPshbIQQhDKgFDW4tjhF2wjVbdXF9O/nyuy3sQWd9JGpiLPvA=="],
-
- "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="],
-
- "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="],
-
- "react-freeze": ["react-freeze@1.0.4", "", { "peerDependencies": { "react": ">=17.0.0" } }, "sha512-r4F0Sec0BLxWicc7HEyo2x3/2icUTrRmDjaaRyzzn+7aDyFZliszMDOgLVwSnQnYENOlL1o569Ze2HZefk8clA=="],
-
- "react-is": ["react-is@19.2.4", "", {}, "sha512-W+EWGn2v0ApPKgKKCy/7s7WHXkboGcsrXE+2joLyVxkbyVQfO3MUEaUQDHoSmb8TFFrSKYa9mw64WZHNHSDzYA=="],
-
- "react-native": ["react-native@0.83.4", "", { "dependencies": { "@jest/create-cache-key-function": "^29.7.0", "@react-native/assets-registry": "0.83.4", "@react-native/codegen": "0.83.4", "@react-native/community-cli-plugin": "0.83.4", "@react-native/gradle-plugin": "0.83.4", "@react-native/js-polyfills": "0.83.4", "@react-native/normalize-colors": "0.83.4", "@react-native/virtualized-lists": "0.83.4", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.32.0", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "hermes-compiler": "0.14.1", "invariant": "^2.2.4", "jest-environment-node": "^29.7.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.83.3", "metro-source-map": "^0.83.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^19.1.1", "react": "^19.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-H5Wco3UJyY6zZsjoBayY8RM9uiAEQ3FeG4G2NAt+lr9DO43QeqPlVe9xxxYEukMkEmeIhNjR70F6bhXuWArOMQ=="],
-
- "react-native-gesture-handler": ["react-native-gesture-handler@2.30.1", "", { "dependencies": { "@egjs/hammerjs": "^2.0.17", "hoist-non-react-statics": "^3.3.0", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-xIUBDo5ktmJs++0fZlavQNvDEE4PsihWhSeJsJtoz4Q6p0MiTM9TgrTgfEgzRR36qGPytFoeq+ShLrVwGdpUdA=="],
-
- "react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.3.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-NIXU/iT5+ORyCc7p0z2nnlkouYKX425vuU1OEm6bMMtWWR9yvb+Xg5AZmImTKoF9abxCPqrKC3rOZsKzUYgYZA=="],
-
- "react-native-reanimated": ["react-native-reanimated@4.2.1", "", { "dependencies": { "react-native-is-edge-to-edge": "1.2.1", "semver": "7.7.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": ">=0.7.0" } }, "sha512-/NcHnZMyOvsD/wYXug/YqSKw90P9edN0kEPL5lP4PFf1aQ4F1V7MKe/E0tvfkXKIajy3Qocp5EiEnlcrK/+BZg=="],
-
- "react-native-render-html": ["react-native-render-html@6.3.4", "", { "dependencies": { "@jsamr/counter-style": "^2.0.1", "@jsamr/react-native-li": "^2.3.0", "@native-html/transient-render-engine": "11.2.3", "@types/ramda": "^0.27.40", "@types/urijs": "^1.19.15", "prop-types": "^15.5.7", "ramda": "^0.27.2", "stringify-entities": "^3.1.0", "urijs": "^1.19.6" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-H2jSMzZjidE+Wo3qCWPUMU1nm98Vs2SGCvQCz/i6xf0P3Y9uVtG/b0sDbG/cYFir2mSYBYCIlS1Dv0WC1LjYig=="],
-
- "react-native-safe-area-context": ["react-native-safe-area-context@5.6.2", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-4XGqMNj5qjUTYywJqpdWZ9IG8jgkS3h06sfVjfw5yZQZfWnRFXczi0GnYyFyCc2EBps/qFmoCH8fez//WumdVg=="],
-
- "react-native-screens": ["react-native-screens@4.23.0", "", { "dependencies": { "react-freeze": "^1.0.0", "warn-once": "^0.1.0" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-XhO3aK0UeLpBn4kLecd+J+EDeRRJlI/Ro9Fze06vo1q163VeYtzfU9QS09/VyDFMWR1qxDC1iazCArTPSFFiPw=="],
-
- "react-native-web": ["react-native-web@0.21.2", "", { "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" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="],
-
- "react-native-worklets": ["react-native-worklets@0.7.2", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "7.27.1", "@babel/plugin-transform-class-properties": "7.27.1", "@babel/plugin-transform-classes": "7.28.4", "@babel/plugin-transform-nullish-coalescing-operator": "7.27.1", "@babel/plugin-transform-optional-chaining": "7.27.1", "@babel/plugin-transform-shorthand-properties": "7.27.1", "@babel/plugin-transform-template-literals": "7.27.1", "@babel/plugin-transform-unicode-regex": "7.27.1", "@babel/preset-typescript": "7.27.1", "convert-source-map": "2.0.0", "semver": "7.7.3" }, "peerDependencies": { "@babel/core": "*", "react": "*", "react-native": "*" } }, "sha512-DuLu1kMV/Uyl9pQHp3hehAlThoLw7Yk2FwRTpzASOmI+cd4845FWn3m2bk9MnjUw8FBRIyhwLqYm2AJaXDXsog=="],
-
- "react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
-
- "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "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" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="],
-
- "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="],
-
- "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="],
-
- "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
-
- "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "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" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
-
- "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="],
-
- "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.2", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g=="],
-
- "regenerator-runtime": ["regenerator-runtime@0.13.11", "", {}, "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="],
-
- "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "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" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
-
- "regexpu-core": ["regexpu-core@6.4.0", "", { "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" } }, "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA=="],
-
- "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="],
-
- "regjsparser": ["regjsparser@0.13.0", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q=="],
-
- "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
-
- "resolve": ["resolve@2.0.0-next.6", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA=="],
-
- "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
-
- "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
-
- "resolve-workspace-root": ["resolve-workspace-root@2.0.1", "", {}, "sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w=="],
-
- "restore-cursor": ["restore-cursor@2.0.0", "", { "dependencies": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" } }, "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q=="],
-
- "rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
-
- "rtl-detect": ["rtl-detect@1.1.2", "", {}, "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ=="],
-
- "safe-array-concat": ["safe-array-concat@1.1.3", "", { "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" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
-
- "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
-
- "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
-
- "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
-
- "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="],
-
- "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
-
- "semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
-
- "send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="],
-
- "serialize-error": ["serialize-error@2.1.0", "", {}, "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw=="],
-
- "serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="],
-
- "server-only": ["server-only@0.0.1", "", {}, "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA=="],
-
- "set-function-length": ["set-function-length@1.2.2", "", { "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" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
-
- "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
-
- "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
-
- "setimmediate": ["setimmediate@1.0.5", "", {}, "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="],
-
- "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
-
- "sf-symbols-typescript": ["sf-symbols-typescript@2.2.0", "", {}, "sha512-TPbeg0b7ylrswdGCji8FRGFAKuqbpQlLbL8SOle3j1iHSs5Ob5mhvMAxWN2UItOjgALAB5Zp3fmMfj8mbWvXKw=="],
-
- "shallowequal": ["shallowequal@1.1.0", "", {}, "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="],
-
- "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
-
- "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
-
- "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
-
- "side-channel": ["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" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
-
- "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
-
- "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
-
- "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "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" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
-
- "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
-
- "simple-plist": ["simple-plist@1.3.1", "", { "dependencies": { "bplist-creator": "0.1.0", "bplist-parser": "0.3.1", "plist": "^3.0.5" } }, "sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw=="],
-
- "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="],
-
- "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
-
- "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
-
- "slugify": ["slugify@1.6.8", "", {}, "sha512-HVk9X1E0gz3mSpoi60h/saazLKXKaZThMLU3u/aNwoYn8/xQyX2MGxL0ui2eaokkD7tF+Zo+cKTHUbe1mmmGzA=="],
-
- "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
-
- "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
-
- "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="],
-
- "split-on-first": ["split-on-first@1.1.0", "", {}, "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="],
-
- "sprintf-js": ["sprintf-js@1.0.3", "", {}, "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="],
-
- "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
-
- "stack-utils": ["stack-utils@2.0.6", "", { "dependencies": { "escape-string-regexp": "^2.0.0" } }, "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ=="],
-
- "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="],
-
- "stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="],
-
- "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
-
- "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
-
- "stream-browserify": ["stream-browserify@3.0.0", "", { "dependencies": { "inherits": "~2.0.4", "readable-stream": "^3.5.0" } }, "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA=="],
-
- "stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="],
-
- "strict-uri-encode": ["strict-uri-encode@2.0.0", "", {}, "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ=="],
-
- "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
-
- "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "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" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="],
-
- "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
-
- "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "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" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
-
- "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
-
- "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
-
- "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
-
- "stringify-entities": ["stringify-entities@3.1.0", "", { "dependencies": { "character-entities-html4": "^1.0.0", "character-entities-legacy": "^1.0.0", "xtend": "^4.0.0" } }, "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg=="],
-
- "strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="],
-
- "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
-
- "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
-
- "strnum": ["strnum@2.2.2", "", {}, "sha512-DnR90I+jtXNSTXWdwrEy9FakW7UX+qUZg28gj5fk2vxxl7uS/3bpI4fjFYVmdK9etptYBPNkpahuQnEwhwECqA=="],
-
- "structured-headers": ["structured-headers@0.4.1", "", {}, "sha512-0MP/Cxx5SzeeZ10p/bZI0S6MpgD+yxAhi1BOQ34jgnMXsCq3j1t6tQnZu+KdlL7dvJTLT3g9xN8tl10TqgFMcg=="],
-
- "styleq": ["styleq@0.1.3", "", {}, "sha512-3ZUifmCDCQanjeej1f6kyl/BeP/Vae5EYkQ9iJfUm/QwZvlgnZzyflqAsAWYURdtea8Vkvswu2GrC57h3qffcA=="],
-
- "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
-
- "supports-hyperlinks": ["supports-hyperlinks@2.3.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA=="],
-
- "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
-
- "terminal-link": ["terminal-link@2.1.1", "", { "dependencies": { "ansi-escapes": "^4.2.1", "supports-hyperlinks": "^2.0.0" } }, "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ=="],
-
- "terser": ["terser@5.46.1", "", { "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" } }, "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ=="],
-
- "test-exclude": ["test-exclude@6.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" } }, "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w=="],
-
- "throat": ["throat@5.0.0", "", {}, "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="],
-
- "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
-
- "tmpl": ["tmpl@1.0.5", "", {}, "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="],
-
- "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
-
- "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
-
- "toqr": ["toqr@0.1.1", "", {}, "sha512-FWAPzCIHZHnrE/5/w9MPk0kK25hSQSH2IKhYh9PyjS3SG/+IEMvlwIHbhz+oF7xl54I+ueZlVnMjyzdSwLmAwA=="],
-
- "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
-
- "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
-
- "ts-toolbelt": ["ts-toolbelt@6.15.5", "", {}, "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A=="],
-
- "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
-
- "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
-
- "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
-
- "type-detect": ["type-detect@4.0.8", "", {}, "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="],
-
- "type-fest": ["type-fest@0.7.1", "", {}, "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg=="],
-
- "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
-
- "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
-
- "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
-
- "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
-
- "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
-
- "ua-parser-js": ["ua-parser-js@0.7.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg=="],
-
- "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
-
- "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
-
- "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="],
-
- "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="],
-
- "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.1", "", {}, "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg=="],
-
- "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.2.0", "", {}, "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ=="],
-
- "unimodules-app-loader": ["unimodules-app-loader@55.0.3-canary-20260328-2049187", "", {}, "sha512-kqGCLCS35FFs4ue6BCIMuCVLO/KTco9WOHq/ghEVsR4NgGnhb9D3td2/D6KAFRY3c8qQ83x8mBAsHTwN7EUnNA=="],
-
- "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
-
- "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="],
-
- "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
-
- "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
-
- "urijs": ["urijs@1.19.11", "", {}, "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="],
-
- "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
-
- "use-latest-callback": ["use-latest-callback@0.2.6", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-FvRG9i1HSo0wagmX63Vrm8SnlUU3LMM3WyZkQ76RnslpBrX694AdG4A0zQBx2B3ZifFA0yv/BaEHGBnEax5rZg=="],
-
- "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="],
-
- "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
-
- "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
-
- "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
-
- "uuid": ["uuid@7.0.3", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg=="],
-
- "validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="],
-
- "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
-
- "vaul": ["vaul@1.1.2", "", { "dependencies": { "@radix-ui/react-dialog": "^1.1.1" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA=="],
-
- "vlq": ["vlq@1.0.1", "", {}, "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w=="],
-
- "walker": ["walker@1.0.8", "", { "dependencies": { "makeerror": "1.0.12" } }, "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ=="],
-
- "warn-once": ["warn-once@0.1.1", "", {}, "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="],
-
- "wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
-
- "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
-
- "whatwg-fetch": ["whatwg-fetch@3.6.20", "", {}, "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg=="],
-
- "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
-
- "whatwg-url-minimum": ["whatwg-url-minimum@0.1.1", "", {}, "sha512-u2FNVjFVFZhdjb502KzXy1gKn1mEisQRJssmSJT8CPhZdZa0AP6VCbWlXERKyGu0l09t0k50FiDiralpGhBxgA=="],
-
- "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
-
- "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
-
- "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
-
- "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
-
- "which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="],
-
- "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
-
- "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
-
- "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
-
- "write-file-atomic": ["write-file-atomic@4.0.2", "", { "dependencies": { "imurmurhash": "^0.1.4", "signal-exit": "^3.0.7" } }, "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg=="],
-
- "ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="],
-
- "xcode": ["xcode@3.0.1", "", { "dependencies": { "simple-plist": "^1.1.0", "uuid": "^7.0.3" } }, "sha512-kCz5k7J7XbJtjABOvkc5lJmkiDh8VhjVCGNiqdKCscmVpdVUpEAyXv1xmCLkQJ5dsHqx3IPO4XW+NTDhU/fatA=="],
-
- "xml2js": ["xml2js@0.6.0", "", { "dependencies": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" } }, "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w=="],
-
- "xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
-
- "xtend": ["xtend@4.0.2", "", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="],
-
- "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
-
- "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
-
- "yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="],
-
- "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
-
- "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
-
- "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
-
- "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
-
- "zustand": ["zustand@5.0.12", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g=="],
-
- "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "@babel/helper-define-polyfill-provider/resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
-
- "@babel/plugin-transform-runtime/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
-
- "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
-
- "@expo/cli/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
-
- "@expo/cli/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@expo/cli/ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="],
-
- "@expo/config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
-
- "@expo/config/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@expo/config-plugins/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
-
- "@expo/config-plugins/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@expo/devcert/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
-
- "@expo/fingerprint/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
-
- "@expo/fingerprint/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
-
- "@expo/fingerprint/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@expo/image-utils/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@expo/metro-config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
-
- "@expo/prebuild-config/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@istanbuljs/load-nyc-config/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
-
- "@istanbuljs/load-nyc-config/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
-
- "@istanbuljs/load-nyc-config/js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="],
-
- "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
-
- "@react-native/codegen/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
-
- "@react-native/community-cli-plugin/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
-
- "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
-
- "@typescript-eslint/typescript-estree/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
-
- "ansi-escapes/type-fest": ["type-fest@0.21.3", "", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="],
-
- "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
-
- "babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
-
- "babel-preset-expo/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.32.1", "", { "dependencies": { "hermes-parser": "0.32.1" } }, "sha512-HgErPZTghW76Rkq9uqn5ESeiD97FbqpZ1V170T1RG2RDp+7pJVQV2pQJs7y5YzN0/gcT6GM5ci9apRnIwuyPdQ=="],
-
- "better-opn/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="],
-
- "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
-
- "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
-
- "compression/negotiator": ["negotiator@0.6.4", "", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="],
-
- "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
-
- "dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="],
-
- "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
-
- "eslint-import-resolver-node/resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
-
- "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
-
- "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
-
- "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
-
- "fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="],
-
- "fbjs/ua-parser-js": ["ua-parser-js@1.0.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug=="],
-
- "finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
-
- "finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="],
-
- "finalhandler/on-finished": ["on-finished@2.3.0", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww=="],
-
- "finalhandler/statuses": ["statuses@1.5.0", "", {}, "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA=="],
-
- "hoist-non-react-statics/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
-
- "hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
-
- "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
-
- "is-bun-module/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "istanbul-lib-instrument/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "jest-util/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
-
- "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
-
- "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
-
- "log-symbols/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
-
- "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
-
- "metro/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
-
- "metro-babel-transformer/hermes-parser": ["hermes-parser@0.32.0", "", { "dependencies": { "hermes-estree": "0.32.0" } }, "sha512-g4nBOWFpuiTqjR3LZdRxKUkij9iyveWeuks7INEsMX741f3r9xxrOe8TeQfUxtda0eXmiIFiMQzoeSQEno33Hw=="],
-
- "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
-
- "node-exports-info/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
-
- "npm-package-arg/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
-
- "path-scurry/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="],
-
- "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
-
- "pretty-format/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
-
- "prop-types/react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
-
- "react-native/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "react-native-reanimated/react-native-is-edge-to-edge": ["react-native-is-edge-to-edge@1.2.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q=="],
-
- "react-native-reanimated/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "react-native-web/@react-native/normalize-colors": ["@react-native/normalize-colors@0.74.89", "", {}, "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg=="],
-
- "react-native-web/memoize-one": ["memoize-one@6.0.0", "", {}, "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="],
-
- "react-native-worklets/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="],
-
- "send/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="],
-
- "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
-
- "stack-utils/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="],
-
- "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
-
- "strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
-
- "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
-
- "tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
-
- "wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
-
- "xml2js/xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="],
-
- "@expo/cli/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
-
- "@expo/config-plugins/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
-
- "@expo/config/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
-
- "@expo/fingerprint/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
-
- "@expo/metro-config/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
-
- "@istanbuljs/load-nyc-config/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
-
- "@istanbuljs/load-nyc-config/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="],
-
- "@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
-
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
-
- "babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
-
- "compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "connect/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "log-symbols/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
-
- "log-symbols/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
-
- "log-symbols/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
-
- "metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
-
- "metro/hermes-parser/hermes-estree": ["hermes-estree@0.32.0", "", {}, "sha512-KWn3BqnlDOl97Xe1Yviur6NbgIZ+IP+UVSpshlZWkq+EtoHg6/cwiDj/osP9PCEgFE15KBm1O55JRwbMEm5ejQ=="],
-
- "ora/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
-
- "ora/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
-
- "ora/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
-
- "send/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
-
- "@expo/cli/glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
-
- "@expo/config-plugins/glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
-
- "@expo/config/glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
-
- "@expo/fingerprint/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
-
- "@expo/metro-config/glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
-
- "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
-
- "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
-
- "log-symbols/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
-
- "log-symbols/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
-
- "ora/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
-
- "ora/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
-
- "@expo/cli/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
-
- "@expo/config-plugins/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
-
- "@expo/config/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
-
- "@expo/metro-config/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
-
- "@istanbuljs/load-nyc-config/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
-
- "log-symbols/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
-
- "ora/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
- }
-}
diff --git a/eslint.config.js b/eslint.config.js
deleted file mode 100644
index ba708ed..0000000
--- a/eslint.config.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// https://docs.expo.dev/guides/using-eslint/
-const { defineConfig } = require('eslint/config');
-const expoConfig = require("eslint-config-expo/flat");
-
-module.exports = defineConfig([
- expoConfig,
- {
- ignores: ["dist/*"],
- }
-]);
diff --git a/iOS/RSSuper.xcodeproj/project.pbxproj b/iOS/RSSuper.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..a13f964
--- /dev/null
+++ b/iOS/RSSuper.xcodeproj/project.pbxproj
@@ -0,0 +1,583 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 77;
+ objects = {
+
+/* Begin PBXContainerItemProxy section */
+ 27A094F62F79600D0067CFA4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 27A094DE2F79600B0067CFA4 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 27A094E52F79600B0067CFA4;
+ remoteInfo = RSSuper;
+ };
+ 27A095002F79600D0067CFA4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 27A094DE2F79600B0067CFA4 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 27A094E52F79600B0067CFA4;
+ remoteInfo = RSSuper;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 27A094E62F79600B0067CFA4 /* RSSuper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RSSuper.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 27A094F52F79600D0067CFA4 /* RSSuperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RSSuperTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 27A094FF2F79600D0067CFA4 /* RSSuperUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RSSuperUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+/* End PBXFileReference section */
+
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+ 27A094E82F79600B0067CFA4 /* RSSuper */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ path = RSSuper;
+ sourceTree = "";
+ };
+ 27A094F82F79600D0067CFA4 /* RSSuperTests */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ path = RSSuperTests;
+ sourceTree = "";
+ };
+ 27A095022F79600D0067CFA4 /* RSSuperUITests */ = {
+ isa = PBXFileSystemSynchronizedRootGroup;
+ path = RSSuperUITests;
+ sourceTree = "";
+ };
+/* End PBXFileSystemSynchronizedRootGroup section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 27A094E32F79600B0067CFA4 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27A094F22F79600D0067CFA4 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27A094FC2F79600D0067CFA4 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 27A094DD2F79600B0067CFA4 = {
+ isa = PBXGroup;
+ children = (
+ 27A094E82F79600B0067CFA4 /* RSSuper */,
+ 27A094F82F79600D0067CFA4 /* RSSuperTests */,
+ 27A095022F79600D0067CFA4 /* RSSuperUITests */,
+ 27A094E72F79600B0067CFA4 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 27A094E72F79600B0067CFA4 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 27A094E62F79600B0067CFA4 /* RSSuper.app */,
+ 27A094F52F79600D0067CFA4 /* RSSuperTests.xctest */,
+ 27A094FF2F79600D0067CFA4 /* RSSuperUITests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 27A094E52F79600B0067CFA4 /* RSSuper */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 27A095092F79600D0067CFA4 /* Build configuration list for PBXNativeTarget "RSSuper" */;
+ buildPhases = (
+ 27A094E22F79600B0067CFA4 /* Sources */,
+ 27A094E32F79600B0067CFA4 /* Frameworks */,
+ 27A094E42F79600B0067CFA4 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ fileSystemSynchronizedGroups = (
+ 27A094E82F79600B0067CFA4 /* RSSuper */,
+ );
+ name = RSSuper;
+ packageProductDependencies = (
+ );
+ productName = RSSuper;
+ productReference = 27A094E62F79600B0067CFA4 /* RSSuper.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 27A094F42F79600D0067CFA4 /* RSSuperTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 27A0950C2F79600D0067CFA4 /* Build configuration list for PBXNativeTarget "RSSuperTests" */;
+ buildPhases = (
+ 27A094F12F79600D0067CFA4 /* Sources */,
+ 27A094F22F79600D0067CFA4 /* Frameworks */,
+ 27A094F32F79600D0067CFA4 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 27A094F72F79600D0067CFA4 /* PBXTargetDependency */,
+ );
+ fileSystemSynchronizedGroups = (
+ 27A094F82F79600D0067CFA4 /* RSSuperTests */,
+ );
+ name = RSSuperTests;
+ packageProductDependencies = (
+ );
+ productName = RSSuperTests;
+ productReference = 27A094F52F79600D0067CFA4 /* RSSuperTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 27A094FE2F79600D0067CFA4 /* RSSuperUITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 27A0950F2F79600D0067CFA4 /* Build configuration list for PBXNativeTarget "RSSuperUITests" */;
+ buildPhases = (
+ 27A094FB2F79600D0067CFA4 /* Sources */,
+ 27A094FC2F79600D0067CFA4 /* Frameworks */,
+ 27A094FD2F79600D0067CFA4 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 27A095012F79600D0067CFA4 /* PBXTargetDependency */,
+ );
+ fileSystemSynchronizedGroups = (
+ 27A095022F79600D0067CFA4 /* RSSuperUITests */,
+ );
+ name = RSSuperUITests;
+ packageProductDependencies = (
+ );
+ productName = RSSuperUITests;
+ productReference = 27A094FF2F79600D0067CFA4 /* RSSuperUITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 27A094DE2F79600B0067CFA4 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = 1;
+ LastSwiftUpdateCheck = 2630;
+ LastUpgradeCheck = 2630;
+ TargetAttributes = {
+ 27A094E52F79600B0067CFA4 = {
+ CreatedOnToolsVersion = 26.3;
+ };
+ 27A094F42F79600D0067CFA4 = {
+ CreatedOnToolsVersion = 26.3;
+ TestTargetID = 27A094E52F79600B0067CFA4;
+ };
+ 27A094FE2F79600D0067CFA4 = {
+ CreatedOnToolsVersion = 26.3;
+ TestTargetID = 27A094E52F79600B0067CFA4;
+ };
+ };
+ };
+ buildConfigurationList = 27A094E12F79600B0067CFA4 /* Build configuration list for PBXProject "RSSuper" */;
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 27A094DD2F79600B0067CFA4;
+ minimizedProjectReferenceProxies = 1;
+ preferredProjectObjectVersion = 77;
+ productRefGroup = 27A094E72F79600B0067CFA4 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 27A094E52F79600B0067CFA4 /* RSSuper */,
+ 27A094F42F79600D0067CFA4 /* RSSuperTests */,
+ 27A094FE2F79600D0067CFA4 /* RSSuperUITests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 27A094E42F79600B0067CFA4 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27A094F32F79600D0067CFA4 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27A094FD2F79600D0067CFA4 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 27A094E22F79600B0067CFA4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27A094F12F79600D0067CFA4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 27A094FB2F79600D0067CFA4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 27A094F72F79600D0067CFA4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 27A094E52F79600B0067CFA4 /* RSSuper */;
+ targetProxy = 27A094F62F79600D0067CFA4 /* PBXContainerItemProxy */;
+ };
+ 27A095012F79600D0067CFA4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 27A094E52F79600B0067CFA4 /* RSSuper */;
+ targetProxy = 27A095002F79600D0067CFA4 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 27A095072F79600D0067CFA4 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 26.2;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 27A095082F79600D0067CFA4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_USER_SCRIPT_SANDBOXING = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 26.2;
+ LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 27A0950A2F79600D0067CFA4 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.mikefreno.RSSuper;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ STRING_CATALOG_GENERATE_SYMBOLS = YES;
+ SWIFT_APPROACHABLE_CONCURRENCY = YES;
+ SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 27A0950B2F79600D0067CFA4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ ENABLE_PREVIEWS = YES;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.mikefreno.RSSuper;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ STRING_CATALOG_GENERATE_SYMBOLS = YES;
+ SWIFT_APPROACHABLE_CONCURRENCY = YES;
+ SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 27A0950D2F79600D0067CFA4 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 26.2;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.mikefreno.RSSuperTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ STRING_CATALOG_GENERATE_SYMBOLS = NO;
+ SWIFT_APPROACHABLE_CONCURRENCY = YES;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RSSuper.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/RSSuper";
+ };
+ name = Debug;
+ };
+ 27A0950E2F79600D0067CFA4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 26.2;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.mikefreno.RSSuperTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ STRING_CATALOG_GENERATE_SYMBOLS = NO;
+ SWIFT_APPROACHABLE_CONCURRENCY = YES;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RSSuper.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/RSSuper";
+ };
+ name = Release;
+ };
+ 27A095102F79600D0067CFA4 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.mikefreno.RSSuperUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ STRING_CATALOG_GENERATE_SYMBOLS = NO;
+ SWIFT_APPROACHABLE_CONCURRENCY = YES;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = RSSuper;
+ };
+ name = Debug;
+ };
+ 27A095112F79600D0067CFA4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 6GK4F9L62V;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.mikefreno.RSSuperUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ STRING_CATALOG_GENERATE_SYMBOLS = NO;
+ SWIFT_APPROACHABLE_CONCURRENCY = YES;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = RSSuper;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 27A094E12F79600B0067CFA4 /* Build configuration list for PBXProject "RSSuper" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 27A095072F79600D0067CFA4 /* Debug */,
+ 27A095082F79600D0067CFA4 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 27A095092F79600D0067CFA4 /* Build configuration list for PBXNativeTarget "RSSuper" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 27A0950A2F79600D0067CFA4 /* Debug */,
+ 27A0950B2F79600D0067CFA4 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 27A0950C2F79600D0067CFA4 /* Build configuration list for PBXNativeTarget "RSSuperTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 27A0950D2F79600D0067CFA4 /* Debug */,
+ 27A0950E2F79600D0067CFA4 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 27A0950F2F79600D0067CFA4 /* Build configuration list for PBXNativeTarget "RSSuperUITests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 27A095102F79600D0067CFA4 /* Debug */,
+ 27A095112F79600D0067CFA4 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 27A094DE2F79600B0067CFA4 /* Project object */;
+}
diff --git a/iOS/RSSuper.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/iOS/RSSuper.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/iOS/RSSuper.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/iOS/RSSuper.xcodeproj/project.xcworkspace/xcuserdata/mike.xcuserdatad/UserInterfaceState.xcuserstate b/iOS/RSSuper.xcodeproj/project.xcworkspace/xcuserdata/mike.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..632a797
Binary files /dev/null and b/iOS/RSSuper.xcodeproj/project.xcworkspace/xcuserdata/mike.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/iOS/RSSuper.xcodeproj/xcuserdata/mike.xcuserdatad/xcschemes/xcschememanagement.plist b/iOS/RSSuper.xcodeproj/xcuserdata/mike.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..eaba87e
--- /dev/null
+++ b/iOS/RSSuper.xcodeproj/xcuserdata/mike.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,14 @@
+
+
+
+
+ SchemeUserState
+
+ RSSuper.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+
+
+
diff --git a/iOS/RSSuper/Assets.xcassets/AccentColor.colorset/Contents.json b/iOS/RSSuper/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 0000000..eb87897
--- /dev/null
+++ b/iOS/RSSuper/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOS/RSSuper/Assets.xcassets/AppIcon.appiconset/Contents.json b/iOS/RSSuper/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..2305880
--- /dev/null
+++ b/iOS/RSSuper/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,35 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "tinted"
+ }
+ ],
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOS/RSSuper/Assets.xcassets/Contents.json b/iOS/RSSuper/Assets.xcassets/Contents.json
new file mode 100644
index 0000000..73c0059
--- /dev/null
+++ b/iOS/RSSuper/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/iOS/RSSuper/ContentView.swift b/iOS/RSSuper/ContentView.swift
new file mode 100644
index 0000000..0f54560
--- /dev/null
+++ b/iOS/RSSuper/ContentView.swift
@@ -0,0 +1,61 @@
+//
+// ContentView.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import SwiftUI
+import SwiftData
+
+struct ContentView: View {
+ @Environment(\.modelContext) private var modelContext
+ @Query private var items: [Item]
+
+ var body: some View {
+ NavigationSplitView {
+ List {
+ ForEach(items) { item in
+ NavigationLink {
+ Text("Item at \(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))")
+ } label: {
+ Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
+ }
+ }
+ .onDelete(perform: deleteItems)
+ }
+ .toolbar {
+ ToolbarItem(placement: .navigationBarTrailing) {
+ EditButton()
+ }
+ ToolbarItem {
+ Button(action: addItem) {
+ Label("Add Item", systemImage: "plus")
+ }
+ }
+ }
+ } detail: {
+ Text("Select an item")
+ }
+ }
+
+ private func addItem() {
+ withAnimation {
+ let newItem = Item(timestamp: Date())
+ modelContext.insert(newItem)
+ }
+ }
+
+ private func deleteItems(offsets: IndexSet) {
+ withAnimation {
+ for index in offsets {
+ modelContext.delete(items[index])
+ }
+ }
+ }
+}
+
+#Preview {
+ ContentView()
+ .modelContainer(for: Item.self, inMemory: true)
+}
diff --git a/iOS/RSSuper/Database/DatabaseManager.swift b/iOS/RSSuper/Database/DatabaseManager.swift
new file mode 100644
index 0000000..6201b15
--- /dev/null
+++ b/iOS/RSSuper/Database/DatabaseManager.swift
@@ -0,0 +1,764 @@
+//
+// DatabaseManager.swift
+// RSSuper
+//
+// Created on 3/29/26.
+//
+
+import Foundation
+import SQLite3
+
+enum DatabaseError: LocalizedError {
+ case objectNotFound
+ case saveFailed(Error)
+ case fetchFailed(Error)
+ case migrationFailed(Error)
+
+ var errorDescription: String? {
+ switch self {
+ case .objectNotFound:
+ return "Object not found"
+ case .saveFailed(let error):
+ return "Failed to save: \(error.localizedDescription)"
+ case .fetchFailed(let error):
+ return "Failed to fetch: \(error.localizedDescription)"
+ case .migrationFailed(let error):
+ return "Migration failed: \(error.localizedDescription)"
+ }
+ }
+}
+
+final class DatabaseManager {
+ static let shared = DatabaseManager()
+
+ private var db: OpaquePointer?
+ private let fileManager = FileManager.default
+
+ private init() {
+ let dbPath = databasePath()
+ ensureDatabaseDirectoryExists()
+
+ if sqlite3_open(dbPath, &db) != SQLITE_OK {
+ fatalError("Failed to open database")
+ }
+
+ enableForeignKeys()
+ try? migrateDatabase()
+ }
+
+ deinit {
+ if db != nil {
+ sqlite3_close(db)
+ }
+ }
+
+ private func databasePath() -> String {
+ let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
+ let documentsDirectory = urls[0]
+ return documentsDirectory.appendingPathComponent("RSSuper.sqlite").path
+ }
+
+ private func ensureDatabaseDirectoryExists() {
+ let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)
+ let documentsDirectory = urls[0]
+ try? fileManager.createDirectory(at: documentsDirectory, withIntermediateDirectories: true)
+ }
+
+ private func enableForeignKeys() {
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+ sqlite3_exec(db, "PRAGMA foreign_keys = ON", nil, nil, &errorMessage)
+ }
+
+ private func migrateDatabase() throws {
+ createSubscriptionsTable()
+ createFeedItemsTable()
+ createSearchHistoryTable()
+ createFTSIndex()
+ createIndexes()
+ }
+
+ private func createSubscriptionsTable() {
+ let createTableSQL = """
+ CREATE TABLE IF NOT EXISTS subscriptions (
+ id TEXT PRIMARY KEY,
+ url TEXT NOT NULL,
+ title TEXT NOT NULL,
+ category TEXT,
+ enabled INTEGER NOT NULL DEFAULT 1,
+ fetch_interval INTEGER NOT NULL DEFAULT 3600,
+ created_at TEXT NOT NULL,
+ updated_at TEXT NOT NULL,
+ last_fetched_at TEXT,
+ next_fetch_at TEXT,
+ error TEXT,
+ http_auth BLOB
+ )
+ """
+
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+
+ if sqlite3_exec(db, createTableSQL, nil, nil, &errorMessage) != SQLITE_OK {
+ let error = String(cString: errorMessage!)
+ fatalError("Failed to create subscriptions table: \(error)")
+ }
+
+ let uniqueIndexSQL = "CREATE UNIQUE INDEX IF NOT EXISTS idx_subscriptions_url ON subscriptions(url)"
+ var error: UnsafeMutablePointer?
+ defer { sqlite3_free(error) }
+ sqlite3_exec(db, uniqueIndexSQL, nil, nil, &error)
+ }
+
+ private func createFeedItemsTable() {
+ let createTableSQL = """
+ CREATE TABLE IF NOT EXISTS feed_items (
+ id TEXT PRIMARY KEY,
+ title TEXT NOT NULL,
+ link TEXT,
+ description TEXT,
+ content TEXT,
+ author TEXT,
+ published TEXT,
+ updated TEXT,
+ categories TEXT,
+ enclosure BLOB,
+ guid TEXT,
+ subscription_id TEXT NOT NULL REFERENCES subscriptions(id) ON DELETE CASCADE,
+ subscription_title TEXT,
+ read INTEGER NOT NULL DEFAULT 0,
+ created_at TEXT NOT NULL
+ )
+ """
+
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+
+ if sqlite3_exec(db, createTableSQL, nil, nil, &errorMessage) != SQLITE_OK {
+ let error = String(cString: errorMessage!)
+ fatalError("Failed to create feed_items table: \(error)")
+ }
+ }
+
+ private func createSearchHistoryTable() {
+ let createTableSQL = """
+ CREATE TABLE IF NOT EXISTS search_history (
+ id TEXT PRIMARY KEY,
+ query TEXT NOT NULL,
+ timestamp TEXT NOT NULL
+ )
+ """
+
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+
+ if sqlite3_exec(db, createTableSQL, nil, nil, &errorMessage) != SQLITE_OK {
+ let error = String(cString: errorMessage!)
+ fatalError("Failed to create search_history table: \(error)")
+ }
+ }
+
+ private func createFTSIndex() {
+ let createFTSQL = """
+ CREATE VIRTUAL TABLE IF NOT EXISTS feed_items_fts USING fts5(
+ title,
+ description,
+ content,
+ author,
+ content='feed_items',
+ content_rowid='rowid'
+ )
+ """
+
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+ sqlite3_exec(db, createFTSQL, nil, nil, &errorMessage)
+
+ let triggerInsertSQL = """
+ CREATE TRIGGER IF NOT EXISTS feed_items_ai AFTER INSERT ON feed_items BEGIN
+ INSERT INTO feed_items_fts(rowid, title, description, content, author)
+ VALUES (new.rowid, new.title, new.description, new.content, new.author);
+ END
+ """
+ var error: UnsafeMutablePointer?
+ defer { sqlite3_free(error) }
+ sqlite3_exec(db, triggerInsertSQL, nil, nil, &error)
+
+ let triggerDeleteSQL = """
+ CREATE TRIGGER IF NOT EXISTS feed_items_ad AFTER DELETE ON feed_items BEGIN
+ DELETE FROM feed_items_fts WHERE rowid = old.rowid;
+ END
+ """
+ defer { sqlite3_free(error) }
+ sqlite3_exec(db, triggerDeleteSQL, nil, nil, &error)
+
+ let triggerUpdateSQL = """
+ CREATE TRIGGER IF NOT EXISTS feed_items_au AFTER UPDATE ON feed_items BEGIN
+ DELETE FROM feed_items_fts WHERE rowid = old.rowid;
+ INSERT INTO feed_items_fts(rowid, title, description, content, author)
+ VALUES (new.rowid, new.title, new.description, new.content, new.author);
+ END
+ """
+ defer { sqlite3_free(error) }
+ sqlite3_exec(db, triggerUpdateSQL, nil, nil, &error)
+ }
+
+ private func createIndexes() {
+ let indexes = [
+ "CREATE INDEX IF NOT EXISTS idx_feed_items_subscription_id ON feed_items(subscription_id)",
+ "CREATE INDEX IF NOT EXISTS idx_feed_items_published ON feed_items(published)",
+ "CREATE INDEX IF NOT EXISTS idx_feed_items_read ON feed_items(read)",
+ "CREATE INDEX IF NOT EXISTS idx_search_history_timestamp ON search_history(timestamp)"
+ ]
+
+ for indexSQL in indexes {
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+ sqlite3_exec(db, indexSQL, nil, nil, &errorMessage)
+ }
+ }
+}
+
+// MARK: - Subscription CRUD
+
+extension DatabaseManager {
+ func createSubscription(id: String, url: String, title: String, category: String? = nil, enabled: Bool = true, fetchInterval: Int = 3600) throws -> FeedSubscription {
+ let now = ISO8601DateFormatter().string(from: Date())
+ let subscription = FeedSubscription(
+ id: id,
+ url: url,
+ title: title,
+ category: category,
+ enabled: enabled,
+ fetchInterval: fetchInterval,
+ createdAt: Date(),
+ updatedAt: Date(),
+ lastFetchedAt: nil,
+ nextFetchAt: nil,
+ error: nil,
+ httpAuth: nil
+ )
+
+ let insertSQL = """
+ INSERT INTO subscriptions (id, url, title, category, enabled, fetch_interval, created_at, updated_at)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+ """
+
+ guard let statement = prepareStatement(sql: insertSQL) else {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ defer { sqlite3_finalize(statement) }
+
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 2, (url as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 3, (title as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 4, (category as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_int(statement, 5, enabled ? 1 : 0)
+ sqlite3_bind_int(statement, 6, Int32(fetchInterval))
+ sqlite3_bind_text(statement, 7, (now as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 8, (now as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) != SQLITE_DONE {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ return subscription
+ }
+
+ func fetchSubscription(id: String) throws -> FeedSubscription? {
+ let selectSQL = "SELECT * FROM subscriptions WHERE id = ? LIMIT 1"
+
+ guard let statement = prepareStatement(sql: selectSQL) else {
+ return nil
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) == SQLITE_ROW {
+ return rowToSubscription(statement)
+ }
+
+ return nil
+ }
+
+ func fetchAllSubscriptions() throws -> [FeedSubscription] {
+ let selectSQL = "SELECT * FROM subscriptions ORDER BY created_at DESC"
+ return executeQuery(sql: selectSQL, bindParams: [], rowMapper: rowToSubscription)
+ }
+
+ func fetchEnabledSubscriptions() throws -> [FeedSubscription] {
+ let selectSQL = "SELECT * FROM subscriptions WHERE enabled = 1 ORDER BY title"
+ return executeQuery(sql: selectSQL, bindParams: [], rowMapper: rowToSubscription)
+ }
+
+ func updateSubscription(_ subscription: FeedSubscription, title: String? = nil, category: String? = nil, enabled: Bool? = nil, fetchInterval: Int? = nil) throws -> FeedSubscription {
+ var updated = subscription
+ if let title = title { updated.title = title }
+ if let category = category { updated.category = category }
+ if let enabled = enabled { updated.enabled = enabled }
+ if let fetchInterval = fetchInterval { updated.fetchInterval = fetchInterval }
+ updated.updatedAt = Date()
+
+ let updateSQL = """
+ UPDATE subscriptions SET
+ title = ?, category = ?, enabled = ?, fetch_interval = ?, updated_at = ?
+ WHERE id = ?
+ """
+
+ guard let statement = prepareStatement(sql: updateSQL) else {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ defer { sqlite3_finalize(statement) }
+
+ let now = ISO8601DateFormatter().string(from: Date())
+ sqlite3_bind_text(statement, 1, (updated.title as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 2, (updated.category as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_int(statement, 3, updated.enabled ? 1 : 0)
+ sqlite3_bind_int(statement, 4, Int32(updated.fetchInterval))
+ sqlite3_bind_text(statement, 5, (now as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 6, (updated.id as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) != SQLITE_DONE {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ return updated
+ }
+
+ func deleteSubscription(id: String) throws {
+ let deleteSQL = "DELETE FROM subscriptions WHERE id = ?"
+
+ guard let statement = prepareStatement(sql: deleteSQL) else {
+ return
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) != SQLITE_DONE {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+ }
+
+ private func rowToSubscription(_ statement: OpaquePointer) -> FeedSubscription {
+ let id = String(cString: sqlite3_column_text(statement, 0))
+ let url = String(cString: sqlite3_column_text(statement, 1))
+ let title = String(cString: sqlite3_column_text(statement, 2))
+ let category = sqlite3_column_type(statement, 3) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 3))
+ let enabled = sqlite3_column_int(statement, 4) == 1
+ let fetchInterval = Int(sqlite3_column_int(statement, 5))
+ let createdAt = parseDate(String(cString: sqlite3_column_text(statement, 6)))
+ let updatedAt = parseDate(String(cString: sqlite3_column_text(statement, 7)))
+ let lastFetchedAt = sqlite3_column_type(statement, 8) == SQLITE_NULL ? nil : parseDate(String(cString: sqlite3_column_text(statement, 8)))
+ let nextFetchAt = sqlite3_column_type(statement, 9) == SQLITE_NULL ? nil : parseDate(String(cString: sqlite3_column_text(statement, 9)))
+ let error = sqlite3_column_type(statement, 10) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 10))
+ let httpAuthData = sqlite3_column_type(statement, 11) == SQLITE_NULL ? nil : Data(bytes: sqlite3_column_blob(statement, 11), count: Int(sqlite3_column_bytes(statement, 11)))
+ let httpAuth = httpAuthData.flatMap { try? JSONDecoder().decode(HttpAuth.self, from: $0) }
+
+ return FeedSubscription(
+ id: id,
+ url: url,
+ title: title,
+ category: category,
+ enabled: enabled,
+ fetchInterval: fetchInterval,
+ createdAt: createdAt,
+ updatedAt: updatedAt,
+ lastFetchedAt: lastFetchedAt,
+ nextFetchAt: nextFetchAt,
+ error: error,
+ httpAuth: httpAuth
+ )
+ }
+}
+
+// MARK: - FeedItem CRUD
+
+extension DatabaseManager {
+ func createFeedItem(_ item: FeedItem) throws -> FeedItem {
+ let now = ISO8601DateFormatter().string(from: Date())
+
+ let insertSQL = """
+ INSERT INTO feed_items (id, title, link, description, content, author, published, updated, categories, enclosure, guid, subscription_id, subscription_title, read, created_at)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """
+
+ guard let statement = prepareStatement(sql: insertSQL) else {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ defer { sqlite3_finalize(statement) }
+
+ sqlite3_bind_text(statement, 1, (item.id as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 2, (item.title as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 3, (item.link as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_text(statement, 4, (item.description as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_text(statement, 5, (item.content as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_text(statement, 6, (item.author as NSString?)?.utf8String, -1, nil)
+ if let published = item.published {
+ sqlite3_bind_text(statement, 7, (ISO8601DateFormatter().string(from: published) as NSString).utf8String, -1, nil)
+ } else {
+ sqlite3_bind_null(statement, 7)
+ }
+ if let updated = item.updated {
+ sqlite3_bind_text(statement, 8, (ISO8601DateFormatter().string(from: updated) as NSString).utf8String, -1, nil)
+ } else {
+ sqlite3_bind_null(statement, 8)
+ }
+ if let categories = item.categories, let data = try? JSONEncoder().encode(categories) {
+ sqlite3_bind_blob(statement, 9, (data as NSData).bytes, Int32(data.count), nil)
+ } else {
+ sqlite3_bind_null(statement, 9)
+ }
+ if let enclosure = item.enclosure, let data = try? JSONEncoder().encode(enclosure) {
+ sqlite3_bind_blob(statement, 10, (data as NSData).bytes, Int32(data.count), nil)
+ } else {
+ sqlite3_bind_null(statement, 10)
+ }
+ sqlite3_bind_text(statement, 11, (item.guid as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_text(statement, 12, (item.subscriptionId as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 13, (item.subscriptionTitle as NSString?)?.utf8String, -1, nil)
+ sqlite3_bind_int(statement, 14, item.read ? 1 : 0)
+ sqlite3_bind_text(statement, 15, (now as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) != SQLITE_DONE {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ return item
+ }
+
+ func fetchFeedItem(id: String) throws -> FeedItem? {
+ let selectSQL = "SELECT * FROM feed_items WHERE id = ? LIMIT 1"
+
+ guard let statement = prepareStatement(sql: selectSQL) else {
+ return nil
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) == SQLITE_ROW {
+ return rowToFeedItem(statement)
+ }
+
+ return nil
+ }
+
+ func fetchFeedItems(for subscriptionId: String) throws -> [FeedItem] {
+ let selectSQL = "SELECT * FROM feed_items WHERE subscription_id = ? ORDER BY published DESC"
+ return executeQuery(sql: selectSQL, bindParams: [subscriptionId], rowMapper: rowToFeedItem)
+ }
+
+ func fetchFeedItems(limit: Int = 50) throws -> [FeedItem] {
+ let selectSQL = "SELECT * FROM feed_items ORDER BY published DESC LIMIT ?"
+ return executeQuery(sql: selectSQL, bindParams: [limit], rowMapper: rowToFeedItem)
+ }
+
+ func fetchUnreadFeedItems(limit: Int = 50) throws -> [FeedItem] {
+ let selectSQL = "SELECT * FROM feed_items WHERE read = 0 ORDER BY published DESC LIMIT ?"
+ return executeQuery(sql: selectSQL, bindParams: [limit], rowMapper: rowToFeedItem)
+ }
+
+ func updateFeedItem(_ item: FeedItem, read: Bool? = nil) throws -> FeedItem {
+ guard let read = read else { return item }
+
+ let updateSQL = "UPDATE feed_items SET read = ? WHERE id = ?"
+
+ guard let statement = prepareStatement(sql: updateSQL) else {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_int(statement, 1, read ? 1 : 0)
+ sqlite3_bind_text(statement, 2, (item.id as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) != SQLITE_DONE {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ var updatedItem = item
+ updatedItem.read = read
+ return updatedItem
+ }
+
+ func markAsRead(ids: [String]) throws {
+ guard !ids.isEmpty else { return }
+
+ let placeholders = ids.map { _ in "?" }.joined(separator: ",")
+ let updateSQL = "UPDATE feed_items SET read = 1 WHERE id IN (\(placeholders))"
+
+ guard let statement = prepareStatement(sql: updateSQL) else {
+ return
+ }
+
+ defer { sqlite3_finalize(statement) }
+
+ for (index, id) in ids.enumerated() {
+ sqlite3_bind_text(statement, Int32(index + 1), (id as NSString).utf8String, -1, nil)
+ }
+
+ sqlite3_step(statement)
+ }
+
+ func deleteFeedItem(id: String) throws {
+ let deleteSQL = "DELETE FROM feed_items WHERE id = ?"
+
+ guard let statement = prepareStatement(sql: deleteSQL) else {
+ return
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+ sqlite3_step(statement)
+ }
+
+ func deleteFeedItems(for subscriptionId: String) throws {
+ let deleteSQL = "DELETE FROM feed_items WHERE subscription_id = ?"
+
+ guard let statement = prepareStatement(sql: deleteSQL) else {
+ return
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (subscriptionId as NSString).utf8String, -1, nil)
+ sqlite3_step(statement)
+ }
+
+ private func rowToFeedItem(_ statement: OpaquePointer) -> FeedItem {
+ let id = String(cString: sqlite3_column_text(statement, 0))
+ let title = String(cString: sqlite3_column_text(statement, 1))
+ let link = sqlite3_column_type(statement, 2) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 2))
+ let description = sqlite3_column_type(statement, 3) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 3))
+ let content = sqlite3_column_type(statement, 4) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 4))
+ let author = sqlite3_column_type(statement, 5) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 5))
+ let published = sqlite3_column_type(statement, 6) == SQLITE_NULL ? nil : parseDate(String(cString: sqlite3_column_text(statement, 6)))
+ let updated = sqlite3_column_type(statement, 7) == SQLITE_NULL ? nil : parseDate(String(cString: sqlite3_column_text(statement, 7)))
+ let categoriesData = sqlite3_column_type(statement, 8) == SQLITE_NULL ? nil : Data(bytes: sqlite3_column_blob(statement, 8), count: Int(sqlite3_column_bytes(statement, 8)))
+ let categories = categoriesData.flatMap { try? JSONDecoder().decode([String].self, from: $0) }
+ let enclosureData = sqlite3_column_type(statement, 9) == SQLITE_NULL ? nil : Data(bytes: sqlite3_column_blob(statement, 9), count: Int(sqlite3_column_bytes(statement, 9)))
+ let enclosure = enclosureData.flatMap { try? JSONDecoder().decode(Enclosure.self, from: $0) }
+ let guid = sqlite3_column_type(statement, 10) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 10))
+ let subscriptionId = String(cString: sqlite3_column_text(statement, 11))
+ let subscriptionTitle = sqlite3_column_type(statement, 12) == SQLITE_NULL ? nil : String(cString: sqlite3_column_text(statement, 12))
+ let read = sqlite3_column_int(statement, 13) == 1
+
+ return FeedItem(
+ id: id,
+ title: title,
+ link: link,
+ description: description,
+ content: content,
+ author: author,
+ published: published,
+ updated: updated,
+ categories: categories,
+ enclosure: enclosure,
+ guid: guid,
+ subscriptionId: subscriptionId,
+ subscriptionTitle: subscriptionTitle,
+ read: read
+ )
+ }
+}
+
+// MARK: - SearchHistory CRUD
+
+extension DatabaseManager {
+ func addToSearchHistory(query: String) throws -> SearchHistoryItem {
+ let id = UUID().uuidString
+ let timestamp = ISO8601DateFormatter().string(from: Date())
+ let item = SearchHistoryItem(id: id, query: query, timestamp: Date())
+
+ let insertSQL = "INSERT INTO search_history (id, query, timestamp) VALUES (?, ?, ?)"
+
+ guard let statement = prepareStatement(sql: insertSQL) else {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 2, (query as NSString).utf8String, -1, nil)
+ sqlite3_bind_text(statement, 3, (timestamp as NSString).utf8String, -1, nil)
+
+ if sqlite3_step(statement) != SQLITE_DONE {
+ throw DatabaseError.saveFailed(DatabaseError.objectNotFound)
+ }
+
+ return item
+ }
+
+ func fetchSearchHistory(limit: Int = 20) throws -> [SearchHistoryItem] {
+ let selectSQL = "SELECT * FROM search_history ORDER BY timestamp DESC LIMIT ?"
+ return executeQuery(sql: selectSQL, bindParams: [limit], rowMapper: rowToSearchHistoryItem)
+ }
+
+ func clearSearchHistory() throws {
+ let deleteSQL = "DELETE FROM search_history"
+ var errorMessage: UnsafeMutablePointer?
+ defer { sqlite3_free(errorMessage) }
+ sqlite3_exec(db, deleteSQL, nil, nil, &errorMessage)
+ }
+
+ func deleteSearchHistoryItem(id: String) throws {
+ let deleteSQL = "DELETE FROM search_history WHERE id = ?"
+
+ guard let statement = prepareStatement(sql: deleteSQL) else {
+ return
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (id as NSString).utf8String, -1, nil)
+ sqlite3_step(statement)
+ }
+
+ private func rowToSearchHistoryItem(_ statement: OpaquePointer) -> SearchHistoryItem {
+ let id = String(cString: sqlite3_column_text(statement, 0))
+ let query = String(cString: sqlite3_column_text(statement, 1))
+ let timestamp = parseDate(String(cString: sqlite3_column_text(statement, 2)))
+
+ return SearchHistoryItem(id: id, query: query, timestamp: timestamp)
+ }
+}
+
+// MARK: - FTS Search
+
+extension DatabaseManager {
+ func fullTextSearch(query: String, limit: Int = 50) throws -> [FeedItem] {
+ let selectSQL = """
+ SELECT * FROM feed_items
+ WHERE title LIKE ? OR description LIKE ? OR content LIKE ? OR author LIKE ?
+ ORDER BY published DESC
+ LIMIT ?
+ """
+
+ let pattern = "%\(query)%"
+ return executeQuery(sql: selectSQL, bindParams: [pattern, pattern, pattern, pattern, limit], rowMapper: rowToFeedItem)
+ }
+
+ func advancedSearch(title: String? = nil, author: String? = nil, subscriptionId: String? = nil, startDate: Date? = nil, endDate: Date? = nil, limit: Int = 50) throws -> [FeedItem] {
+ var conditions: [String] = []
+ var parameters: [String] = []
+
+ if let title = title {
+ conditions.append("title LIKE ?")
+ parameters.append("%\(title)%")
+ }
+
+ if let author = author {
+ conditions.append("author LIKE ?")
+ parameters.append("%\(author)%")
+ }
+
+ if let subscriptionId = subscriptionId {
+ conditions.append("subscription_id = ?")
+ parameters.append(subscriptionId)
+ }
+
+ if let startDate = startDate {
+ conditions.append("published >= ?")
+ parameters.append(ISO8601DateFormatter().string(from: startDate))
+ }
+
+ if let endDate = endDate {
+ conditions.append("published <= ?")
+ parameters.append(ISO8601DateFormatter().string(from: endDate))
+ }
+
+ var sql = "SELECT * FROM feed_items"
+ if !conditions.isEmpty {
+ sql += " WHERE " + conditions.joined(separator: " AND ")
+ }
+ sql += " ORDER BY published DESC LIMIT ?"
+ parameters.append(String(limit))
+
+ return executeQuery(sql: sql, bindParams: parameters, rowMapper: rowToFeedItem)
+ }
+}
+
+// MARK: - Batch Operations
+
+extension DatabaseManager {
+ func markAllAsRead(for subscriptionId: String) throws {
+ let updateSQL = "UPDATE feed_items SET read = 1 WHERE subscription_id = ?"
+
+ guard let statement = prepareStatement(sql: updateSQL) else {
+ return
+ }
+
+ defer { sqlite3_finalize(statement) }
+ sqlite3_bind_text(statement, 1, (subscriptionId as NSString).utf8String, -1, nil)
+ sqlite3_step(statement)
+ }
+
+ func cleanupOldItems(olderThan days: Int, for subscriptionId: String? = nil) throws -> Int {
+ let cutoffDate = Calendar.current.date(byAdding: .day, value: -days, to: Date())!
+ let cutoffString = ISO8601DateFormatter().string(from: cutoffDate)
+
+ var sql = "DELETE FROM feed_items WHERE published < ?"
+ var params: [String] = [cutoffString]
+
+ if let subscriptionId = subscriptionId {
+ sql += " AND subscription_id = ?"
+ params.append(subscriptionId)
+ }
+
+ guard let statement = prepareStatement(sql: sql) else {
+ return 0
+ }
+
+ defer { sqlite3_finalize(statement) }
+
+ for (index, param) in params.enumerated() {
+ sqlite3_bind_text(statement, Int32(index + 1), (param as NSString).utf8String, -1, nil)
+ }
+
+ sqlite3_step(statement)
+ return Int(sqlite3_changes(db))
+ }
+}
+
+// MARK: - Helper Methods
+
+extension DatabaseManager {
+ private func prepareStatement(sql: String) -> OpaquePointer? {
+ var statement: OpaquePointer?
+ if sqlite3_prepare_v2(db, sql, -1, &statement, nil) == SQLITE_OK {
+ return statement
+ }
+ return nil
+ }
+
+ private func executeQuery(sql: String, bindParams: [Any], rowMapper: (OpaquePointer) -> T) -> [T] {
+ var results: [T] = []
+
+ guard let statement = prepareStatement(sql: sql) else {
+ return results
+ }
+
+ defer { sqlite3_finalize(statement) }
+
+ for (index, param) in bindParams.enumerated() {
+ let paramIndex = Int32(index + 1)
+ if let stringParam = param as? String {
+ sqlite3_bind_text(statement, paramIndex, (stringParam as NSString).utf8String, -1, nil)
+ } else if let intParam = param as? Int {
+ sqlite3_bind_int(statement, paramIndex, Int32(intParam))
+ }
+ }
+
+ while sqlite3_step(statement) == SQLITE_ROW {
+ results.append(rowMapper(statement))
+ }
+
+ return results
+ }
+
+ private func parseDate(_ string: String) -> Date {
+ let formatter = ISO8601DateFormatter()
+ return formatter.date(from: string) ?? Date()
+ }
+}
diff --git a/iOS/RSSuper/Item.swift b/iOS/RSSuper/Item.swift
new file mode 100644
index 0000000..487c391
--- /dev/null
+++ b/iOS/RSSuper/Item.swift
@@ -0,0 +1,18 @@
+//
+// Item.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+import SwiftData
+
+@Model
+final class Item {
+ var timestamp: Date
+
+ init(timestamp: Date) {
+ self.timestamp = timestamp
+ }
+}
diff --git a/iOS/RSSuper/Models/ContentType.swift b/iOS/RSSuper/Models/ContentType.swift
new file mode 100644
index 0000000..5bacf9e
--- /dev/null
+++ b/iOS/RSSuper/Models/ContentType.swift
@@ -0,0 +1,66 @@
+//
+// ContentType.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+enum ContentType: String, Codable, CaseIterable {
+ case article
+ case audio
+ case video
+
+ var localizedDescription: String {
+ switch self {
+ case .article: return "Article"
+ case .audio: return "Audio"
+ case .video: return "Video"
+ }
+ }
+}
+
+enum Theme: String, Codable, CaseIterable {
+ case system
+ case light
+ case dark
+
+ var localizedDescription: String {
+ switch self {
+ case .system: return "System"
+ case .light: return "Light"
+ case .dark: return "Dark"
+ }
+ }
+}
+
+enum Privacy: String, Codable, CaseIterable {
+ case `public`
+ case `private`
+ case anonymous
+
+ var localizedDescription: String {
+ switch self {
+ case .public: return "Public"
+ case .private: return "Private"
+ case .anonymous: return "Anonymous"
+ }
+ }
+}
+
+enum NotificationType: String, Codable, CaseIterable {
+ case newArticle = "NEW_ARTICLE"
+ case episodeRelease = "EPISODE_RELEASE"
+ case customAlert = "CUSTOM_ALERT"
+ case upgradePromo = "UPGRADE_PROMO"
+
+ var localizedDescription: String {
+ switch self {
+ case .newArticle: return "New Article"
+ case .episodeRelease: return "Episode Release"
+ case .customAlert: return "Custom Alert"
+ case .upgradePromo: return "Upgrade Promo"
+ }
+ }
+}
diff --git a/iOS/RSSuper/Models/Date+Extensions.swift b/iOS/RSSuper/Models/Date+Extensions.swift
new file mode 100644
index 0000000..5e71d08
--- /dev/null
+++ b/iOS/RSSuper/Models/Date+Extensions.swift
@@ -0,0 +1,48 @@
+//
+// Date+Extensions.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+extension Date {
+ /// Creates a Date from Unix timestamp in milliseconds
+ init?(millisecondsSince1970: Int64) {
+ let seconds = TimeInterval(millisecondsSince1970) / 1000.0
+ self.init(timeIntervalSince1970: seconds)
+ }
+
+ /// Returns the Unix timestamp in milliseconds
+ var millisecondsSince1970: Int64 {
+ Int64((timeIntervalSince1970 * 1000).rounded())
+ }
+
+ /// Creates a Date from Unix timestamp in seconds
+ init?(secondsSince1970: Int64) {
+ self.init(timeIntervalSince1970: TimeInterval(secondsSince1970))
+ }
+
+ /// Returns the Unix timestamp in seconds
+ var secondsSince1970: Int64 {
+ Int64(timeIntervalSince1970.rounded())
+ }
+
+ /// ISO8601 formatted string
+ var iso8601String: String {
+ let formatter = ISO8601DateFormatter()
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
+ return formatter.string(from: self)
+ }
+
+ /// Creates a Date from ISO8601 string
+ init?(iso8601String: String) {
+ let formatter = ISO8601DateFormatter()
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
+ guard let date = formatter.date(from: iso8601String) else {
+ return nil
+ }
+ self = date
+ }
+}
diff --git a/iOS/RSSuper/Models/Feed.swift b/iOS/RSSuper/Models/Feed.swift
new file mode 100644
index 0000000..060b806
--- /dev/null
+++ b/iOS/RSSuper/Models/Feed.swift
@@ -0,0 +1,85 @@
+//
+// Feed.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct Feed: Identifiable, Codable, Equatable {
+ let id: String
+ let title: String
+ var link: String?
+ var description: String?
+ var subtitle: String?
+ var language: String?
+ var lastBuildDate: Date?
+ var updated: Date?
+ var generator: String?
+ var ttl: Int?
+ var items: [FeedItem]
+ var rawUrl: String
+ var lastFetchedAt: Date?
+ var nextFetchAt: Date?
+
+ enum CodingKeys: String, CodingKey {
+ case id
+ case title
+ case link
+ case description
+ case subtitle
+ case language
+ case lastBuildDate = "last_build_date"
+ case updated
+ case generator
+ case ttl
+ case items
+ case rawUrl = "raw_url"
+ case lastFetchedAt = "last_fetched_at"
+ case nextFetchAt = "next_fetch_at"
+ }
+
+ init(
+ id: String,
+ title: String,
+ link: String? = nil,
+ description: String? = nil,
+ subtitle: String? = nil,
+ language: String? = nil,
+ lastBuildDate: Date? = nil,
+ updated: Date? = nil,
+ generator: String? = nil,
+ ttl: Int? = nil,
+ items: [FeedItem] = [],
+ rawUrl: String,
+ lastFetchedAt: Date? = nil,
+ nextFetchAt: Date? = nil
+ ) {
+ self.id = id
+ self.title = title
+ self.link = link
+ self.description = description
+ self.subtitle = subtitle
+ self.language = language
+ self.lastBuildDate = lastBuildDate
+ self.updated = updated
+ self.generator = generator
+ self.ttl = ttl
+ self.items = items
+ self.rawUrl = rawUrl
+ self.lastFetchedAt = lastFetchedAt
+ self.nextFetchAt = nextFetchAt
+ }
+
+ var debugDescription: String {
+ """
+ Feed(
+ id: \(id),
+ title: \(title),
+ items: \(items.count),
+ lastFetched: \(lastFetchedAt?.formatted(date: .abbreviated, time: .shortened) ?? "N/A")
+ )
+ """
+ }
+}
diff --git a/iOS/RSSuper/Models/FeedItem.swift b/iOS/RSSuper/Models/FeedItem.swift
new file mode 100644
index 0000000..40eb273
--- /dev/null
+++ b/iOS/RSSuper/Models/FeedItem.swift
@@ -0,0 +1,109 @@
+//
+// FeedItem.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct FeedItem: Identifiable, Codable, Equatable {
+ let id: String
+ let title: String
+ var link: String?
+ var description: String?
+ var content: String?
+ var author: String?
+ var published: Date?
+ var updated: Date?
+ var categories: [String]?
+ var enclosure: Enclosure?
+ var guid: String?
+ var subscriptionId: String
+ var subscriptionTitle: String?
+ var read: Bool = false
+
+ enum CodingKeys: String, CodingKey {
+ case id
+ case title
+ case link
+ case description
+ case content
+ case author
+ case published
+ case updated
+ case categories
+ case enclosure
+ case guid
+ case subscriptionId = "subscription_id"
+ case subscriptionTitle = "subscription_title"
+ case read
+ }
+
+ init(
+ id: String,
+ title: String,
+ link: String? = nil,
+ description: String? = nil,
+ content: String? = nil,
+ author: String? = nil,
+ published: Date? = nil,
+ updated: Date? = nil,
+ categories: [String]? = nil,
+ enclosure: Enclosure? = nil,
+ guid: String? = nil,
+ subscriptionId: String,
+ subscriptionTitle: String? = nil,
+ read: Bool = false
+ ) {
+ self.id = id
+ self.title = title
+ self.link = link
+ self.description = description
+ self.content = content
+ self.author = author
+ self.published = published
+ self.updated = updated
+ self.categories = categories
+ self.enclosure = enclosure
+ self.guid = guid
+ self.subscriptionId = subscriptionId
+ self.subscriptionTitle = subscriptionTitle
+ self.read = read
+ }
+
+ var debugDescription: String {
+ """
+ FeedItem(
+ id: \(id),
+ title: \(title),
+ author: \(author ?? "N/A"),
+ published: \(published?.formatted(date: .abbreviated, time: .shortened) ?? "N/A"),
+ subscription: \(subscriptionTitle ?? "N/A")
+ )
+ """
+ }
+}
+
+struct Enclosure: Codable, Equatable {
+ let url: String
+ let type: String
+ var length: Int64?
+
+ var mimeType: ContentType {
+ if type.contains("audio") {
+ return .audio
+ } else if type.contains("video") {
+ return .video
+ } else {
+ return .article
+ }
+ }
+
+ var fileSizeDescription: String {
+ guard let length = length else { return "Unknown" }
+ let formatter = ByteCountFormatter()
+ formatter.countStyle = .file
+ return formatter.string(fromByteCount: length)
+ }
+}
diff --git a/iOS/RSSuper/Models/FeedSubscription.swift b/iOS/RSSuper/Models/FeedSubscription.swift
new file mode 100644
index 0000000..fa8f88c
--- /dev/null
+++ b/iOS/RSSuper/Models/FeedSubscription.swift
@@ -0,0 +1,89 @@
+//
+// FeedSubscription.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct FeedSubscription: Identifiable, Codable, Equatable {
+ let id: String
+ let url: String
+ var title: String
+ var category: String?
+ var enabled: Bool
+ var fetchInterval: Int
+ let createdAt: Date
+ var updatedAt: Date
+ var lastFetchedAt: Date?
+ var nextFetchAt: Date?
+ var error: String?
+ var httpAuth: HttpAuth?
+
+ enum CodingKeys: String, CodingKey {
+ case id
+ case url
+ case title
+ case category
+ case enabled
+ case fetchInterval = "fetch_interval"
+ case createdAt = "created_at"
+ case updatedAt = "updated_at"
+ case lastFetchedAt = "last_fetched_at"
+ case nextFetchAt = "next_fetch_at"
+ case error
+ case httpAuth = "http_auth"
+ }
+
+ init(
+ id: String,
+ url: String,
+ title: String,
+ category: String? = nil,
+ enabled: Bool = true,
+ fetchInterval: Int = 60,
+ createdAt: Date = Date(),
+ updatedAt: Date = Date(),
+ lastFetchedAt: Date? = nil,
+ nextFetchAt: Date? = nil,
+ error: String? = nil,
+ httpAuth: HttpAuth? = nil
+ ) {
+ self.id = id
+ self.url = url
+ self.title = title
+ self.category = category
+ self.enabled = enabled
+ self.fetchInterval = fetchInterval
+ self.createdAt = createdAt
+ self.updatedAt = updatedAt
+ self.lastFetchedAt = lastFetchedAt
+ self.nextFetchAt = nextFetchAt
+ self.error = error
+ self.httpAuth = httpAuth
+ }
+
+ var debugDescription: String {
+ """
+ FeedSubscription(
+ id: \(id),
+ title: \(title),
+ url: \(url),
+ enabled: \(enabled),
+ fetchInterval: \(fetchInterval)min,
+ error: \(error ?? "None")
+ )
+ """
+ }
+}
+
+struct HttpAuth: Codable, Equatable {
+ let username: String
+ let password: String
+
+ init(username: String, password: String) {
+ self.username = username
+ self.password = password
+ }
+}
diff --git a/iOS/RSSuper/Models/NotificationPreferences.swift b/iOS/RSSuper/Models/NotificationPreferences.swift
new file mode 100644
index 0000000..479098d
--- /dev/null
+++ b/iOS/RSSuper/Models/NotificationPreferences.swift
@@ -0,0 +1,54 @@
+//
+// NotificationPreferences.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct NotificationPreferences: Codable, Equatable {
+ var newArticles: Bool
+ var episodeReleases: Bool
+ var customAlerts: Bool
+ var badgeCount: Bool
+ var sound: Bool
+ var vibration: Bool
+
+ init(
+ newArticles: Bool = true,
+ episodeReleases: Bool = true,
+ customAlerts: Bool = false,
+ badgeCount: Bool = true,
+ sound: Bool = true,
+ vibration: Bool = true
+ ) {
+ self.newArticles = newArticles
+ self.episodeReleases = episodeReleases
+ self.customAlerts = customAlerts
+ self.badgeCount = badgeCount
+ self.sound = sound
+ self.vibration = vibration
+ }
+
+ var allEnabled: Bool {
+ newArticles && episodeReleases && customAlerts && badgeCount && sound && vibration
+ }
+
+ var anyEnabled: Bool {
+ newArticles || episodeReleases || customAlerts || badgeCount || sound || vibration
+ }
+
+ var debugDescription: String {
+ """
+ NotificationPreferences(
+ newArticles: \(newArticles),
+ episodeReleases: \(episodeReleases),
+ customAlerts: \(customAlerts),
+ badgeCount: \(badgeCount),
+ sound: \(sound),
+ vibration: \(vibration)
+ )
+ """
+ }
+}
diff --git a/iOS/RSSuper/Models/ReadingPreferences.swift b/iOS/RSSuper/Models/ReadingPreferences.swift
new file mode 100644
index 0000000..d27e599
--- /dev/null
+++ b/iOS/RSSuper/Models/ReadingPreferences.swift
@@ -0,0 +1,76 @@
+//
+// ReadingPreferences.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct ReadingPreferences: Codable, Equatable {
+ var fontSize: FontSize
+ var lineHeight: LineHeight
+ var showTableOfContents: Bool
+ var showReadingTime: Bool
+ var showAuthor: Bool
+ var showDate: Bool
+
+ enum FontSize: String, Codable, CaseIterable {
+ case small
+ case medium
+ case large
+ case xlarge
+
+ var pointValue: CGFloat {
+ switch self {
+ case .small: return 14
+ case .medium: return 16
+ case .large: return 18
+ case .xlarge: return 20
+ }
+ }
+ }
+
+ enum LineHeight: String, Codable, CaseIterable {
+ case normal
+ case relaxed
+ case loose
+
+ var multiplier: CGFloat {
+ switch self {
+ case .normal: return 1.2
+ case .relaxed: return 1.5
+ case .loose: return 1.8
+ }
+ }
+ }
+
+ init(
+ fontSize: FontSize = .medium,
+ lineHeight: LineHeight = .relaxed,
+ showTableOfContents: Bool = false,
+ showReadingTime: Bool = true,
+ showAuthor: Bool = true,
+ showDate: Bool = true
+ ) {
+ self.fontSize = fontSize
+ self.lineHeight = lineHeight
+ self.showTableOfContents = showTableOfContents
+ self.showReadingTime = showReadingTime
+ self.showAuthor = showAuthor
+ self.showDate = showDate
+ }
+
+ var debugDescription: String {
+ """
+ ReadingPreferences(
+ fontSize: \(fontSize.rawValue),
+ lineHeight: \(lineHeight.rawValue),
+ showTableOfContents: \(showTableOfContents),
+ showReadingTime: \(showReadingTime),
+ showAuthor: \(showAuthor),
+ showDate: \(showDate)
+ )
+ """
+ }
+}
diff --git a/iOS/RSSuper/Models/SearchFilters.swift b/iOS/RSSuper/Models/SearchFilters.swift
new file mode 100644
index 0000000..5c387e1
--- /dev/null
+++ b/iOS/RSSuper/Models/SearchFilters.swift
@@ -0,0 +1,72 @@
+//
+// SearchFilters.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct SearchFilters: Codable, Equatable {
+ var dateFrom: Date?
+ var dateTo: Date?
+ var feedIds: [String]?
+ var authors: [String]?
+ var contentType: ContentType?
+
+ enum CodingKeys: String, CodingKey {
+ case dateFrom = "date_from"
+ case dateTo = "date_to"
+ case feedIds = "feed_ids"
+ case authors
+ case contentType = "content_type"
+ }
+
+ init(
+ dateFrom: Date? = nil,
+ dateTo: Date? = nil,
+ feedIds: [String]? = nil,
+ authors: [String]? = nil,
+ contentType: ContentType? = nil
+ ) {
+ self.dateFrom = dateFrom
+ self.dateTo = dateTo
+ self.feedIds = feedIds
+ self.authors = authors
+ self.contentType = contentType
+ }
+
+ var debugDescription: String {
+ """
+ SearchFilters(
+ dateFrom: \(dateFrom?.formatted(date: .abbreviated, time: .shortened) ?? "N/A"),
+ dateTo: \(dateTo?.formatted(date: .abbreviated, time: .shortened) ?? "N/A"),
+ feedIds: \(feedIds.map { "\($0.count) feeds" } ?? "All"),
+ authors: \(authors.map { "\($0.count) authors" } ?? "All"),
+ contentType: \(contentType?.localizedDescription ?? "All")
+ )
+ """
+ }
+}
+
+enum SearchSortOption: String, Codable, CaseIterable {
+ case relevance = "relevance"
+ case dateDesc = "date_desc"
+ case dateAsc = "date_asc"
+ case titleAsc = "title_asc"
+ case titleDesc = "title_desc"
+ case feedAsc = "feed_asc"
+ case feedDesc = "feed_desc"
+
+ var localizedDescription: String {
+ switch self {
+ case .relevance: return "Relevance"
+ case .dateDesc: return "Date (Newest First)"
+ case .dateAsc: return "Date (Oldest First)"
+ case .titleAsc: return "Title (A-Z)"
+ case .titleDesc: return "Title (Z-A)"
+ case .feedAsc: return "Feed (A-Z)"
+ case .feedDesc: return "Feed (Z-A)"
+ }
+ }
+}
diff --git a/iOS/RSSuper/Models/SearchHistoryItem.swift b/iOS/RSSuper/Models/SearchHistoryItem.swift
new file mode 100644
index 0000000..aff64eb
--- /dev/null
+++ b/iOS/RSSuper/Models/SearchHistoryItem.swift
@@ -0,0 +1,30 @@
+//
+// SearchHistoryItem.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct SearchHistoryItem: Identifiable, Codable, Equatable {
+ let id: String
+ let query: String
+ let timestamp: Date
+
+ init(id: String, query: String, timestamp: Date = Date()) {
+ self.id = id
+ self.query = query
+ self.timestamp = timestamp
+ }
+
+ var debugDescription: String {
+ """
+ SearchHistoryItem(
+ id: \(id),
+ query: \(query),
+ timestamp: \(timestamp.formatted(date: .abbreviated, time: .shortened))
+ )
+ """
+ }
+}
diff --git a/iOS/RSSuper/Models/SearchResult.swift b/iOS/RSSuper/Models/SearchResult.swift
new file mode 100644
index 0000000..75d0400
--- /dev/null
+++ b/iOS/RSSuper/Models/SearchResult.swift
@@ -0,0 +1,73 @@
+//
+// SearchResult.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import Foundation
+
+struct SearchResult: Identifiable, Codable, Equatable {
+ let id: String
+ let type: SearchResultType
+ let title: String
+ var snippet: String?
+ var link: String?
+ var feedTitle: String?
+ var published: Date?
+ var score: Double?
+
+ enum CodingKeys: String, CodingKey {
+ case id
+ case type
+ case title
+ case snippet
+ case link
+ case feedTitle = "feed_title"
+ case published
+ case score
+ }
+
+ init(
+ id: String,
+ type: SearchResultType,
+ title: String,
+ snippet: String? = nil,
+ link: String? = nil,
+ feedTitle: String? = nil,
+ published: Date? = nil,
+ score: Double? = nil
+ ) {
+ self.id = id
+ self.type = type
+ self.title = title
+ self.snippet = snippet
+ self.link = link
+ self.feedTitle = feedTitle
+ self.published = published
+ self.score = score
+ }
+
+ var debugDescription: String {
+ """
+ SearchResult(
+ id: \(id),
+ type: \(type.localizedDescription),
+ title: \(title),
+ score: \(score.map { String($0) } ?? "N/A")
+ )
+ """
+ }
+}
+
+enum SearchResultType: String, Codable, CaseIterable {
+ case article
+ case feed
+
+ var localizedDescription: String {
+ switch self {
+ case .article: return "Article"
+ case .feed: return "Feed"
+ }
+ }
+}
diff --git a/iOS/RSSuper/Networking/01_FetchResult.swift b/iOS/RSSuper/Networking/01_FetchResult.swift
new file mode 100644
index 0000000..5db6e2f
--- /dev/null
+++ b/iOS/RSSuper/Networking/01_FetchResult.swift
@@ -0,0 +1,15 @@
+import Foundation
+
+struct FetchResult {
+ let feedData: Data
+ let headers: [String: String]
+ let url: URL
+ let cached: Bool
+
+ init(feedData: Data, headers: [String: String], url: URL, cached: Bool = false) {
+ self.feedData = feedData
+ self.headers = headers
+ self.url = url
+ self.cached = cached
+ }
+}
diff --git a/iOS/RSSuper/Networking/03_FeedFetcher.swift b/iOS/RSSuper/Networking/03_FeedFetcher.swift
new file mode 100644
index 0000000..504c0c6
--- /dev/null
+++ b/iOS/RSSuper/Networking/03_FeedFetcher.swift
@@ -0,0 +1,172 @@
+import Foundation
+
+final class FeedFetcher {
+ private let session: URLSession
+ private let cacheManager = CacheManager.shared
+ private let timeout: TimeInterval = 15.0
+ private let maxRetries = 3
+ private let maxBackoffDelay: TimeInterval = 60.0
+
+ nonisolated init(session: URLSession = URLSession(configuration: .default)) {
+ self.session = session
+ }
+
+ func fetchFeed(url: URL, credentials: HTTPAuthCredentials? = nil) async throws -> FetchResult {
+ if let cached = cacheManager.getCachedResult(for: url), !isCacheExpired(for: url) {
+ return cached
+ }
+
+ return try await withRetries { retryNumber in
+ try await self.fetchFeedInternal(url: url, credentials: credentials, retryNumber: retryNumber)
+ }
+ }
+
+ private func fetchFeedInternal(url: URL, credentials: HTTPAuthCredentials?, retryNumber: Int) async throws -> FetchResult {
+ var request = URLRequest(url: url)
+ request.timeoutInterval = timeout
+
+ if let credentials {
+ request.setValue(credentials.authorizationHeader(), forHTTPHeaderField: "Authorization")
+ }
+
+ let (data, response) = try await session.data(for: request)
+
+ guard let httpResponse = response as? HTTPURLResponse else {
+ throw NetworkError.noData
+ }
+
+ switch httpResponse.statusCode {
+ case 200...299:
+ let headers = httpResponse.allHeaderFields.reduce(into: [String: String]()) { result, pair in
+ if let key = pair.key as? String, let value = pair.value as? String {
+ result[key] = value
+ }
+ }
+
+ let result = FetchResult(
+ feedData: data,
+ headers: headers,
+ url: url,
+ cached: false
+ )
+
+ if shouldCacheResponse(httpResponse: httpResponse) {
+ cacheManager.cacheResult(result, for: url)
+ }
+
+ return result
+
+ case 401:
+ throw NetworkError.authenticationError
+ case 404:
+ throw NetworkError.httpError(statusCode: 404)
+ case 408:
+ throw NetworkError.timeout
+ case 500...599:
+ throw NetworkError.httpError(statusCode: httpResponse.statusCode)
+ default:
+ throw NetworkError.httpError(statusCode: httpResponse.statusCode)
+ }
+ }
+
+ private func withRetries(_ operation: @escaping (Int) async throws -> T) async throws -> T {
+ var lastError: Error?
+
+ for attempt in 0...maxRetries {
+ if attempt > 0 {
+ let delay = calculateBackoffDelay(attempt: attempt)
+ try await Task.sleep(for: .seconds(delay))
+ }
+
+ do {
+ return try await operation(attempt)
+ } catch {
+ lastError = error
+ let networkError = error as? NetworkError
+ if !shouldRetry(error: networkError) {
+ throw error
+ }
+ }
+ }
+
+ throw lastError ?? NetworkError.noData
+ }
+
+ private func shouldRetry(error: NetworkError?) -> Bool {
+ guard let error else { return false }
+ switch error {
+ case .timeout, .httpError(_), .noData:
+ return true
+ case .invalidURL, .decodingError, .authenticationError, .cacheError:
+ return false
+ }
+ }
+
+ private func calculateBackoffDelay(attempt: Int) -> TimeInterval {
+ let baseDelay: TimeInterval = 0.5
+ let delay = baseDelay * pow(2, Double(attempt))
+ return min(delay, maxBackoffDelay)
+ }
+
+ private func isCacheExpired(for url: URL) -> Bool {
+ guard let cached = cacheManager.getCachedResult(for: url) else { return true }
+
+ if let cacheControl = cached.headers["Cache-Control"] ?? cached.headers["cache-control"] {
+ if cacheControl.contains("no-store") {
+ return true
+ }
+ if cacheControl.contains("no-cache") {
+ return true
+ }
+ if let maxAge = extractMaxAge(from: cacheControl) {
+ let age = Date().timeIntervalSince(cached.url.lastPathComponent.isEmpty ? Date() : Date())
+ return age > maxAge
+ }
+ }
+
+ if let lastModified = cached.headers["Last-Modified"] ?? cached.headers["last-modified"],
+ let cacheUntil = parseHTTPDate(lastModified) {
+ return Date() > cacheUntil
+ }
+
+ return false
+ }
+
+ private func shouldCacheResponse(httpResponse: HTTPURLResponse) -> Bool {
+ guard let cacheControl = httpResponse.allHeaderFields["Cache-Control"] as? String else {
+ return httpResponse.statusCode == 200
+ }
+
+ if cacheControl.contains("no-store") {
+ return false
+ }
+
+ return true
+ }
+
+ private func extractMaxAge(from cacheControl: String) -> TimeInterval? {
+ let parts = cacheControl.split(separator: ",")
+ for part in parts {
+ let trimmed = part.trimmingCharacters(in: .whitespaces)
+ if trimmed.starts(with: "max-age=") {
+ let valueString = trimmed.dropFirst(8)
+ return Double(String(valueString))
+ }
+ }
+ return nil
+ }
+
+ private func parseHTTPDate(_ dateString: String) -> Date? {
+ let formatter = HTTPDateFormatter.formatter
+ return formatter.date(from: dateString)
+ }
+}
+
+private class HTTPDateFormatter {
+ static let formatter: DateFormatter = {
+ let df = DateFormatter()
+ df.locale = Locale(identifier: "en_US_POSIX")
+ df.dateFormat = "EEE, dd MMM yyyy HH:mm:ss Z"
+ return df
+ }()
+}
diff --git a/iOS/RSSuper/Networking/CacheManager.swift b/iOS/RSSuper/Networking/CacheManager.swift
new file mode 100644
index 0000000..4ced8a7
--- /dev/null
+++ b/iOS/RSSuper/Networking/CacheManager.swift
@@ -0,0 +1,37 @@
+import Foundation
+
+final class CacheManager {
+ static let shared = CacheManager()
+
+ private var cache = [String: FetchResult]()
+ private let lock = NSLock()
+
+ private init() {}
+
+ func getCachedResult(for url: URL) -> FetchResult? {
+ let key = url.absoluteString
+ lock.lock()
+ defer { lock.unlock() }
+ return cache[key]
+ }
+
+ func cacheResult(_ result: FetchResult, for url: URL) {
+ let key = url.absoluteString
+ lock.lock()
+ defer { lock.unlock() }
+ cache[key] = result
+ }
+
+ func removeCachedResult(for url: URL) {
+ let key = url.absoluteString
+ lock.lock()
+ defer { lock.unlock() }
+ cache.removeValue(forKey: key)
+ }
+
+ func clearAll() {
+ lock.lock()
+ defer { lock.unlock() }
+ cache.removeAll()
+ }
+}
diff --git a/iOS/RSSuper/Networking/HTTPAuthCredentials.swift b/iOS/RSSuper/Networking/HTTPAuthCredentials.swift
new file mode 100644
index 0000000..838a358
--- /dev/null
+++ b/iOS/RSSuper/Networking/HTTPAuthCredentials.swift
@@ -0,0 +1,20 @@
+import Foundation
+
+nonisolated(unsafe) struct HTTPAuthCredentials {
+ let username: String
+ let password: String
+
+ nonisolated init(username: String, password: String) {
+ self.username = username
+ self.password = password
+ }
+
+ nonisolated func authorizationHeader() -> String {
+ let credentials = "\(username):\(password)"
+ guard let data = credentials.data(using: .utf8) else {
+ return ""
+ }
+ let base64 = data.base64EncodedString()
+ return "Basic \(base64)"
+ }
+}
diff --git a/iOS/RSSuper/Networking/NetworkError.swift b/iOS/RSSuper/Networking/NetworkError.swift
new file mode 100644
index 0000000..609613c
--- /dev/null
+++ b/iOS/RSSuper/Networking/NetworkError.swift
@@ -0,0 +1,32 @@
+import Foundation
+
+enum NetworkError: Error {
+ case invalidURL
+ case timeout
+ case httpError(statusCode: Int)
+ case noData
+ case decodingError(Error)
+ case authenticationError
+ case cacheError(Error)
+}
+
+extension NetworkError: LocalizedError {
+ var errorDescription: String? {
+ switch self {
+ case .invalidURL:
+ return "Invalid URL"
+ case .timeout:
+ return "Request timeout"
+ case .httpError(let statusCode):
+ return "HTTP error: \(statusCode)"
+ case .noData:
+ return "No data received"
+ case .decodingError(let error):
+ return "Decoding error: \(error.localizedDescription)"
+ case .authenticationError:
+ return "Authentication failed"
+ case .cacheError(let error):
+ return "Cache error: \(error.localizedDescription)"
+ }
+ }
+}
diff --git a/iOS/RSSuper/Parsing/AtomParser.swift b/iOS/RSSuper/Parsing/AtomParser.swift
new file mode 100644
index 0000000..8c7f480
--- /dev/null
+++ b/iOS/RSSuper/Parsing/AtomParser.swift
@@ -0,0 +1,100 @@
+import Foundation
+
+final class AtomParser {
+ nonisolated init() {}
+
+ nonisolated func parse(xml: String, sourceURL: String) throws -> Feed {
+ let lowered = xml.lowercased()
+ guard lowered.contains("") else {
+ throw FeedParsingError.malformedXML
+ }
+
+ guard let feedBlock = xmlFirstBlock("feed", in: xml) else {
+ throw FeedParsingError.malformedXML
+ }
+
+ let entryBlocks = xmlAllBlocks("entry", in: feedBlock)
+ let feedWithoutEntries = feedBlock.replacingOccurrences(
+ of: "(?is)<(?:\\w+:)?entry\\b[^>]*>.*?(?:\\w+:)?entry>",
+ with: "",
+ options: .regularExpression
+ )
+
+ let feedTitle = xmlFirstTagValue("title", in: feedWithoutEntries)?.xmlNilIfEmpty ?? sourceURL
+ let feedLink = selectAlternateLink(in: feedWithoutEntries)
+ let items = entryBlocks.map { parseEntry(xml: $0, subscriptionId: sourceURL, subscriptionTitle: feedTitle) }
+
+ return Feed(
+ id: sourceURL,
+ title: feedTitle,
+ link: feedLink,
+ description: xmlFirstTagValue("summary", in: feedWithoutEntries)?.xmlNilIfEmpty,
+ subtitle: xmlFirstTagValue("subtitle", in: feedWithoutEntries)?.xmlNilIfEmpty,
+ updated: XMLDateParser.parse(xmlFirstTagValue("updated", in: feedWithoutEntries)),
+ generator: xmlFirstTagValue("generator", in: feedWithoutEntries)?.xmlNilIfEmpty,
+ items: items,
+ rawUrl: sourceURL
+ )
+ }
+
+ nonisolated private func parseEntry(xml: String, subscriptionId: String, subscriptionTitle: String) -> FeedItem {
+ let title = xmlFirstTagValue("title", in: xml)?.xmlNilIfEmpty
+ let link = selectAlternateLink(in: xml)
+ let guid = xmlFirstTagValue("id", in: xml)?.xmlNilIfEmpty
+ let resolvedId = guid ?? link ?? UUID().uuidString
+
+ return FeedItem(
+ id: resolvedId,
+ title: title ?? link ?? "(Untitled)",
+ link: link,
+ description: xmlFirstTagValue("summary", in: xml)?.xmlNilIfEmpty,
+ content: xmlFirstTagValue("content", in: xml)?.xmlNilIfEmpty,
+ author: xmlFirstTagValue("name", in: xml)?.xmlNilIfEmpty
+ ?? xmlFirstTagValue("author", in: xml)?.xmlNilIfEmpty,
+ published: XMLDateParser.parse(xmlFirstTagValue("published", in: xml)),
+ updated: XMLDateParser.parse(xmlFirstTagValue("updated", in: xml)),
+ categories: parseCategories(in: xml),
+ enclosure: parseEnclosure(in: xml),
+ guid: guid,
+ subscriptionId: subscriptionId,
+ subscriptionTitle: subscriptionTitle
+ )
+ }
+
+ nonisolated private func parseCategories(in xml: String) -> [String]? {
+ var values = xmlAllTagValues("category", in: xml)
+ let attributes = xmlAllTagAttributes("category", in: xml)
+
+ for attribute in attributes {
+ if let term = attribute["term"]?.xmlNilIfEmpty {
+ values.append(term)
+ }
+ }
+
+ return values.isEmpty ? nil : values
+ }
+
+ nonisolated private func parseEnclosure(in xml: String) -> Enclosure? {
+ let links = xmlAllTagAttributes("link", in: xml)
+ guard let enclosure = links.first(where: { $0["rel"]?.lowercased() == "enclosure" }) else {
+ return nil
+ }
+
+ guard let href = enclosure["href"]?.xmlNilIfEmpty else { return nil }
+ let type = enclosure["type"]?.xmlNilIfEmpty ?? "application/octet-stream"
+ return Enclosure(url: href, type: type, length: xmlInt64(enclosure["length"]))
+ }
+
+ nonisolated private func selectAlternateLink(in xml: String) -> String? {
+ let links = xmlAllTagAttributes("link", in: xml)
+
+ if let preferred = links.first(where: {
+ let rel = $0["rel"]?.lowercased() ?? "alternate"
+ return rel == "alternate"
+ }) {
+ return preferred["href"]?.xmlNilIfEmpty
+ }
+
+ return links.first?["href"]?.xmlNilIfEmpty
+ }
+}
diff --git a/iOS/RSSuper/Parsing/FeedParser.swift b/iOS/RSSuper/Parsing/FeedParser.swift
new file mode 100644
index 0000000..a9c426c
--- /dev/null
+++ b/iOS/RSSuper/Parsing/FeedParser.swift
@@ -0,0 +1,37 @@
+import Foundation
+
+final class FeedParser {
+ nonisolated init() {}
+
+ nonisolated func parse(data: Data, sourceURL: String) throws -> ParseResult {
+ let xml = String(decoding: data, as: UTF8.self)
+ let feedType = try detectFeedType(from: xml)
+
+ switch feedType {
+ case .rss:
+ let feed = try RSSParser().parse(xml: xml, sourceURL: sourceURL)
+ return ParseResult(feedType: .rss, feed: feed)
+ case .atom:
+ let feed = try AtomParser().parse(xml: xml, sourceURL: sourceURL)
+ return ParseResult(feedType: .atom, feed: feed)
+ }
+ }
+
+ nonisolated private func detectFeedType(from xml: String) throws -> FeedType {
+ let lowered = xml.lowercased()
+
+ if lowered.contains(" Feed {
+ let lowered = xml.lowercased()
+ guard lowered.contains("") else {
+ throw FeedParsingError.malformedXML
+ }
+
+ guard let channel = xmlFirstBlock("channel", in: xml) else {
+ throw FeedParsingError.malformedXML
+ }
+
+ let itemBlocks = xmlAllBlocks("item", in: channel)
+ let channelWithoutItems = channel.replacingOccurrences(
+ of: "(?is)<(?:\\w+:)?item\\b[^>]*>.*?(?:\\w+:)?item>",
+ with: "",
+ options: .regularExpression
+ )
+
+ let title = xmlFirstTagValue("title", in: channelWithoutItems)?.xmlNilIfEmpty ?? sourceURL
+ let feedDescription = xmlFirstTagValue("description", in: channelWithoutItems)?.xmlNilIfEmpty
+ ?? xmlFirstTagValue("summary", in: channelWithoutItems)?.xmlNilIfEmpty
+ let subtitle = xmlFirstTagValue("subtitle", in: channelWithoutItems)?.xmlNilIfEmpty
+ let items = itemBlocks.map { parseItem(xml: $0, subscriptionId: sourceURL, subscriptionTitle: title) }
+
+ return Feed(
+ id: sourceURL,
+ title: title,
+ link: xmlFirstTagValue("link", in: channelWithoutItems)?.xmlNilIfEmpty,
+ description: feedDescription,
+ subtitle: subtitle,
+ language: xmlFirstTagValue("language", in: channelWithoutItems)?.xmlNilIfEmpty,
+ lastBuildDate: XMLDateParser.parse(xmlFirstTagValue("lastBuildDate", in: channelWithoutItems)),
+ generator: xmlFirstTagValue("generator", in: channelWithoutItems)?.xmlNilIfEmpty,
+ ttl: Int(xmlFirstTagValue("ttl", in: channelWithoutItems) ?? ""),
+ items: items,
+ rawUrl: sourceURL
+ )
+ }
+
+ nonisolated private func parseItem(xml: String, subscriptionId: String, subscriptionTitle: String) -> FeedItem {
+ let title = xmlFirstTagValue("title", in: xml)?.xmlNilIfEmpty
+ let link = xmlFirstTagValue("link", in: xml)?.xmlNilIfEmpty
+ let guid = xmlFirstTagValue("guid", in: xml)?.xmlNilIfEmpty
+ let resolvedId = guid ?? link ?? UUID().uuidString
+
+ let enclosureAttributes = xmlAllTagAttributes("enclosure", in: xml).first
+ let enclosure = makeEnclosure(attributes: enclosureAttributes)
+
+ let description = xmlFirstTagValue("description", in: xml)?.xmlNilIfEmpty
+ ?? xmlFirstTagValue("summary", in: xml)?.xmlNilIfEmpty
+
+ return FeedItem(
+ id: resolvedId,
+ title: title ?? link ?? "(Untitled)",
+ link: link,
+ description: description,
+ content: xmlFirstTagValue("encoded", in: xml)?.xmlNilIfEmpty,
+ author: xmlFirstTagValue("author", in: xml)?.xmlNilIfEmpty
+ ?? xmlFirstTagValue("creator", in: xml)?.xmlNilIfEmpty,
+ published: XMLDateParser.parse(xmlFirstTagValue("pubDate", in: xml)),
+ categories: xmlAllTagValues("category", in: xml).isEmpty ? nil : xmlAllTagValues("category", in: xml),
+ enclosure: enclosure,
+ guid: guid,
+ subscriptionId: subscriptionId,
+ subscriptionTitle: subscriptionTitle
+ )
+ }
+
+ nonisolated private func makeEnclosure(attributes: [String: String]?) -> Enclosure? {
+ guard
+ let attributes,
+ let url = attributes["url"]?.xmlNilIfEmpty,
+ let type = attributes["type"]?.xmlNilIfEmpty
+ else {
+ return nil
+ }
+
+ return Enclosure(url: url, type: type, length: xmlInt64(attributes["length"]))
+ }
+}
diff --git a/iOS/RSSuper/Parsing/XMLParsingUtilities.swift b/iOS/RSSuper/Parsing/XMLParsingUtilities.swift
new file mode 100644
index 0000000..44e3a23
--- /dev/null
+++ b/iOS/RSSuper/Parsing/XMLParsingUtilities.swift
@@ -0,0 +1,145 @@
+import Foundation
+
+struct XMLDateParser {
+ nonisolated(unsafe) private static let iso8601WithFractional: ISO8601DateFormatter = {
+ let formatter = ISO8601DateFormatter()
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
+ return formatter
+ }()
+
+ nonisolated(unsafe) private static let iso8601: ISO8601DateFormatter = {
+ let formatter = ISO8601DateFormatter()
+ formatter.formatOptions = [.withInternetDateTime]
+ return formatter
+ }()
+
+ nonisolated(unsafe) private static let dateFormatters: [DateFormatter] = {
+ let formats = [
+ "EEE, dd MMM yyyy HH:mm:ss Z",
+ "EEE, dd MMM yyyy HH:mm Z",
+ "yyyy-MM-dd'T'HH:mm:ssZ",
+ "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
+ "yyyy-MM-dd HH:mm:ss Z"
+ ]
+
+ return formats.map { format in
+ let formatter = DateFormatter()
+ formatter.locale = Locale(identifier: "en_US_POSIX")
+ formatter.timeZone = TimeZone(secondsFromGMT: 0)
+ formatter.dateFormat = format
+ return formatter
+ }
+ }()
+
+ nonisolated(unsafe) static func parse(_ value: String?) -> Date? {
+ guard let raw = value?.xmlTrimmed, !raw.isEmpty else { return nil }
+
+ if let date = iso8601WithFractional.date(from: raw) { return date }
+ if let date = iso8601.date(from: raw) { return date }
+
+ for formatter in dateFormatters {
+ if let date = formatter.date(from: raw) {
+ return date
+ }
+ }
+
+ return nil
+ }
+}
+
+extension String {
+ nonisolated(unsafe) var xmlTrimmed: String {
+ trimmingCharacters(in: .whitespacesAndNewlines)
+ }
+
+ nonisolated(unsafe) var xmlNilIfEmpty: String? {
+ let trimmed = xmlTrimmed
+ return trimmed.isEmpty ? nil : trimmed
+ }
+
+ nonisolated(unsafe) var xmlDecoded: String {
+ replacingOccurrences(of: "", with: "")
+ .replacingOccurrences(of: "<", with: "<")
+ .replacingOccurrences(of: ">", with: ">")
+ .replacingOccurrences(of: "&", with: "&")
+ .replacingOccurrences(of: """, with: "\"")
+ .replacingOccurrences(of: "'", with: "'")
+ }
+}
+
+nonisolated(unsafe) func xmlInt64(_ value: String?) -> Int64? {
+ guard let value = value?.xmlTrimmed, !value.isEmpty else { return nil }
+ return Int64(value)
+}
+
+nonisolated(unsafe) func xmlFirstTagValue(_ tag: String, in xml: String) -> String? {
+ let pattern = "(?is)<(?:\\w+:)?\(tag)\\b[^>]*>(.*?)(?:\\w+:)?\(tag)>"
+ guard let value = xmlFirstCapture(pattern: pattern, in: xml) else { return nil }
+ return value.xmlDecoded.xmlTrimmed
+}
+
+nonisolated(unsafe) func xmlAllTagValues(_ tag: String, in xml: String) -> [String] {
+ let pattern = "(?is)<(?:\\w+:)?\(tag)\\b[^>]*>(.*?)(?:\\w+:)?\(tag)>"
+ return xmlAllCaptures(pattern: pattern, in: xml)
+ .map { $0.xmlDecoded.xmlTrimmed }
+ .filter { !$0.isEmpty }
+}
+
+nonisolated(unsafe) func xmlFirstBlock(_ tag: String, in xml: String) -> String? {
+ let pattern = "(?is)<(?:\\w+:)?\(tag)\\b[^>]*>(.*?)(?:\\w+:)?\(tag)>"
+ return xmlFirstCapture(pattern: pattern, in: xml)
+}
+
+nonisolated(unsafe) func xmlAllBlocks(_ tag: String, in xml: String) -> [String] {
+ let pattern = "(?is)<(?:\\w+:)?\(tag)\\b[^>]*>(.*?)(?:\\w+:)?\(tag)>"
+ return xmlAllCaptures(pattern: pattern, in: xml)
+}
+
+nonisolated(unsafe) func xmlAllTagAttributes(_ tag: String, in xml: String) -> [[String: String]] {
+ let pattern = "(?is)<(?:\\w+:)?\(tag)\\b([^>]*)/?>"
+ return xmlAllCaptures(pattern: pattern, in: xml).map(parseXMLAttributes)
+}
+
+nonisolated(unsafe) private func xmlFirstCapture(pattern: String, in text: String) -> String? {
+ guard
+ let regex = try? NSRegularExpression(pattern: pattern),
+ let match = regex.firstMatch(in: text, range: NSRange(text.startIndex..., in: text)),
+ let range = Range(match.range(at: 1), in: text)
+ else {
+ return nil
+ }
+
+ return String(text[range])
+}
+
+nonisolated(unsafe) private func xmlAllCaptures(pattern: String, in text: String) -> [String] {
+ guard let regex = try? NSRegularExpression(pattern: pattern) else { return [] }
+
+ return regex.matches(in: text, range: NSRange(text.startIndex..., in: text)).compactMap { match in
+ guard let range = Range(match.range(at: 1), in: text) else { return nil }
+ return String(text[range])
+ }
+}
+
+nonisolated(unsafe) private func parseXMLAttributes(_ raw: String) -> [String: String] {
+ guard let regex = try? NSRegularExpression(pattern: "(\\w+(?::\\w+)?)\\s*=\\s*\"([^\"]*)\"") else {
+ return [:]
+ }
+
+ var result: [String: String] = [:]
+ for match in regex.matches(in: raw, range: NSRange(raw.startIndex..., in: raw)) {
+ guard
+ let keyRange = Range(match.range(at: 1), in: raw),
+ let valueRange = Range(match.range(at: 2), in: raw)
+ else {
+ continue
+ }
+
+ let key = String(raw[keyRange]).lowercased()
+ let value = String(raw[valueRange]).xmlDecoded.xmlTrimmed
+ result[key] = value
+ }
+
+ return result
+}
diff --git a/iOS/RSSuper/RSSuperApp.swift b/iOS/RSSuper/RSSuperApp.swift
new file mode 100644
index 0000000..b5193ca
--- /dev/null
+++ b/iOS/RSSuper/RSSuperApp.swift
@@ -0,0 +1,32 @@
+//
+// RSSuperApp.swift
+// RSSuper
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import SwiftUI
+import SwiftData
+
+@main
+struct RSSuperApp: App {
+ var sharedModelContainer: ModelContainer = {
+ let schema = Schema([
+ Item.self,
+ ])
+ let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false)
+
+ do {
+ return try ModelContainer(for: schema, configurations: [modelConfiguration])
+ } catch {
+ fatalError("Could not create ModelContainer: \(error)")
+ }
+ }()
+
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ .modelContainer(sharedModelContainer)
+ }
+}
diff --git a/iOS/RSSuperTests/DatabaseManagerTests.swift b/iOS/RSSuperTests/DatabaseManagerTests.swift
new file mode 100644
index 0000000..392fab4
--- /dev/null
+++ b/iOS/RSSuperTests/DatabaseManagerTests.swift
@@ -0,0 +1,395 @@
+//
+// DatabaseManagerTests.swift
+// RSSuperTests
+//
+// Created on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class DatabaseManagerTests: XCTestCase {
+
+ private var databaseManager: DatabaseManager!
+ private var testSubscriptionId: String!
+
+ override func setUp() {
+ super.setUp()
+ databaseManager = DatabaseManager.shared
+ testSubscriptionId = UUID().uuidString
+
+ // Clean up any existing test data
+ try? databaseManager.deleteSubscription(id: testSubscriptionId)
+ }
+
+ override func tearDown() {
+ // Clean up test data
+ try? databaseManager.deleteSubscription(id: testSubscriptionId)
+ databaseManager = nil
+ super.tearDown()
+ }
+
+ // MARK: - Subscription CRUD Tests
+
+ func testCreateSubscription() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com/feed.xml",
+ title: "Test Subscription",
+ category: "Technology",
+ enabled: true,
+ fetchInterval: 3600
+ )
+
+ XCTAssertEqual(subscription.id, testSubscriptionId)
+ XCTAssertEqual(subscription.url, "https://example.com/feed.xml")
+ XCTAssertEqual(subscription.title, "Test Subscription")
+ XCTAssertEqual(subscription.category, "Technology")
+ XCTAssertTrue(subscription.enabled)
+ XCTAssertEqual(subscription.fetchInterval, 3600)
+ }
+
+ func testFetchSubscription() throws {
+ // Create first
+ _ = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com/feed.xml",
+ title: "Test Subscription"
+ )
+
+ // Fetch
+ let fetched = try databaseManager.fetchSubscription(id: testSubscriptionId)
+
+ XCTAssertNotNil(fetched)
+ XCTAssertEqual(fetched?.id, testSubscriptionId)
+ XCTAssertEqual(fetched?.title, "Test Subscription")
+ }
+
+ func testFetchSubscriptionNotFound() throws {
+ let fetched = try databaseManager.fetchSubscription(id: "non-existent-id")
+ XCTAssertNil(fetched)
+ }
+
+ func testFetchAllSubscriptions() throws {
+ let id1 = UUID().uuidString
+ let id2 = UUID().uuidString
+
+ try databaseManager.createSubscription(id: id1, url: "https://example1.com", title: "Sub 1")
+ try databaseManager.createSubscription(id: id2, url: "https://example2.com", title: "Sub 2")
+
+ let subscriptions = try databaseManager.fetchAllSubscriptions()
+
+ XCTAssertGreaterThanOrEqual(subscriptions.count, 2)
+
+ // Cleanup
+ try databaseManager.deleteSubscription(id: id1)
+ try databaseManager.deleteSubscription(id: id2)
+ }
+
+ func testFetchEnabledSubscriptions() throws {
+ let id1 = UUID().uuidString
+ let id2 = UUID().uuidString
+
+ try databaseManager.createSubscription(id: id1, url: "https://example1.com", title: "Sub 1", enabled: true)
+ try databaseManager.createSubscription(id: id2, url: "https://example2.com", title: "Sub 2", enabled: false)
+
+ let subscriptions = try databaseManager.fetchEnabledSubscriptions()
+
+ XCTAssertTrue(subscriptions.allSatisfy { $0.enabled })
+
+ // Cleanup
+ try databaseManager.deleteSubscription(id: id1)
+ try databaseManager.deleteSubscription(id: id2)
+ }
+
+ func testUpdateSubscription() throws {
+ _ = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Original Title"
+ )
+
+ let updated = try databaseManager.updateSubscription(
+ try databaseManager.fetchSubscription(id: testSubscriptionId)!,
+ title: "Updated Title",
+ enabled: false
+ )
+
+ XCTAssertEqual(updated.title, "Updated Title")
+ XCTAssertFalse(updated.enabled)
+ }
+
+ func testDeleteSubscription() throws {
+ _ = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "To Delete"
+ )
+
+ try databaseManager.deleteSubscription(id: testSubscriptionId)
+
+ let fetched = try databaseManager.fetchSubscription(id: testSubscriptionId)
+ XCTAssertNil(fetched)
+ }
+
+ // MARK: - FeedItem CRUD Tests
+
+ func testCreateFeedItem() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let item = FeedItem(
+ id: UUID().uuidString,
+ title: "Test Article",
+ link: "https://example.com/article",
+ description: "Article description",
+ content: "Full article content",
+ author: "John Doe",
+ published: Date(),
+ subscriptionId: subscription.id,
+ subscriptionTitle: subscription.title
+ )
+
+ let created = try databaseManager.createFeedItem(item)
+
+ XCTAssertEqual(created.id, item.id)
+ XCTAssertEqual(created.title, "Test Article")
+ XCTAssertEqual(created.subscriptionId, testSubscriptionId)
+ }
+
+ func testFetchFeedItem() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let itemId = UUID().uuidString
+ let item = FeedItem(
+ id: itemId,
+ title: "To Fetch",
+ subscriptionId: subscription.id
+ )
+ _ = try databaseManager.createFeedItem(item)
+
+ let fetched = try databaseManager.fetchFeedItem(id: itemId)
+
+ XCTAssertNotNil(fetched)
+ XCTAssertEqual(fetched?.id, itemId)
+ }
+
+ func testFetchFeedItemsForSubscription() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ for i in 1...3 {
+ let item = FeedItem(
+ id: UUID().uuidString,
+ title: "Article \(i)",
+ subscriptionId: subscription.id
+ )
+ _ = try databaseManager.createFeedItem(item)
+ }
+
+ let items = try databaseManager.fetchFeedItems(for: testSubscriptionId)
+
+ XCTAssertEqual(items.count, 3)
+ }
+
+ func testFetchUnreadFeedItems() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let readItem = FeedItem(id: UUID().uuidString, title: "Read", subscriptionId: subscription.id, read: true)
+ let unreadItem = FeedItem(id: UUID().uuidString, title: "Unread", subscriptionId: subscription.id, read: false)
+
+ _ = try databaseManager.createFeedItem(readItem)
+ _ = try databaseManager.createFeedItem(unreadItem)
+
+ let unreadItems = try databaseManager.fetchUnreadFeedItems()
+
+ XCTAssertTrue(unreadItems.allSatisfy { !$0.read })
+ }
+
+ func testMarkAsRead() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let item1 = FeedItem(id: UUID().uuidString, title: "Item 1", subscriptionId: subscription.id, read: false)
+ let item2 = FeedItem(id: UUID().uuidString, title: "Item 2", subscriptionId: subscription.id, read: false)
+
+ _ = try databaseManager.createFeedItem(item1)
+ _ = try databaseManager.createFeedItem(item2)
+
+ try databaseManager.markAsRead(ids: [item1.id, item2.id])
+
+ let fetched1 = try databaseManager.fetchFeedItem(id: item1.id)
+ let fetched2 = try databaseManager.fetchFeedItem(id: item2.id)
+
+ XCTAssertTrue(fetched1?.read ?? false)
+ XCTAssertTrue(fetched2?.read ?? false)
+ }
+
+ func testDeleteFeedItem() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let item = FeedItem(id: UUID().uuidString, title: "To Delete", subscriptionId: subscription.id)
+ _ = try databaseManager.createFeedItem(item)
+
+ try databaseManager.deleteFeedItem(id: item.id)
+
+ let fetched = try databaseManager.fetchFeedItem(id: item.id)
+ XCTAssertNil(fetched)
+ }
+
+ // MARK: - SearchHistory Tests
+
+ func testAddToSearchHistory() throws {
+ let item = try databaseManager.addToSearchHistory(query: "test query")
+
+ XCTAssertEqual(item.query, "test query")
+ XCTAssertNotNil(item.id)
+ }
+
+ func testFetchSearchHistory() throws {
+ try databaseManager.addToSearchHistory(query: "Query 1")
+ try databaseManager.addToSearchHistory(query: "Query 2")
+
+ let history = try databaseManager.fetchSearchHistory()
+
+ XCTAssertGreaterThanOrEqual(history.count, 2)
+ }
+
+ func testClearSearchHistory() throws {
+ try databaseManager.addToSearchHistory(query: "To Clear")
+ try databaseManager.clearSearchHistory()
+
+ let history = try databaseManager.fetchSearchHistory()
+ XCTAssertTrue(history.isEmpty)
+ }
+
+ // MARK: - FTS Search Tests
+
+ func testFullTextSearch() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let searchableItem = FeedItem(
+ id: UUID().uuidString,
+ title: "Unique Title for Search Test",
+ description: "This has special content",
+ subscriptionId: subscription.id
+ )
+ let nonMatchingItem = FeedItem(
+ id: UUID().uuidString,
+ title: "Completely Different",
+ subscriptionId: subscription.id
+ )
+
+ _ = try databaseManager.createFeedItem(searchableItem)
+ _ = try databaseManager.createFeedItem(nonMatchingItem)
+
+ let results = try databaseManager.fullTextSearch(query: "Unique")
+
+ XCTAssertTrue(results.contains { $0.id == searchableItem.id || $0.title.contains("Unique") })
+ XCTAssertFalse(results.contains { $0.id == nonMatchingItem.id })
+ }
+
+ func testAdvancedSearch() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let item1 = FeedItem(
+ id: UUID().uuidString,
+ title: "Searchable Title",
+ author: "Test Author",
+ subscriptionId: subscription.id
+ )
+ let item2 = FeedItem(
+ id: UUID().uuidString,
+ title: "Different Title",
+ author: "Other Author",
+ subscriptionId: subscription.id
+ )
+
+ _ = try databaseManager.createFeedItem(item1)
+ _ = try databaseManager.createFeedItem(item2)
+
+ let results = try databaseManager.advancedSearch(title: "Searchable", author: "Test")
+
+ XCTAssertTrue(results.contains { $0.id == item1.id })
+ XCTAssertFalse(results.contains { $0.id == item2.id })
+ }
+
+ // MARK: - Batch Operations Tests
+
+ func testMarkAllAsRead() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ _ = try databaseManager.createFeedItem(FeedItem(id: UUID().uuidString, title: "Item 1", subscriptionId: subscription.id, read: false))
+ _ = try databaseManager.createFeedItem(FeedItem(id: UUID().uuidString, title: "Item 2", subscriptionId: subscription.id, read: false))
+
+ try databaseManager.markAllAsRead(for: testSubscriptionId)
+
+ let items = try databaseManager.fetchFeedItems(for: testSubscriptionId)
+ XCTAssertTrue(items.allSatisfy { $0.read })
+ }
+
+ func testCleanupOldItems() throws {
+ let subscription = try databaseManager.createSubscription(
+ id: testSubscriptionId,
+ url: "https://example.com",
+ title: "Test Sub"
+ )
+
+ let oldItem = FeedItem(
+ id: UUID().uuidString,
+ title: "Old Item",
+ published: Calendar.current.date(byAdding: .day, value: -30, to: Date()),
+ subscriptionId: subscription.id
+ )
+ let newItem = FeedItem(
+ id: UUID().uuidString,
+ title: "New Item",
+ published: Date(),
+ subscriptionId: subscription.id
+ )
+
+ _ = try databaseManager.createFeedItem(oldItem)
+ _ = try databaseManager.createFeedItem(newItem)
+
+ let deletedCount = try databaseManager.cleanupOldItems(olderThan: 7, for: testSubscriptionId)
+
+ XCTAssertEqual(deletedCount, 1)
+
+ let remainingItems = try databaseManager.fetchFeedItems(for: testSubscriptionId)
+ XCTAssertEqual(remainingItems.count, 1)
+ XCTAssertEqual(remainingItems.first?.id, newItem.id)
+ }
+}
diff --git a/iOS/RSSuperTests/DateExtensionsTests.swift b/iOS/RSSuperTests/DateExtensionsTests.swift
new file mode 100644
index 0000000..a26d593
--- /dev/null
+++ b/iOS/RSSuperTests/DateExtensionsTests.swift
@@ -0,0 +1,56 @@
+//
+// DateExtensionsTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class DateExtensionsTests: XCTestCase {
+
+ func testMillisecondsSince1970() {
+ let date = Date(timeIntervalSince1970: 1609459200)
+ XCTAssertEqual(date.millisecondsSince1970, 1609459200000)
+ }
+
+ func testInitFromMilliseconds() {
+ let date = Date(millisecondsSince1970: 1609459200000)!
+ XCTAssertEqual(date.timeIntervalSince1970, 1609459200)
+ }
+
+ func testSecondsSince1970() {
+ let date = Date(timeIntervalSince1970: 1609459200)
+ XCTAssertEqual(date.secondsSince1970, 1609459200)
+ }
+
+ func testInitFromSeconds() {
+ let date = Date(secondsSince1970: 1609459200)!
+ XCTAssertEqual(date.timeIntervalSince1970, 1609459200)
+ }
+
+ func testISO8601String() {
+ let date = Date(timeIntervalSince1970: 1609459200)
+ let isoString = date.iso8601String
+
+ // Verify it's a valid ISO8601 string
+ let formatter = ISO8601DateFormatter()
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
+ XCTAssertNotNil(formatter.date(from: isoString))
+ }
+
+ func testInitFromISO8601String() {
+ let formatter = ISO8601DateFormatter()
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
+ let isoString = formatter.string(from: Date(timeIntervalSince1970: 1609459200))
+
+ let date = Date(iso8601String: isoString)!
+ XCTAssertEqual(date.timeIntervalSince1970, 1609459200, accuracy: 1.0)
+ }
+
+ func testInvalidISO8601String() {
+ let date = Date(iso8601String: "not-a-date")
+ XCTAssertNil(date)
+ }
+}
diff --git a/iOS/RSSuperTests/FeedFetcherTests.swift b/iOS/RSSuperTests/FeedFetcherTests.swift
new file mode 100644
index 0000000..ed279ee
--- /dev/null
+++ b/iOS/RSSuperTests/FeedFetcherTests.swift
@@ -0,0 +1,217 @@
+import XCTest
+import os.signpost
+@testable import RSSuper
+
+final class FeedFetcherTests: XCTestCase {
+ private var fetcher: FeedFetcher!
+ private var session: MockURLSession!
+
+ override func setUp() {
+ super.setUp()
+ session = MockURLSession()
+ fetcher = FeedFetcher(session: session)
+ }
+
+ override func tearDown() {
+ fetcher = nil
+ session = nil
+ super.tearDown()
+ }
+
+ func testFetchFeedSuccess() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+ let feedData = Data(rssSample.utf8)
+
+ session.response = (feedData, HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!)
+
+ let result = try await fetcher.fetchFeed(url: url)
+
+ XCTAssertEqual(result.feedData, feedData)
+ XCTAssertEqual(result.url, url)
+ XCTAssertFalse(result.cached)
+ }
+
+ func testFetchFeedWithAuthentication() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+ let feedData = Data(rssSample.utf8)
+ let credentials = HTTPAuthCredentials(username: "user", password: "pass")
+
+ session.response = (feedData, HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!)
+
+ let result = try await fetcher.fetchFeed(url: url, credentials: credentials)
+
+ XCTAssertEqual(result.feedData, feedData)
+ let authHeader = session.lastAuthHeader
+ XCTAssertTrue(authHeader?.starts(with: "Basic ") ?? false)
+ }
+
+ func testFetchFeedTimeoutError() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+
+ session.error = URLError(.timedOut)
+
+ do {
+ _ = try await fetcher.fetchFeed(url: url)
+ XCTFail("Expected error to be thrown")
+ } catch {
+ XCTAssertTrue(true)
+ }
+ }
+
+ func testFetchFeed404Error() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+
+ session.response = (Data(), HTTPURLResponse(url: url, statusCode: 404, httpVersion: "HTTP/1.1", headerFields: nil)!)
+
+ do {
+ _ = try await fetcher.fetchFeed(url: url)
+ XCTFail("Expected error to be thrown")
+ } catch {
+ XCTAssertTrue(true)
+ }
+ }
+
+ func testFetchFeedAuthenticationError() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+
+ session.response = (Data(), HTTPURLResponse(url: url, statusCode: 401, httpVersion: "HTTP/1.1", headerFields: nil)!)
+
+ do {
+ _ = try await fetcher.fetchFeed(url: url)
+ XCTFail("Expected error to be thrown")
+ } catch {
+ XCTAssertTrue(true)
+ }
+ }
+
+ func testFetchFeedRetriesOnTimeout() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+ let feedData = Data(rssSample.utf8)
+
+ var callCount = 0
+ session.onRequest = { [unowned self] in
+ callCount += 1
+ if callCount < 3 {
+ self.session.error = URLError(.timedOut)
+ }
+ }
+
+ session.response = (feedData, HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!)
+
+ let result = try await fetcher.fetchFeed(url: url)
+
+ XCTAssertEqual(result.feedData, feedData)
+ XCTAssertEqual(callCount, 3)
+ }
+
+ func testFetchFeedCaching() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+ let feedData = Data(rssSample.utf8)
+
+ session.response = (feedData, HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!)
+
+ let result1 = try await fetcher.fetchFeed(url: url)
+ XCTAssertFalse(result1.cached)
+
+ let result2 = try await fetcher.fetchFeed(url: url)
+ XCTAssertTrue(result2.cached)
+
+ XCTAssertEqual(result1.feedData, result2.feedData)
+ }
+
+ func testFetchFeedRespectsCacheControlNoStore() async throws {
+ let url = URL(string: "https://example.com/feed.xml")!
+ let feedData = Data(rssSample.utf8)
+
+ session.response = (feedData, HTTPURLResponse(url: url, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: ["Cache-Control": "no-store"])!)
+
+ let result1 = try await fetcher.fetchFeed(url: url)
+ XCTAssertFalse(result1.cached)
+
+ let result2 = try await fetcher.fetchFeed(url: url)
+ XCTAssertFalse(result2.cached)
+ }
+
+ func testHTTPAuthAuthorizationHeader() {
+ let credentials = HTTPAuthCredentials(username: "user", password: "pass")
+ let authHeader = credentials.authorizationHeader()
+
+ XCTAssertEqual(authHeader, "Basic dXNlcjpwYXNz")
+ }
+
+ func testHTTPAuthAuthorizationHeaderWithSpecialCharacters() {
+ let credentials = HTTPAuthCredentials(username: "user@domain", password: "p@ss:w0rd")
+ let authHeader = credentials.authorizationHeader()
+
+ let expectedData = "user@domain:p@ss:w0rd".data(using: .utf8)!
+ let expectedBase64 = expectedData.base64EncodedString()
+ XCTAssertEqual(authHeader, "Basic \(expectedBase64)")
+ }
+}
+
+private let rssSample = """
+
+
+
+ Test Feed
+ https://example.com
+ A test feed
+ -
+ Test Item
+ https://example.com/item1
+ item-1
+ Test item description
+
+
+
+"""
+
+final class MockURLSession: URLSession {
+ var response: (Data, URLResponse)?
+ var error: Error?
+ var onRequest: (() -> Void)?
+ var lastAuthHeader: String?
+
+ private var requestCounter = 0
+
+ override func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
+ requestCounter += 1
+
+ if let auth = request.allHTTPHeaderFields?["Authorization"] {
+ lastAuthHeader = auth
+ }
+
+ onRequest?()
+
+ if let error {
+ completionHandler(nil, nil, error)
+ return MockURLSessionDataTask(error: error)
+ }
+
+ if let (data, response) = response {
+ completionHandler(data, response, nil)
+ return MockURLSessionDataTask()
+ }
+
+ completionHandler(nil, nil, nil)
+ return MockURLSessionDataTask()
+ }
+
+ func reset() {
+ requestCounter = 0
+ lastAuthHeader = nil
+ }
+}
+
+final class MockURLSessionDataTask: URLSessionDataTask {
+ private let mockError: Error?
+
+ init(error: Error? = nil) {
+ self.mockError = error
+ super.init()
+ }
+
+ override func resume() {
+ // No-op for testing
+ }
+}
diff --git a/iOS/RSSuperTests/FeedItemTests.swift b/iOS/RSSuperTests/FeedItemTests.swift
new file mode 100644
index 0000000..12763b5
--- /dev/null
+++ b/iOS/RSSuperTests/FeedItemTests.swift
@@ -0,0 +1,148 @@
+//
+// FeedItemTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class FeedItemTests: XCTestCase {
+
+ func testFeedItemEncodingDecoding() throws {
+ let item = FeedItem(
+ id: "550e8400-e29b-41d4-a716-446655440000",
+ title: "Test Article",
+ link: "https://example.com/article",
+ description: "A test description",
+ content: "Full content here",
+ author: "John Doe",
+ published: Date(millisecondsSince1970: 1609459200000),
+ categories: ["tech", "swift"],
+ enclosure: Enclosure(url: "https://example.com/audio.mp3", type: "audio/mpeg", length: 1234567),
+ guid: "guid-123",
+ subscriptionId: "sub-123",
+ subscriptionTitle: "Test Feed"
+ )
+
+ let data = try JSONEncoder().encode(item)
+ let decoded = try JSONDecoder().decode(FeedItem.self, from: data)
+
+ XCTAssertEqual(decoded.id, item.id)
+ XCTAssertEqual(decoded.title, item.title)
+ XCTAssertEqual(decoded.link, item.link)
+ XCTAssertEqual(decoded.description, item.description)
+ XCTAssertEqual(decoded.content, item.content)
+ XCTAssertEqual(decoded.author, item.author)
+ XCTAssertEqual(decoded.published, item.published)
+ XCTAssertEqual(decoded.categories, item.categories)
+ XCTAssertEqual(decoded.guid, item.guid)
+ XCTAssertEqual(decoded.subscriptionId, item.subscriptionId)
+ XCTAssertEqual(decoded.subscriptionTitle, item.subscriptionTitle)
+ }
+
+ func testFeedItemOptionalProperties() throws {
+ let item = FeedItem(
+ id: "test-id",
+ title: "Minimal Item",
+ subscriptionId: "sub-id"
+ )
+
+ XCTAssertNil(item.link)
+ XCTAssertNil(item.description)
+ XCTAssertNil(item.content)
+ XCTAssertNil(item.author)
+ XCTAssertNil(item.published)
+ XCTAssertNil(item.categories)
+ XCTAssertNil(item.enclosure)
+ XCTAssertNil(item.guid)
+ XCTAssertNil(item.subscriptionTitle)
+
+ let data = try JSONEncoder().encode(item)
+ let decoded = try JSONDecoder().decode(FeedItem.self, from: data)
+
+ XCTAssertEqual(decoded.id, item.id)
+ XCTAssertEqual(decoded.title, item.title)
+ }
+
+ func testEnclosureEncodingDecoding() throws {
+ let enclosure = Enclosure(
+ url: "https://example.com/podcast.mp3",
+ type: "audio/mpeg",
+ length: 98765432
+ )
+
+ let data = try JSONEncoder().encode(enclosure)
+ let decoded = try JSONDecoder().decode(Enclosure.self, from: data)
+
+ XCTAssertEqual(decoded.url, enclosure.url)
+ XCTAssertEqual(decoded.type, enclosure.type)
+ XCTAssertEqual(decoded.length, enclosure.length)
+ }
+
+ func testEnclosureWithoutLength() throws {
+ let enclosure = Enclosure(
+ url: "https://example.com/video.mp4",
+ type: "video/mp4"
+ )
+
+ let data = try JSONEncoder().encode(enclosure)
+ let decoded = try JSONDecoder().decode(Enclosure.self, from: data)
+
+ XCTAssertEqual(decoded.url, enclosure.url)
+ XCTAssertEqual(decoded.type, enclosure.type)
+ XCTAssertNil(decoded.length)
+ }
+
+ func testFeedItemEquality() {
+ let item1 = FeedItem(
+ id: "same-id",
+ title: "Same Title",
+ subscriptionId: "sub-id"
+ )
+
+ let item2 = FeedItem(
+ id: "same-id",
+ title: "Same Title",
+ subscriptionId: "sub-id"
+ )
+
+ let item3 = FeedItem(
+ id: "different-id",
+ title: "Different Title",
+ subscriptionId: "sub-id"
+ )
+
+ XCTAssertEqual(item1, item2)
+ XCTAssertNotEqual(item1, item3)
+ }
+
+ func testContentTypeDetection() {
+ let audioEnclosure = Enclosure(url: "test.mp3", type: "audio/mpeg")
+ XCTAssertEqual(audioEnclosure.mimeType, .audio)
+
+ let videoEnclosure = Enclosure(url: "test.mp4", type: "video/mp4")
+ XCTAssertEqual(videoEnclosure.mimeType, .video)
+
+ let articleEnclosure = Enclosure(url: "test.pdf", type: "application/pdf")
+ XCTAssertEqual(articleEnclosure.mimeType, .article)
+ }
+
+ func testFeedItemDebugDescription() {
+ let item = FeedItem(
+ id: "test-id",
+ title: "Debug Test",
+ author: "Test Author",
+ published: Date(millisecondsSince1970: 1609459200000),
+ subscriptionId: "sub-id",
+ subscriptionTitle: "My Feed"
+ )
+
+ let debugDesc = item.debugDescription
+ XCTAssertTrue(debugDesc.contains("test-id"))
+ XCTAssertTrue(debugDesc.contains("Debug Test"))
+ XCTAssertTrue(debugDesc.contains("Test Author"))
+ XCTAssertTrue(debugDesc.contains("My Feed"))
+ }
+}
diff --git a/iOS/RSSuperTests/FeedParserTests.swift b/iOS/RSSuperTests/FeedParserTests.swift
new file mode 100644
index 0000000..015ff98
--- /dev/null
+++ b/iOS/RSSuperTests/FeedParserTests.swift
@@ -0,0 +1,211 @@
+import XCTest
+@testable import RSSuper
+
+final class FeedParserTests: XCTestCase {
+ func testParsesRSS20Feed() throws {
+ let parser = FeedParser()
+ let result = try parser.parse(
+ data: Data(rssSample.utf8),
+ sourceURL: "https://example.com/rss.xml"
+ )
+
+ XCTAssertEqual(result.feedType, .rss)
+ XCTAssertEqual(result.feed.title, "Example Podcast")
+ XCTAssertEqual(result.feed.subtitle, "Weekly iOS and Swift updates")
+ XCTAssertEqual(result.feed.items.count, 2)
+ XCTAssertEqual(result.feed.ttl, 60)
+
+ let firstItem = try XCTUnwrap(result.feed.items.first)
+ XCTAssertEqual(firstItem.title, "Episode 1")
+ XCTAssertEqual(firstItem.author, "Host Name")
+ XCTAssertEqual(firstItem.guid, "episode-1")
+ XCTAssertEqual(firstItem.categories, ["Swift"])
+ XCTAssertEqual(firstItem.enclosure?.url, "https://example.com/audio/ep1.mp3")
+ XCTAssertEqual(firstItem.enclosure?.type, "audio/mpeg")
+ XCTAssertEqual(firstItem.enclosure?.length, 12345)
+ XCTAssertEqual(firstItem.content, "Full content for episode 1.
")
+ }
+
+ func testParsesAtom10Feed() throws {
+ let parser = FeedParser()
+ let result = try parser.parse(
+ data: Data(atomSample.utf8),
+ sourceURL: "https://example.com/atom.xml"
+ )
+
+ XCTAssertEqual(result.feedType, .atom)
+ XCTAssertEqual(result.feed.title, "Example Atom Feed")
+ XCTAssertEqual(result.feed.subtitle, "Recent engineering posts")
+ XCTAssertEqual(result.feed.link, "https://example.com")
+ XCTAssertEqual(result.feed.items.count, 2)
+
+ let firstItem = try XCTUnwrap(result.feed.items.first)
+ XCTAssertEqual(firstItem.guid, "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a")
+ XCTAssertEqual(firstItem.link, "https://example.com/posts/1")
+ XCTAssertEqual(firstItem.author, "Jane Author")
+ XCTAssertEqual(firstItem.enclosure?.url, "https://example.com/audio/post1.mp3")
+ XCTAssertEqual(firstItem.enclosure?.type, "audio/mpeg")
+ XCTAssertEqual(firstItem.enclosure?.length, 2048)
+ }
+
+ func testHandlesITunesNamespace() throws {
+ let parser = FeedParser()
+ let result = try parser.parse(
+ data: Data(rssWithITunesSample.utf8),
+ sourceURL: "https://example.com/itunes.xml"
+ )
+
+ XCTAssertEqual(result.feed.subtitle, "Podcast subtitle")
+ XCTAssertEqual(result.feed.description, "Feed-level summary")
+
+ let item = try XCTUnwrap(result.feed.items.first)
+ XCTAssertEqual(item.author, "Podcast Author")
+ XCTAssertEqual(item.description, "Item-level summary")
+ }
+
+ func testThrowsForMalformedXML() {
+ let parser = FeedParser()
+ XCTAssertThrowsError(
+ try parser.parse(
+ data: Data("Broken".utf8),
+ sourceURL: "https://example.com/broken.xml"
+ )
+ ) { error in
+ XCTAssertEqual(error as? FeedParsingError, .malformedXML)
+ }
+ }
+
+ func testParsesRealWorldStyleFeeds() throws {
+ let parser = FeedParser()
+ let rssResult = try parser.parse(
+ data: Data(realWorldRSSSample.utf8),
+ sourceURL: "https://feeds.example.com/news.xml"
+ )
+ XCTAssertEqual(rssResult.feedType, .rss)
+ XCTAssertGreaterThan(rssResult.feed.items.count, 0)
+
+ let atomResult = try parser.parse(
+ data: Data(realWorldAtomSample.utf8),
+ sourceURL: "https://feeds.example.com/engineering.xml"
+ )
+ XCTAssertEqual(atomResult.feedType, .atom)
+ XCTAssertGreaterThan(atomResult.feed.items.count, 0)
+ }
+}
+
+private let rssSample = """
+
+
+
+ Example Podcast
+ https://example.com
+ A sample RSS feed
+ en-us
+ Mon, 30 Mar 2026 10:00:00 +0000
+ RSSuper Test Suite
+ 60
+ Weekly iOS and Swift updates
+ -
+ Episode 1
+ https://example.com/episodes/1
+ episode-1
+ Mon, 30 Mar 2026 09:00:00 +0000
+ Swift
+ Episode 1 summary
+ Full content for episode 1.
]]>
+ Host Name
+
+
+ -
+ Episode 2
+ https://example.com/episodes/2
+ episode-2
+ Mon, 30 Mar 2026 08:00:00 +0000
+ Episode 2 summary
+
+
+
+"""
+
+private let atomSample = """
+
+
+ Example Atom Feed
+ Recent engineering posts
+
+ 2026-03-30T10:00:00Z
+ Atom Test Generator
+
+ Post One
+ urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a
+ 2026-03-30T09:00:00Z
+ 2026-03-30T08:59:00Z
+ First post summary
+ <p>First post full content</p>
+ Jane Author
+
+
+
+
+ Post Two
+ urn:uuid:7a9b2f0d-65b2-44a7-a2ad-d3c3ff7dd003
+ 2026-03-30T08:00:00Z
+ Second post summary
+
+
+
+"""
+
+private let rssWithITunesSample = """
+
+
+
+ iTunes Feed
+ Podcast subtitle
+ Feed-level summary
+ -
+ Episode
+ Podcast Author
+ Item-level summary
+
+
+
+"""
+
+private let realWorldRSSSample = """
+
+
+
+ Daily Tech News
+ https://news.example.com
+ Latest updates from the tech world
+ Mon, 30 Mar 2026 12:00:00 +0000
+ -
+ Apple ships new SDK tools
+ https://news.example.com/apple-sdk-tools
+ news-1
+ Mon, 30 Mar 2026 11:00:00 +0000
+ Tooling improvements for mobile developers.
+
+
+
+"""
+
+private let realWorldAtomSample = """
+
+
+ Engineering Blog
+ 2026-03-30T12:00:00Z
+
+
+ Improving app startup performance
+ tag:engineering.example.com,2026:post-1
+ 2026-03-29T16:00:00Z
+ 2026-03-29T15:00:00Z
+ How we reduced cold-start by 25%.
+ Detailed analysis of startup bottlenecks and fixes.
+ Engineering Team
+
+
+
+"""
diff --git a/iOS/RSSuperTests/FeedSubscriptionTests.swift b/iOS/RSSuperTests/FeedSubscriptionTests.swift
new file mode 100644
index 0000000..64d770d
--- /dev/null
+++ b/iOS/RSSuperTests/FeedSubscriptionTests.swift
@@ -0,0 +1,116 @@
+//
+// FeedSubscriptionTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class FeedSubscriptionTests: XCTestCase {
+
+ func testFeedSubscriptionEncodingDecoding() throws {
+ let subscription = FeedSubscription(
+ id: "sub-123",
+ url: "https://example.com/feed.xml",
+ title: "Example Feed",
+ category: "Tech",
+ enabled: true,
+ fetchInterval: 120,
+ createdAt: Date(timeIntervalSince1970: 1609459200),
+ updatedAt: Date(timeIntervalSince1970: 1609545600),
+ lastFetchedAt: Date(timeIntervalSince1970: 1609632000),
+ nextFetchAt: Date(timeIntervalSince1970: 1609718400),
+ error: nil,
+ httpAuth: HttpAuth(username: "user", password: "pass")
+ )
+
+ let data = try JSONEncoder().encode(subscription)
+ let decoded = try JSONDecoder().decode(FeedSubscription.self, from: data)
+
+ XCTAssertEqual(decoded.id, subscription.id)
+ XCTAssertEqual(decoded.url, subscription.url)
+ XCTAssertEqual(decoded.title, subscription.title)
+ XCTAssertEqual(decoded.category, subscription.category)
+ XCTAssertEqual(decoded.enabled, subscription.enabled)
+ XCTAssertEqual(decoded.fetchInterval, subscription.fetchInterval)
+ XCTAssertEqual(decoded.createdAt, subscription.createdAt)
+ XCTAssertEqual(decoded.updatedAt, subscription.updatedAt)
+ XCTAssertEqual(decoded.lastFetchedAt, subscription.lastFetchedAt)
+ XCTAssertEqual(decoded.nextFetchAt, subscription.nextFetchAt)
+ XCTAssertEqual(decoded.httpAuth?.username, subscription.httpAuth?.username)
+ XCTAssertEqual(decoded.httpAuth?.password, subscription.httpAuth?.password)
+ }
+
+ func testFeedSubscriptionOptionalProperties() throws {
+ let subscription = FeedSubscription(
+ id: "minimal-sub",
+ url: "https://example.com/minimal.xml",
+ title: "Minimal Feed"
+ )
+
+ XCTAssertNil(subscription.category)
+ XCTAssertNil(subscription.lastFetchedAt)
+ XCTAssertNil(subscription.nextFetchAt)
+ XCTAssertNil(subscription.error)
+ XCTAssertNil(subscription.httpAuth)
+
+ let data = try JSONEncoder().encode(subscription)
+ let decoded = try JSONDecoder().decode(FeedSubscription.self, from: data)
+
+ XCTAssertEqual(decoded.id, subscription.id)
+ XCTAssertEqual(decoded.enabled, true)
+ XCTAssertEqual(decoded.fetchInterval, 60)
+ }
+
+ func testFeedSubscriptionEquality() {
+ let sub1 = FeedSubscription(
+ id: "same-id",
+ url: "https://example.com/feed.xml",
+ title: "Same Title"
+ )
+
+ let sub2 = FeedSubscription(
+ id: "same-id",
+ url: "https://example.com/feed.xml",
+ title: "Same Title"
+ )
+
+ let sub3 = FeedSubscription(
+ id: "different-id",
+ url: "https://example.com/other.xml",
+ title: "Different Title"
+ )
+
+ XCTAssertEqual(sub1, sub2)
+ XCTAssertNotEqual(sub1, sub3)
+ }
+
+ func testHttpAuthEncodingDecoding() throws {
+ let auth = HttpAuth(username: "testuser", password: "testpass")
+
+ let data = try JSONEncoder().encode(auth)
+ let decoded = try JSONDecoder().decode(HttpAuth.self, from: data)
+
+ XCTAssertEqual(decoded.username, auth.username)
+ XCTAssertEqual(decoded.password, auth.password)
+ }
+
+ func testFeedSubscriptionDebugDescription() {
+ let subscription = FeedSubscription(
+ id: "debug-id",
+ url: "https://example.com/debug.xml",
+ title: "Debug Feed",
+ enabled: false,
+ fetchInterval: 30,
+ error: "Connection timeout"
+ )
+
+ let debugDesc = subscription.debugDescription
+ XCTAssertTrue(debugDesc.contains("debug-id"))
+ XCTAssertTrue(debugDesc.contains("Debug Feed"))
+ XCTAssertTrue(debugDesc.contains("30min"))
+ XCTAssertTrue(debugDesc.contains("Connection timeout"))
+ }
+}
diff --git a/iOS/RSSuperTests/NotificationPreferencesTests.swift b/iOS/RSSuperTests/NotificationPreferencesTests.swift
new file mode 100644
index 0000000..a4b6b08
--- /dev/null
+++ b/iOS/RSSuperTests/NotificationPreferencesTests.swift
@@ -0,0 +1,102 @@
+//
+// NotificationPreferencesTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class NotificationPreferencesTests: XCTestCase {
+
+ func testNotificationPreferencesEncodingDecoding() throws {
+ let prefs = NotificationPreferences(
+ newArticles: true,
+ episodeReleases: false,
+ customAlerts: true,
+ badgeCount: true,
+ sound: false,
+ vibration: true
+ )
+
+ let data = try JSONEncoder().encode(prefs)
+ let decoded = try JSONDecoder().decode(NotificationPreferences.self, from: data)
+
+ XCTAssertEqual(decoded.newArticles, prefs.newArticles)
+ XCTAssertEqual(decoded.episodeReleases, prefs.episodeReleases)
+ XCTAssertEqual(decoded.customAlerts, prefs.customAlerts)
+ XCTAssertEqual(decoded.badgeCount, prefs.badgeCount)
+ XCTAssertEqual(decoded.sound, prefs.sound)
+ XCTAssertEqual(decoded.vibration, prefs.vibration)
+ }
+
+ func testNotificationPreferencesDefaults() {
+ let prefs = NotificationPreferences()
+
+ XCTAssertEqual(prefs.newArticles, true)
+ XCTAssertEqual(prefs.episodeReleases, true)
+ XCTAssertEqual(prefs.customAlerts, false)
+ XCTAssertEqual(prefs.badgeCount, true)
+ XCTAssertEqual(prefs.sound, true)
+ XCTAssertEqual(prefs.vibration, true)
+ }
+
+ func testNotificationPreferencesAllEnabled() {
+ let allEnabled = NotificationPreferences(
+ newArticles: true,
+ episodeReleases: true,
+ customAlerts: true,
+ badgeCount: true,
+ sound: true,
+ vibration: true
+ )
+
+ XCTAssertTrue(allEnabled.allEnabled)
+ }
+
+ func testNotificationPreferencesAnyEnabled() {
+ let noneEnabled = NotificationPreferences(
+ newArticles: false,
+ episodeReleases: false,
+ customAlerts: false,
+ badgeCount: false,
+ sound: false,
+ vibration: false
+ )
+
+ XCTAssertFalse(noneEnabled.anyEnabled)
+
+ let someEnabled = NotificationPreferences(
+ newArticles: true,
+ episodeReleases: false,
+ customAlerts: false,
+ badgeCount: false,
+ sound: false,
+ vibration: false
+ )
+
+ XCTAssertTrue(someEnabled.anyEnabled)
+ }
+
+ func testNotificationPreferencesEquality() {
+ let prefs1 = NotificationPreferences(newArticles: true, episodeReleases: false)
+ let prefs2 = NotificationPreferences(newArticles: true, episodeReleases: false)
+ let prefs3 = NotificationPreferences(newArticles: false, episodeReleases: true)
+
+ XCTAssertEqual(prefs1, prefs2)
+ XCTAssertNotEqual(prefs1, prefs3)
+ }
+
+ func testNotificationPreferencesDebugDescription() {
+ let prefs = NotificationPreferences(
+ newArticles: true,
+ episodeReleases: false,
+ customAlerts: true
+ )
+
+ let debugDesc = prefs.debugDescription
+ XCTAssertTrue(debugDesc.contains("true"))
+ XCTAssertTrue(debugDesc.contains("false"))
+ }
+}
diff --git a/iOS/RSSuperTests/RSSuperTests.swift b/iOS/RSSuperTests/RSSuperTests.swift
new file mode 100644
index 0000000..5e91e09
--- /dev/null
+++ b/iOS/RSSuperTests/RSSuperTests.swift
@@ -0,0 +1,18 @@
+//
+// RSSuperTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+
+@testable import RSSuper
+
+final class RSSuperTests: XCTestCase {
+
+ func testPlaceholder() {
+ // Placeholder test - all actual tests are in dedicated test files
+ XCTAssertTrue(true)
+ }
+}
diff --git a/iOS/RSSuperTests/ReadingPreferencesTests.swift b/iOS/RSSuperTests/ReadingPreferencesTests.swift
new file mode 100644
index 0000000..cabc3b5
--- /dev/null
+++ b/iOS/RSSuperTests/ReadingPreferencesTests.swift
@@ -0,0 +1,79 @@
+//
+// ReadingPreferencesTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class ReadingPreferencesTests: XCTestCase {
+
+ func testReadingPreferencesEncodingDecoding() throws {
+ let prefs = ReadingPreferences(
+ fontSize: .large,
+ lineHeight: .loose,
+ showTableOfContents: true,
+ showReadingTime: false,
+ showAuthor: true,
+ showDate: false
+ )
+
+ let data = try JSONEncoder().encode(prefs)
+ let decoded = try JSONDecoder().decode(ReadingPreferences.self, from: data)
+
+ XCTAssertEqual(decoded.fontSize, prefs.fontSize)
+ XCTAssertEqual(decoded.lineHeight, prefs.lineHeight)
+ XCTAssertEqual(decoded.showTableOfContents, prefs.showTableOfContents)
+ XCTAssertEqual(decoded.showReadingTime, prefs.showReadingTime)
+ XCTAssertEqual(decoded.showAuthor, prefs.showAuthor)
+ XCTAssertEqual(decoded.showDate, prefs.showDate)
+ }
+
+ func testReadingPreferencesDefaults() {
+ let prefs = ReadingPreferences()
+
+ XCTAssertEqual(prefs.fontSize, .medium)
+ XCTAssertEqual(prefs.lineHeight, .relaxed)
+ XCTAssertEqual(prefs.showTableOfContents, false)
+ XCTAssertEqual(prefs.showReadingTime, true)
+ XCTAssertEqual(prefs.showAuthor, true)
+ XCTAssertEqual(prefs.showDate, true)
+ }
+
+ func testFontSizePointValue() {
+ XCTAssertEqual(ReadingPreferences.FontSize.small.pointValue, 14)
+ XCTAssertEqual(ReadingPreferences.FontSize.medium.pointValue, 16)
+ XCTAssertEqual(ReadingPreferences.FontSize.large.pointValue, 18)
+ XCTAssertEqual(ReadingPreferences.FontSize.xlarge.pointValue, 20)
+ }
+
+ func testLineHeightMultiplier() {
+ XCTAssertEqual(ReadingPreferences.LineHeight.normal.multiplier, 1.2)
+ XCTAssertEqual(ReadingPreferences.LineHeight.relaxed.multiplier, 1.5)
+ XCTAssertEqual(ReadingPreferences.LineHeight.loose.multiplier, 1.8)
+ }
+
+ func testReadingPreferencesEquality() {
+ let prefs1 = ReadingPreferences(fontSize: .large, lineHeight: .loose)
+ let prefs2 = ReadingPreferences(fontSize: .large, lineHeight: .loose)
+ let prefs3 = ReadingPreferences(fontSize: .medium, lineHeight: .normal)
+
+ XCTAssertEqual(prefs1, prefs2)
+ XCTAssertNotEqual(prefs1, prefs3)
+ }
+
+ func testReadingPreferencesDebugDescription() {
+ let prefs = ReadingPreferences(
+ fontSize: .xlarge,
+ lineHeight: .normal,
+ showTableOfContents: true
+ )
+
+ let debugDesc = prefs.debugDescription
+ XCTAssertTrue(debugDesc.contains("xlarge"))
+ XCTAssertTrue(debugDesc.contains("normal"))
+ XCTAssertTrue(debugDesc.contains("true"))
+ }
+}
diff --git a/iOS/RSSuperTests/SearchFiltersTests.swift b/iOS/RSSuperTests/SearchFiltersTests.swift
new file mode 100644
index 0000000..185c24b
--- /dev/null
+++ b/iOS/RSSuperTests/SearchFiltersTests.swift
@@ -0,0 +1,96 @@
+//
+// SearchFiltersTests.swift
+// RSSuperTests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+@testable import RSSuper
+
+final class SearchFiltersTests: XCTestCase {
+
+ func testSearchFiltersEncodingDecoding() throws {
+ let filters = SearchFilters(
+ dateFrom: Date(timeIntervalSince1970: 1609459200),
+ dateTo: Date(timeIntervalSince1970: 1609545600),
+ feedIds: ["feed-1", "feed-2"],
+ authors: ["Author 1", "Author 2"],
+ contentType: .audio
+ )
+
+ let data = try JSONEncoder().encode(filters)
+ let decoded = try JSONDecoder().decode(SearchFilters.self, from: data)
+
+ XCTAssertEqual(decoded.dateFrom, filters.dateFrom)
+ XCTAssertEqual(decoded.dateTo, filters.dateTo)
+ XCTAssertEqual(decoded.feedIds, filters.feedIds)
+ XCTAssertEqual(decoded.authors, filters.authors)
+ XCTAssertEqual(decoded.contentType, filters.contentType)
+ }
+
+ func testSearchFiltersEmpty() throws {
+ let filters = SearchFilters()
+
+ XCTAssertNil(filters.dateFrom)
+ XCTAssertNil(filters.dateTo)
+ XCTAssertNil(filters.feedIds)
+ XCTAssertNil(filters.authors)
+ XCTAssertNil(filters.contentType)
+
+ let data = try JSONEncoder().encode(filters)
+ let decoded = try JSONDecoder().decode(SearchFilters.self, from: data)
+
+ XCTAssertNil(decoded.dateFrom)
+ XCTAssertNil(decoded.feedIds)
+ }
+
+ func testSearchFiltersEquality() {
+ let filters1 = SearchFilters(
+ feedIds: ["feed-1"],
+ authors: ["Author 1"]
+ )
+
+ let filters2 = SearchFilters(
+ feedIds: ["feed-1"],
+ authors: ["Author 1"]
+ )
+
+ let filters3 = SearchFilters(
+ feedIds: ["feed-2"],
+ authors: ["Author 2"]
+ )
+
+ XCTAssertEqual(filters1, filters2)
+ XCTAssertNotEqual(filters1, filters3)
+ }
+
+ func testSearchSortOptionLocalizedDescription() {
+ XCTAssertEqual(SearchSortOption.relevance.localizedDescription, "Relevance")
+ XCTAssertEqual(SearchSortOption.dateDesc.localizedDescription, "Date (Newest First)")
+ XCTAssertEqual(SearchSortOption.dateAsc.localizedDescription, "Date (Oldest First)")
+ XCTAssertEqual(SearchSortOption.titleAsc.localizedDescription, "Title (A-Z)")
+ XCTAssertEqual(SearchSortOption.titleDesc.localizedDescription, "Title (Z-A)")
+ XCTAssertEqual(SearchSortOption.feedAsc.localizedDescription, "Feed (A-Z)")
+ XCTAssertEqual(SearchSortOption.feedDesc.localizedDescription, "Feed (Z-A)")
+ }
+
+ func testContentTypeLocalizedDescription() {
+ XCTAssertEqual(ContentType.article.localizedDescription, "Article")
+ XCTAssertEqual(ContentType.audio.localizedDescription, "Audio")
+ XCTAssertEqual(ContentType.video.localizedDescription, "Video")
+ }
+
+ func testSearchFiltersDebugDescription() {
+ let filters = SearchFilters(
+ dateFrom: Date(timeIntervalSince1970: 1609459200),
+ feedIds: ["feed-1", "feed-2"],
+ contentType: .video
+ )
+
+ let debugDesc = filters.debugDescription
+ XCTAssertTrue(debugDesc.contains("feed-1"))
+ XCTAssertTrue(debugDesc.contains("feed-2"))
+ XCTAssertTrue(debugDesc.contains("Video"))
+ }
+}
diff --git a/iOS/RSSuperTests/SearchHistoryStoreTests.swift b/iOS/RSSuperTests/SearchHistoryStoreTests.swift
new file mode 100644
index 0000000..0b087f9
--- /dev/null
+++ b/iOS/RSSuperTests/SearchHistoryStoreTests.swift
@@ -0,0 +1,122 @@
+import XCTest
+@testable import RSSuper
+
+/// Unit tests for SearchHistoryStore
+final class SearchHistoryStoreTests: XCTestCase {
+
+ private var historyStore: SearchHistoryStore!
+ private var databaseManager: DatabaseManager!
+
+ override func setUp() async throws {
+ // Create in-memory database for testing
+ databaseManager = try await DatabaseManager.inMemory()
+ historyStore = SearchHistoryStore(databaseManager: databaseManager, maxHistoryCount: 10)
+ try await historyStore.initialize()
+ }
+
+ override func tearDown() async throws {
+ historyStore = nil
+ databaseManager = nil
+ }
+
+ func testRecordSearch() async throws {
+ try await historyStore.recordSearch("test query")
+
+ let exists = try await historyStore.queryExists("test query")
+ XCTAssertTrue(exists)
+ }
+
+ func testRecordSearchUpdatesExisting() async throws {
+ try await historyStore.recordSearch("test query")
+ let firstCount = try await historyStore.getTotalCount()
+
+ try await historyStore.recordSearch("test query")
+ let secondCount = try await historyStore.getTotalCount()
+
+ XCTAssertEqual(firstCount, secondCount) // Should be same, updated not inserted
+ }
+
+ func testGetRecentQueries() async throws {
+ try await historyStore.recordSearch("query 1")
+ try await historyStore.recordSearch("query 2")
+ try await historyStore.recordSearch("query 3")
+
+ let queries = try await historyStore.getRecentQueries(limit: 2)
+
+ XCTAssertEqual(queries.count, 2)
+ XCTAssertEqual(queries[0], "query 3") // Most recent first
+ XCTAssertEqual(queries[1], "query 2")
+ }
+
+ func testGetHistoryWithMetadata() async throws {
+ try await historyStore.recordSearch("test query", resultCount: 42)
+
+ let entries = try await historyStore.getHistoryWithMetadata(limit: 10)
+
+ XCTAssertEqual(entries.count, 1)
+ XCTAssertEqual(entries[0].query, "test query")
+ XCTAssertEqual(entries[0].resultCount, 42)
+ }
+
+ func testRemoveQuery() async throws {
+ try await historyStore.recordSearch("to remove")
+ XCTAssertTrue(try await historyStore.queryExists("to remove"))
+
+ try await historyStore.removeQuery("to remove")
+ XCTAssertFalse(try await historyStore.queryExists("to remove"))
+ }
+
+ func testClearHistory() async throws {
+ try await historyStore.recordSearch("query 1")
+ try await historyStore.recordSearch("query 2")
+
+ XCTAssertEqual(try await historyStore.getTotalCount(), 2)
+
+ try await historyStore.clearHistory()
+ XCTAssertEqual(try await historyStore.getTotalCount(), 0)
+ }
+
+ func testTrimHistory() async throws {
+ // Insert more than maxHistoryCount
+ for i in 1...15 {
+ try await historyStore.recordSearch("query \(i)")
+ }
+
+ let count = try await historyStore.getTotalCount()
+ XCTAssertEqual(count, 10) // Should be trimmed to maxHistoryCount
+ }
+
+ func testGetPopularQueries() async throws {
+ // Record queries with different frequencies
+ try await historyStore.recordSearch("popular")
+ try await historyStore.recordSearch("popular")
+ try await historyStore.recordSearch("popular")
+ try await historyStore.recordSearch("less popular")
+ try await historyStore.recordSearch("less popular")
+ try await historyStore.recordSearch("once")
+
+ let popular = try await historyStore.getPopularQueries(limit: 10)
+
+ XCTAssertEqual(popular.count, 3)
+ XCTAssertEqual(popular[0].query, "popular")
+ XCTAssertEqual(popular[0].count, 3)
+ }
+
+ func testGetTodaysQueries() async throws {
+ try await historyStore.recordSearch("today query 1")
+ try await historyStore.recordSearch("today query 2")
+
+ let todays = try await historyStore.getTodaysQueries()
+
+ XCTAssertTrue(todays.contains("today query 1"))
+ XCTAssertTrue(todays.contains("today query 2"))
+ }
+
+ func testEmptyQueryIgnored() async throws {
+ try await historyStore.recordSearch("")
+ try await historyStore.recordSearch(" ")
+
+ let count = try await historyStore.getTotalCount()
+ XCTAssertEqual(count, 0)
+ }
+}
diff --git a/iOS/RSSuperTests/SearchQueryTests.swift b/iOS/RSSuperTests/SearchQueryTests.swift
new file mode 100644
index 0000000..9e3f26a
--- /dev/null
+++ b/iOS/RSSuperTests/SearchQueryTests.swift
@@ -0,0 +1,111 @@
+import XCTest
+@testable import RSSuper
+
+/// Unit tests for SearchQuery parsing and manipulation
+final class SearchQueryTests: XCTestCase {
+
+ func testEmptyQuery() {
+ let query = SearchQuery(rawValue: "")
+
+ XCTAssertEqual(query.terms, [])
+ XCTAssertEqual(query.rawText, "")
+ XCTAssertEqual(query.sort, .relevance)
+ XCTAssertFalse(query.fuzzy)
+ }
+
+ func testSimpleQuery() {
+ let query = SearchQuery(rawValue: "swift programming")
+
+ XCTAssertEqual(query.terms, ["swift", "programming"])
+ XCTAssertEqual(query.rawText, "swift programming")
+ }
+
+ func testQueryWithDateFilter() {
+ let query = SearchQuery(rawValue: "swift date:after:2024-01-01")
+
+ XCTAssertEqual(query.terms, ["swift"])
+ XCTAssertNotNil(query.filters.dateRange)
+
+ if case .after(let date) = query.filters.dateRange! {
+ let formatter = DateFormatter()
+ formatter.dateFormat = "yyyy-MM-dd"
+ let expectedDate = formatter.date(from: "2024-01-01")!
+ XCTAssertEqual(date, expectedDate)
+ } else {
+ XCTFail("Expected .after case")
+ }
+ }
+
+ func testQueryWithFeedFilter() {
+ let query = SearchQuery(rawValue: "swift feed:Apple Developer")
+
+ XCTAssertEqual(query.terms, ["swift"])
+ XCTAssertEqual(query.filters.feedTitle, "Apple Developer")
+ }
+
+ func testQueryWithAuthorFilter() {
+ let query = SearchQuery(rawValue: "swift author:John Doe")
+
+ XCTAssertEqual(query.terms, ["swift"])
+ XCTAssertEqual(query.filters.author, "John Doe")
+ }
+
+ func testQueryWithSortOption() {
+ let query = SearchQuery(rawValue: "swift sort:date_desc")
+
+ XCTAssertEqual(query.terms, ["swift"])
+ XCTAssertEqual(query.sort, .dateDesc)
+ }
+
+ func testQueryWithFuzzyFlag() {
+ let query = SearchQuery(rawValue: "swift ~")
+
+ XCTAssertEqual(query.terms, ["swift"])
+ XCTAssertTrue(query.fuzzy)
+ }
+
+ func testFTSQueryGeneration() {
+ let exactQuery = SearchQuery(rawValue: "swift programming")
+ XCTAssertEqual(exactQuery.ftsQuery(), "\"swift\" OR \"programming\"")
+
+ let fuzzyQuery = SearchQuery(rawValue: "swift ~")
+ XCTAssertEqual(fuzzyQuery.ftsQuery(), "\"*swift*\"")
+ }
+
+ func testDisplayString() {
+ let query = SearchQuery(rawValue: "swift date:after:2024-01-01")
+ XCTAssertEqual(query.displayString, "swift")
+ }
+
+ func testDateRangeLowerBound() {
+ let afterRange = DateRange.after(Date())
+ XCTAssertNotNil(afterRange.lowerBound)
+ XCTAssertNil(afterRange.upperBound)
+
+ let beforeRange = DateRange.before(Date())
+ XCTAssertNil(beforeRange.lowerBound)
+ XCTAssertNotNil(beforeRange.upperBound)
+
+ let exactRange = DateRange.exact(Date())
+ XCTAssertNotNil(exactRange.lowerBound)
+ XCTAssertNotNil(exactRange.upperBound)
+ }
+
+ func testSearchFiltersIsEmpty() {
+ var filters = SearchFilters()
+ XCTAssertTrue(filters.isEmpty)
+
+ filters.dateRange = .after(Date())
+ XCTAssertFalse(filters.isEmpty)
+
+ filters = .empty
+ XCTAssertTrue(filters.isEmpty)
+ }
+
+ func testSortOptionOrderByClause() {
+ XCTAssertEqual(SearchSortOption.relevance.orderByClause(), "rank")
+ XCTAssertEqual(SearchSortOption.dateDesc.orderByClause(), "f.published DESC")
+ XCTAssertEqual(SearchSortOption.titleAsc.orderByClause(), "f.title ASC")
+ XCTAssertEqual(SearchSortOption.feedDesc.orderByClause(), "s.title DESC")
+ }
+}
diff --git a/iOS/RSSuperTests/SearchResultTests.swift b/iOS/RSSuperTests/SearchResultTests.swift
new file mode 100644
index 0000000..b66277e
--- /dev/null
+++ b/iOS/RSSuperTests/SearchResultTests.swift
@@ -0,0 +1,89 @@
+import XCTest
+@testable import RSSuper
+
+/// Unit tests for SearchResult and related types
+final class SearchResultTests: XCTestCase {
+
+ func testArticleResultCreation() {
+ let result = SearchResult.article(
+ id: "article-123",
+ title: "Test Article",
+ snippet: "This is a snippet",
+ link: "https://example.com/article",
+ feedTitle: "Test Feed",
+ published: Date(),
+ score: 0.95,
+ author: "Test Author"
+ )
+
+ XCTAssertEqual(result.id, "article-123")
+ XCTAssertEqual(result.type, .article)
+ XCTAssertEqual(result.title, "Test Article")
+ XCTAssertEqual(result.snippet, "This is a snippet")
+ XCTAssertEqual(result.link, "https://example.com/article")
+ XCTAssertEqual(result.feedTitle, "Test Feed")
+ XCTAssertEqual(result.score, 0.95)
+ XCTAssertEqual(result.author, "Test Author")
+ }
+
+ func testFeedResultCreation() {
+ let result = SearchResult.feed(
+ id: "feed-456",
+ title: "Test Feed",
+ link: "https://example.com/feed.xml",
+ score: 0.85
+ )
+
+ XCTAssertEqual(result.id, "feed-456")
+ XCTAssertEqual(result.type, .feed)
+ XCTAssertEqual(result.title, "Test Feed")
+ XCTAssertEqual(result.link, "https://example.com/feed.xml")
+ XCTAssertEqual(result.score, 0.85)
+ }
+
+ func testSuggestionResultCreation() {
+ let result = SearchResult.suggestion(
+ text: "swift programming",
+ score: 0.75
+ )
+
+ XCTAssertEqual(result.type, .suggestion)
+ XCTAssertEqual(result.title, "swift programming")
+ XCTAssertEqual(result.score, 0.75)
+ }
+
+ func testSearchResultTypeEncoding() {
+ XCTAssertEqual(SearchResultType.article.rawValue, "article")
+ XCTAssertEqual(SearchResultType.feed.rawValue, "feed")
+ XCTAssertEqual(SearchResultType.suggestion.rawValue, "suggestion")
+ XCTAssertEqual(SearchResultType.tag.rawValue, "tag")
+ XCTAssertEqual(SearchResultType.author.rawValue, "author")
+ }
+
+ func testSearchResultEquatable() {
+ let result1 = SearchResult.article(id: "1", title: "Test")
+ let result2 = SearchResult.article(id: "1", title: "Test")
+ let result3 = SearchResult.article(id: "2", title: "Test")
+
+ XCTAssertEqual(result1, result2)
+ XCTAssertNotEqual(result1, result3)
+ }
+
+ func testSearchResults totalCount() {
+ let results = SearchResults(
+ articles: [SearchResult.article(id: "1", title: "A")],
+ feeds: [SearchResult.feed(id: "2", title: "F")],
+ suggestions: []
+ )
+
+ XCTAssertEqual(results.totalCount, 2)
+ XCTAssertTrue(results.hasResults)
+ }
+
+ func testSearchResultsEmpty() {
+ let results = SearchResults(articles: [], feeds: [], suggestions: [])
+
+ XCTAssertEqual(results.totalCount, 0)
+ XCTAssertFalse(results.hasResults)
+ }
+}
diff --git a/iOS/RSSuperTests/SyncSchedulerTests.swift b/iOS/RSSuperTests/SyncSchedulerTests.swift
new file mode 100644
index 0000000..7375bca
--- /dev/null
+++ b/iOS/RSSuperTests/SyncSchedulerTests.swift
@@ -0,0 +1,76 @@
+import XCTest
+@testable import RSSuper
+
+/// Unit tests for SyncScheduler
+final class SyncSchedulerTests: XCTestCase {
+
+ private var scheduler: SyncScheduler!
+
+ override func setUp() {
+ super.setUp()
+ scheduler = SyncScheduler()
+ }
+
+ override func tearDown() {
+ scheduler = nil
+ super.tearDown()
+ }
+
+ func testDefaultSyncInterval() {
+ XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.defaultSyncInterval)
+ }
+
+ func testSyncIntervalClamping() {
+ // Test minimum clamping
+ scheduler.preferredSyncInterval = 60 // 1 minute
+ XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.minimumSyncInterval)
+
+ // Test maximum clamping
+ scheduler.preferredSyncInterval = 48 * 3600 // 48 hours
+ XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.maximumSyncInterval)
+ }
+
+ func testIsSyncDue() {
+ // Fresh scheduler should have sync due
+ XCTAssertTrue(scheduler.isSyncDue)
+
+ // Set last sync date to recent past
+ scheduler.lastSyncDate = Date().addingTimeInterval(-1 * 3600) // 1 hour ago
+ XCTAssertFalse(scheduler.isSyncDue)
+
+ // Set last sync date to far past
+ scheduler.lastSyncDate = Date().addingTimeInterval(-12 * 3600) // 12 hours ago
+ XCTAssertTrue(scheduler.isSyncDue)
+ }
+
+ func testTimeSinceLastSync() {
+ scheduler.lastSyncDate = Date().addingTimeInterval(-3600) // 1 hour ago
+
+ let timeSince = scheduler.timeSinceLastSync
+ XCTAssertGreaterThan(timeSince, 3500)
+ XCTAssertLessThan(timeSince, 3700)
+ }
+
+ func testResetSyncSchedule() {
+ scheduler.preferredSyncInterval = 12 * 3600
+ scheduler.lastSyncDate = Date().addingTimeInterval(-100)
+
+ scheduler.resetSyncSchedule()
+
+ XCTAssertEqual(scheduler.preferredSyncInterval, SyncScheduler.defaultSyncInterval)
+ XCTAssertNil(scheduler.lastSyncDate)
+ }
+
+ func testUserActivityLevelCalculation() {
+ // High activity
+ XCTAssertEqual(UserActivityLevel.calculate(from: 5, lastOpenedAgo: 3600), .high)
+ XCTAssertEqual(UserActivityLevel.calculate(from: 1, lastOpenedAgo: 60), .high)
+
+ // Medium activity
+ XCTAssertEqual(UserActivityLevel.calculate(from: 2, lastOpenedAgo: 3600), .medium)
+ XCTAssertEqual(UserActivityLevel.calculate(from: 0, lastOpenedAgo: 43200), .medium)
+
+ // Low activity
+ XCTAssertEqual(UserActivityLevel.calculate(from: 0, lastOpenedAgo: 172800), .low)
+ }
+}
diff --git a/iOS/RSSuperUITests/RSSuperUITests.swift b/iOS/RSSuperUITests/RSSuperUITests.swift
new file mode 100644
index 0000000..069f728
--- /dev/null
+++ b/iOS/RSSuperUITests/RSSuperUITests.swift
@@ -0,0 +1,41 @@
+//
+// RSSuperUITests.swift
+// RSSuperUITests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+
+final class RSSuperUITests: XCTestCase {
+
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+
+ // In UI tests it is usually best to stop immediately when a failure occurs.
+ continueAfterFailure = false
+
+ // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ @MainActor
+ func testExample() throws {
+ // UI tests must launch the application that they test.
+ let app = XCUIApplication()
+ app.launch()
+
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ }
+
+ @MainActor
+ func testLaunchPerformance() throws {
+ // This measures how long it takes to launch your application.
+ measure(metrics: [XCTApplicationLaunchMetric()]) {
+ XCUIApplication().launch()
+ }
+ }
+}
diff --git a/iOS/RSSuperUITests/RSSuperUITestsLaunchTests.swift b/iOS/RSSuperUITests/RSSuperUITestsLaunchTests.swift
new file mode 100644
index 0000000..916e643
--- /dev/null
+++ b/iOS/RSSuperUITests/RSSuperUITestsLaunchTests.swift
@@ -0,0 +1,33 @@
+//
+// RSSuperUITestsLaunchTests.swift
+// RSSuperUITests
+//
+// Created by Mike Freno on 3/29/26.
+//
+
+import XCTest
+
+final class RSSuperUITestsLaunchTests: XCTestCase {
+
+ override class var runsForEachTargetApplicationUIConfiguration: Bool {
+ true
+ }
+
+ override func setUpWithError() throws {
+ continueAfterFailure = false
+ }
+
+ @MainActor
+ func testLaunch() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Insert steps here to perform after app launch but before taking a screenshot,
+ // such as logging into a test account or navigating somewhere in the app
+
+ let attachment = XCTAttachment(screenshot: app.screenshot())
+ attachment.name = "Launch Screen"
+ attachment.lifetime = .keepAlways
+ add(attachment)
+ }
+}
diff --git a/native-route/linux/.gitignore b/linux/.gitignore
similarity index 100%
rename from native-route/linux/.gitignore
rename to linux/.gitignore
diff --git a/native-route/linux/gsettings/org.rssuper.notification.preferences.gschema.xml b/linux/gsettings/org.rssuper.notification.preferences.gschema.xml
similarity index 100%
rename from native-route/linux/gsettings/org.rssuper.notification.preferences.gschema.xml
rename to linux/gsettings/org.rssuper.notification.preferences.gschema.xml
diff --git a/native-route/linux/meson.build b/linux/meson.build
similarity index 100%
rename from native-route/linux/meson.build
rename to linux/meson.build
diff --git a/native-route/linux/rssuper-database.vapi b/linux/rssuper-database.vapi
similarity index 100%
rename from native-route/linux/rssuper-database.vapi
rename to linux/rssuper-database.vapi
diff --git a/native-route/linux/src/database/database.vala b/linux/src/database/database.vala
similarity index 100%
rename from native-route/linux/src/database/database.vala
rename to linux/src/database/database.vala
diff --git a/native-route/linux/src/database/db-error.vala b/linux/src/database/db-error.vala
similarity index 100%
rename from native-route/linux/src/database/db-error.vala
rename to linux/src/database/db-error.vala
diff --git a/native-route/linux/src/database/feed-item-store.vala b/linux/src/database/feed-item-store.vala
similarity index 100%
rename from native-route/linux/src/database/feed-item-store.vala
rename to linux/src/database/feed-item-store.vala
diff --git a/native-route/linux/src/database/schema.sql b/linux/src/database/schema.sql
similarity index 100%
rename from native-route/linux/src/database/schema.sql
rename to linux/src/database/schema.sql
diff --git a/native-route/linux/src/database/search-history-store.vala b/linux/src/database/search-history-store.vala
similarity index 100%
rename from native-route/linux/src/database/search-history-store.vala
rename to linux/src/database/search-history-store.vala
diff --git a/native-route/linux/src/database/sqlite3.vapi b/linux/src/database/sqlite3.vapi
similarity index 100%
rename from native-route/linux/src/database/sqlite3.vapi
rename to linux/src/database/sqlite3.vapi
diff --git a/native-route/linux/src/database/subscription-store.vala b/linux/src/database/subscription-store.vala
similarity index 100%
rename from native-route/linux/src/database/subscription-store.vala
rename to linux/src/database/subscription-store.vala
diff --git a/native-route/linux/src/models/feed-item.vala b/linux/src/models/feed-item.vala
similarity index 100%
rename from native-route/linux/src/models/feed-item.vala
rename to linux/src/models/feed-item.vala
diff --git a/native-route/linux/src/models/feed-subscription.vala b/linux/src/models/feed-subscription.vala
similarity index 100%
rename from native-route/linux/src/models/feed-subscription.vala
rename to linux/src/models/feed-subscription.vala
diff --git a/native-route/linux/src/models/feed.vala b/linux/src/models/feed.vala
similarity index 100%
rename from native-route/linux/src/models/feed.vala
rename to linux/src/models/feed.vala
diff --git a/native-route/linux/src/models/namespaces.vala b/linux/src/models/namespaces.vala
similarity index 100%
rename from native-route/linux/src/models/namespaces.vala
rename to linux/src/models/namespaces.vala
diff --git a/native-route/linux/src/models/notification-preferences.vala b/linux/src/models/notification-preferences.vala
similarity index 100%
rename from native-route/linux/src/models/notification-preferences.vala
rename to linux/src/models/notification-preferences.vala
diff --git a/native-route/linux/src/models/reading-preferences.vala b/linux/src/models/reading-preferences.vala
similarity index 100%
rename from native-route/linux/src/models/reading-preferences.vala
rename to linux/src/models/reading-preferences.vala
diff --git a/native-route/linux/src/models/search-filters.vala b/linux/src/models/search-filters.vala
similarity index 100%
rename from native-route/linux/src/models/search-filters.vala
rename to linux/src/models/search-filters.vala
diff --git a/native-route/linux/src/models/search-result.vala b/linux/src/models/search-result.vala
similarity index 100%
rename from native-route/linux/src/models/search-result.vala
rename to linux/src/models/search-result.vala
diff --git a/native-route/linux/src/network/feed-fetcher.vala b/linux/src/network/feed-fetcher.vala
similarity index 100%
rename from native-route/linux/src/network/feed-fetcher.vala
rename to linux/src/network/feed-fetcher.vala
diff --git a/native-route/linux/src/network/fetch-result.vala b/linux/src/network/fetch-result.vala
similarity index 100%
rename from native-route/linux/src/network/fetch-result.vala
rename to linux/src/network/fetch-result.vala
diff --git a/native-route/linux/src/network/http-auth-credentials.vala b/linux/src/network/http-auth-credentials.vala
similarity index 100%
rename from native-route/linux/src/network/http-auth-credentials.vala
rename to linux/src/network/http-auth-credentials.vala
diff --git a/native-route/linux/src/network/network-error.vala b/linux/src/network/network-error.vala
similarity index 100%
rename from native-route/linux/src/network/network-error.vala
rename to linux/src/network/network-error.vala
diff --git a/native-route/linux/src/notification-manager.vala b/linux/src/notification-manager.vala
similarity index 100%
rename from native-route/linux/src/notification-manager.vala
rename to linux/src/notification-manager.vala
diff --git a/native-route/linux/src/notification-preferences-store.vala b/linux/src/notification-preferences-store.vala
similarity index 100%
rename from native-route/linux/src/notification-preferences-store.vala
rename to linux/src/notification-preferences-store.vala
diff --git a/native-route/linux/src/notification-service.vala b/linux/src/notification-service.vala
similarity index 100%
rename from native-route/linux/src/notification-service.vala
rename to linux/src/notification-service.vala
diff --git a/native-route/linux/src/parser/atom-parser.vala b/linux/src/parser/atom-parser.vala
similarity index 100%
rename from native-route/linux/src/parser/atom-parser.vala
rename to linux/src/parser/atom-parser.vala
diff --git a/native-route/linux/src/parser/feed-parser.vala b/linux/src/parser/feed-parser.vala
similarity index 100%
rename from native-route/linux/src/parser/feed-parser.vala
rename to linux/src/parser/feed-parser.vala
diff --git a/native-route/linux/src/parser/feed-type.vala b/linux/src/parser/feed-type.vala
similarity index 100%
rename from native-route/linux/src/parser/feed-type.vala
rename to linux/src/parser/feed-type.vala
diff --git a/native-route/linux/src/parser/parse-result.vala b/linux/src/parser/parse-result.vala
similarity index 100%
rename from native-route/linux/src/parser/parse-result.vala
rename to linux/src/parser/parse-result.vala
diff --git a/native-route/linux/src/parser/rss-parser.vala b/linux/src/parser/rss-parser.vala
similarity index 100%
rename from native-route/linux/src/parser/rss-parser.vala
rename to linux/src/parser/rss-parser.vala
diff --git a/native-route/linux/src/repository/Repositories.vala b/linux/src/repository/Repositories.vala
similarity index 100%
rename from native-route/linux/src/repository/Repositories.vala
rename to linux/src/repository/Repositories.vala
diff --git a/native-route/linux/src/repository/RepositoriesImpl.vala b/linux/src/repository/RepositoriesImpl.vala
similarity index 100%
rename from native-route/linux/src/repository/RepositoriesImpl.vala
rename to linux/src/repository/RepositoriesImpl.vala
diff --git a/native-route/linux/src/state/ErrorType.vala b/linux/src/state/ErrorType.vala
similarity index 100%
rename from native-route/linux/src/state/ErrorType.vala
rename to linux/src/state/ErrorType.vala
diff --git a/native-route/linux/src/state/State.vala b/linux/src/state/State.vala
similarity index 100%
rename from native-route/linux/src/state/State.vala
rename to linux/src/state/State.vala
diff --git a/native-route/linux/src/tests/database-tests.vala b/linux/src/tests/database-tests.vala
similarity index 100%
rename from native-route/linux/src/tests/database-tests.vala
rename to linux/src/tests/database-tests.vala
diff --git a/native-route/linux/src/tests/feed-fetcher-tests.vala b/linux/src/tests/feed-fetcher-tests.vala
similarity index 100%
rename from native-route/linux/src/tests/feed-fetcher-tests.vala
rename to linux/src/tests/feed-fetcher-tests.vala
diff --git a/native-route/linux/src/tests/parser-tests.vala b/linux/src/tests/parser-tests.vala
similarity index 100%
rename from native-route/linux/src/tests/parser-tests.vala
rename to linux/src/tests/parser-tests.vala
diff --git a/native-route/linux/src/viewmodel/FeedViewModel.vala b/linux/src/viewmodel/FeedViewModel.vala
similarity index 100%
rename from native-route/linux/src/viewmodel/FeedViewModel.vala
rename to linux/src/viewmodel/FeedViewModel.vala
diff --git a/native-route/linux/src/viewmodel/SubscriptionViewModel.vala b/linux/src/viewmodel/SubscriptionViewModel.vala
similarity index 100%
rename from native-route/linux/src/viewmodel/SubscriptionViewModel.vala
rename to linux/src/viewmodel/SubscriptionViewModel.vala
diff --git a/native-route/README.md b/native-route/README.md
deleted file mode 100644
index f70b672..0000000
--- a/native-route/README.md
+++ /dev/null
@@ -1,263 +0,0 @@
-# RSSuper - Multi-Platform Native Build System
-
-This directory contains the build infrastructure for building RSSuper natively across multiple platforms.
-
-## Architecture
-
-```
-native-route/
-├── ios/ - iOS/macOS app (Swift/SwiftUI)
-│ └── RSSuper/
-│ ├── RSSuper.xcodeproj/
-│ ├── RSSuper/
-│ ├── RSSuperTests/
-│ └── RSSuperUITests/
-├── android/ - Android app (Kotlin/Jetpack Compose)
-│ └── (auto-generated on first build)
-├── linux/ - Linux app (C/Vala + GTK4)
-│ └── (auto-generated on first build)
-└── windows/ - Windows app (TODO)
-```
-
-## Quick Start
-
-### Build All Platforms
-
-```bash
-# From project root
-./scripts/build.sh
-```
-
-### Build Specific Platform
-
-```bash
-# iOS/macOS only
-./scripts/build.sh -p ios
-
-# Android only
-./scripts/build.sh -p android
-
-# Linux only
-./scripts/build.sh -p linux
-
-# Multiple platforms
-./scripts/build.sh -p ios,android
-```
-
-### Build Types
-
-```bash
-# Debug build (default)
-./scripts/build.sh -t debug
-
-# Release build
-./scripts/build.sh -t release
-```
-
-### Run Tests
-
-```bash
-# Build and test all platforms
-./scripts/build.sh --test
-
-# Test specific platform
-./scripts/build.sh -p ios --test
-```
-
-### Clean Build
-
-```bash
-# Clean all platforms
-./scripts/build.sh -a clean
-
-# Clean specific platform
-./scripts/build-ios.sh clean
-./scripts/build-android.sh clean
-./scripts/build-linux.sh clean
-```
-
-## Individual Platform Scripts
-
-### iOS/macOS
-
-```bash
-# Build
-./scripts/build-ios.sh [Debug|Release] [iOS|macOS] [destination] [action]
-
-# Examples
-./scripts/build-ios.sh # Debug iOS
-./scripts/build-ios.sh Release # Release iOS
-./scripts/build-ios.sh Debug iOS "platform=iOS Simulator,name=iPhone 15"
-./scripts/build-ios.sh clean
-./scripts/build-ios.sh Debug iOS "generic/platform=iOS" test
-```
-
-### Android
-
-```bash
-# Build
-./scripts/build-android.sh [debug|release] [assemble|build|test|clean]
-
-# Examples
-./scripts/build-android.sh # Assemble debug
-./scripts/build-android.sh release # Assemble release
-./scripts/build-android.sh debug test # Run tests
-./scripts/build-android.sh clean # Clean
-```
-
-### Linux
-
-```bash
-# Build
-./scripts/build-linux.sh [debug|release] [build|install|test|clean|setup]
-
-# Examples
-./scripts/build-linux.sh # Build debug
-./scripts/build-linux.sh release # Build release
-./scripts/build-linux.sh debug setup # Setup build environment
-./scripts/build-linux.sh debug install-deps # Install dependencies
-./scripts/build-linux.sh debug run # Build and run
-./scripts/build-linux.sh clean # Clean
-```
-
-## Platform-Specific Details
-
-### iOS/macOS
-
-- **Language**: Swift
-- **UI Framework**: SwiftUI
-- **Build System**: Xcode/xcodebuild
-- **Minimum Deployment**: iOS 16.0+
-- **Features**:
- - SwiftUI for declarative UI
- - Combine for reactive programming
- - Core Data for persistence
- - Background fetch for feed updates
-
-### Android
-
-- **Language**: Kotlin
-- **UI Framework**: Jetpack Compose
-- **Build System**: Gradle
-- **Minimum SDK**: 24 (Android 7.0)
-- **Features**:
- - Jetpack Compose for modern UI
- - ViewModel + LiveData for state management
- - Room for local database
- - Retrofit for networking
-
-### Linux
-
-- **Language**: C + Vala
-- **UI Framework**: GTK4 + Libadwaita
-- **Build System**: Meson + Ninja
-- **Dependencies**:
- - GTK4
- - Libadwaita
- - SQLite3
- - libxml2
- - libsoup-3.0
-- **Features**:
- - Native Linux look and feel
- - GNOME integration
- - System tray support
- - Desktop notifications
-
-## CI/CD
-
-GitHub Actions workflow is configured in `.github/workflows/ci.yml`:
-
-- **iOS**: Builds on macos-15 runner
-- **Android**: Builds on ubuntu-24.04 runner
-- **Linux**: Builds on ubuntu-24.04 runner
-
-### Workflow Features
-
-- Automatic builds on push/PR
-- Manual trigger with configurable options
-- Build artifacts uploaded for download
-- Build reports generated
-- Test execution (configurable)
-
-## Project Structure Template
-
-When you add shared code, use this structure:
-
-```
-RSSuper/
-├── native-route/
-│ ├── common/ # Shared code (if using a shared language)
-│ ├── ios/
-│ │ └── RSSuper/
-│ ├── android/
-│ ├── linux/
-│ └── windows/
-├── scripts/
-│ ├── build.sh # Main build orchestrator
-│ ├── build-ios.sh # iOS/macOS builder
-│ ├── build-android.sh # Android builder
-│ ├── build-linux.sh # Linux builder
-│ └── common.sh # Shared utilities
-└── .github/
- └── workflows/
- └── ci.yml # CI configuration
-```
-
-## Migration Notes
-
-Build scripts adapted from Nessa project:
-- Xcode version selection logic
-- Build report generation
-- Error extraction and display
-- CI workflow structure
-
-## Troubleshooting
-
-### iOS Build Fails
-
-```bash
-# Check Xcode installation
-xcodebuild -version
-
-# Select Xcode manually
-sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
-
-# Clean DerivedData
-rm -rf ~/Library/Developer/Xcode/DerivedData/RSSuper-*
-```
-
-### Android Build Fails
-
-```bash
-# Check Java installation
-java -version
-
-# Check Android SDK
-echo $ANDROID_HOME
-
-# Run with more verbose output
-./scripts/build-android.sh debug assemble --info
-```
-
-### Linux Build Fails
-
-```bash
-# Install dependencies (Ubuntu/Debian)
-sudo apt install meson ninja-build pkg-config libgtk-4-dev libadwaita-1-dev
-
-# Check meson installation
-meson --version
-
-# Setup build manually
-cd native-route/linux
-meson setup build --buildtype=debug
-```
-
-## Future Enhancements
-
-- [ ] Windows support (Win32 + DirectUI or WebView2)
-- [ ] Shared business logic layer
-- [ ] Cross-platform test suite
-- [ ] Automated code signing
-- [ ] App store deployment scripts
-- [ ] Performance benchmarking
diff --git a/native-route/ios/RSSuper b/native-route/ios/RSSuper
deleted file mode 160000
index 7916c92..0000000
--- a/native-route/ios/RSSuper
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 7916c92d76f52081c142c849b6324a11eabd6b96
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index a252957..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,8068 +0,0 @@
-{
- "name": "rssuper",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "rssuper",
- "version": "1.0.0",
- "dependencies": {
- "@react-native-async-storage/async-storage": "^3.0.2",
- "@react-navigation/bottom-tabs": "^7.15.5",
- "@react-navigation/elements": "^2.9.10",
- "@react-navigation/native": "^7.1.33",
- "@tanstack/react-query": "^5.95.2",
- "axios": "^1.14.0",
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "expo-device": "55.0.11-canary-20260328-2049187",
- "expo-font": "55.0.5-canary-20260328-2049187",
- "expo-glass-effect": "55.0.9-canary-20260328-2049187",
- "expo-image": "55.0.7-canary-20260328-2049187",
- "expo-linking": "55.0.10-canary-20260328-2049187",
- "expo-localization": "55.0.10-canary-20260328-2049187",
- "expo-notifications": "55.0.15-canary-20260328-2049187",
- "expo-router": "55.0.9-canary-20260328-2049187",
- "expo-splash-screen": "55.0.14-canary-20260328-2049187",
- "expo-sqlite": "55.0.12-canary-20260328-2049187",
- "expo-status-bar": "55.0.5-canary-20260328-2049187",
- "expo-symbols": "55.0.6-canary-20260328-2049187",
- "expo-system-ui": "55.0.12-canary-20260328-2049187",
- "expo-task-manager": "55.0.11-canary-20260328-2049187",
- "expo-web-browser": "55.0.11-canary-20260328-2049187",
- "react": "19.2.0",
- "react-dom": "19.2.0",
- "react-native": "0.83.4",
- "react-native-gesture-handler": "~2.30.0",
- "react-native-reanimated": "4.2.1",
- "react-native-render-html": "^6.3.4",
- "react-native-safe-area-context": "~5.6.2",
- "react-native-screens": "~4.23.0",
- "react-native-web": "~0.21.0",
- "react-native-worklets": "0.7.2",
- "xml2js": "^0.6.2",
- "zustand": "^5.0.12"
- },
- "devDependencies": {
- "@types/react": "~19.2.2",
- "@types/xml2js": "^0.4.14",
- "typescript": "~5.9.2"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.28.5",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.29.0",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helpers": "^7.28.6",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/remapping": "^2.3.5",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/core/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.29.1",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.29.0",
- "@babel/types": "^7.29.0",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.27.3",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.3"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/helper-replace-supers": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/traverse": "^7.28.6",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.28.5",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "regexpu-core": "^6.3.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.6.8",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "debug": "^4.4.3",
- "lodash.debounce": "^4.0.8",
- "resolve": "^1.22.11"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.28.5",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.5",
- "@babel/types": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-validator-identifier": "^7.28.5",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.28.6",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.1",
- "@babel/helper-wrap-function": "^7.27.1",
- "@babel/traverse": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-replace-supers": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.28.5",
- "@babel/helper-optimise-call-expression": "^7.27.1",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.28.5",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-wrap-function": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/traverse": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.29.2",
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.29.2",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.29.0"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-proposal-decorators": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/plugin-syntax-decorators": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-proposal-export-default-from": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-bigint": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-decorators": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-export-default-from": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-flow": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-arrow-functions": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-async-generator-functions": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-remap-async-to-generator": "^7.27.1",
- "@babel/traverse": "^7.29.0"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-async-to-generator": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-remap-async-to-generator": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-properties": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-class-static-block": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.12.0"
- }
- },
- "node_modules/@babel/plugin-transform-classes": {
- "version": "7.28.4",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-compilation-targets": "^7.27.2",
- "@babel/helper-globals": "^7.28.0",
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-replace-supers": "^7.27.1",
- "@babel/traverse": "^7.28.4"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-computed-properties": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/template": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.28.5",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/traverse": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-export-namespace-from": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-flow-strip-types": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/plugin-syntax-flow": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-for-of": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-function-name": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/traverse": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-literals": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-logical-assignment-operators": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-transforms": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.28.5",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-numeric-separator": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-object-rest-spread": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-compilation-targets": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/plugin-transform-destructuring": "^7.28.5",
- "@babel/plugin-transform-parameters": "^7.27.7",
- "@babel/traverse": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-catch-binding": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-optional-chaining": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-parameters": {
- "version": "7.27.7",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-private-methods": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-private-property-in-object": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-display-name": {
- "version": "7.28.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/plugin-syntax-jsx": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-development": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/plugin-transform-react-jsx": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-self": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-jsx-source": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-react-pure-annotations": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-runtime": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-module-imports": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "babel-plugin-polyfill-corejs2": "^0.4.14",
- "babel-plugin-polyfill-corejs3": "^0.13.0",
- "babel-plugin-polyfill-regenerator": "^0.6.5",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/@babel/plugin-transform-shorthand-properties": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-spread": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-sticky-regex": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-template-literals": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-typescript": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.27.3",
- "@babel/helper-create-class-features-plugin": "^7.28.6",
- "@babel/helper-plugin-utils": "^7.28.6",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
- "@babel/plugin-syntax-typescript": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-transform-unicode-regex": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.27.1",
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-react": {
- "version": "7.28.5",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-validator-option": "^7.27.1",
- "@babel/plugin-transform-react-display-name": "^7.28.0",
- "@babel/plugin-transform-react-jsx": "^7.27.1",
- "@babel/plugin-transform-react-jsx-development": "^7.27.1",
- "@babel/plugin-transform-react-pure-annotations": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/preset-typescript": {
- "version": "7.27.1",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1",
- "@babel/helper-validator-option": "^7.27.1",
- "@babel/plugin-syntax-jsx": "^7.27.1",
- "@babel/plugin-transform-modules-commonjs": "^7.27.1",
- "@babel/plugin-transform-typescript": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/runtime": {
- "version": "7.29.2",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.28.6",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.28.6",
- "@babel/parser": "^7.28.6",
- "@babel/types": "^7.28.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse--for-generate-function-map": {
- "name": "@babel/traverse",
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.29.0",
- "@babel/generator": "^7.29.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.29.0",
- "@babel/template": "^7.28.6",
- "@babel/types": "^7.29.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.29.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.28.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@egjs/hammerjs": {
- "version": "2.0.17",
- "license": "MIT",
- "dependencies": {
- "@types/hammerjs": "^2.0.36"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@expo-google-fonts/material-symbols": {
- "version": "0.4.27",
- "license": "MIT AND Apache-2.0"
- },
- "node_modules/@expo/cli": {
- "version": "55.0.20-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/code-signing-certificates": "^0.0.6",
- "@expo/config": "55.0.12-canary-20260328-2049187",
- "@expo/config-plugins": "55.0.8-canary-20260328-2049187",
- "@expo/devcert": "^1.2.1",
- "@expo/env": "2.1.2-canary-20260328-2049187",
- "@expo/image-utils": "0.8.13-canary-20260328-2049187",
- "@expo/json-file": "10.0.13-canary-20260328-2049187",
- "@expo/log-box": "55.0.9-canary-20260328-2049187",
- "@expo/metro": "~54.2.0",
- "@expo/metro-config": "55.0.12-canary-20260328-2049187",
- "@expo/osascript": "2.4.3-canary-20260328-2049187",
- "@expo/package-manager": "1.10.4-canary-20260328-2049187",
- "@expo/plist": "0.5.3-canary-20260328-2049187",
- "@expo/prebuild-config": "55.0.12-canary-20260328-2049187",
- "@expo/require-utils": "55.0.4-canary-20260328-2049187",
- "@expo/router-server": "55.0.12-canary-20260328-2049187",
- "@expo/schema-utils": "55.0.3-canary-20260328-2049187",
- "@expo/spawn-async": "^1.7.2",
- "@expo/ws-tunnel": "^1.0.1",
- "@expo/xcpretty": "^4.4.0",
- "@react-native/dev-middleware": "0.83.4",
- "accepts": "^1.3.8",
- "arg": "^5.0.2",
- "better-opn": "~3.0.2",
- "bplist-creator": "0.1.0",
- "bplist-parser": "^0.3.1",
- "chalk": "^4.0.0",
- "ci-info": "^3.3.0",
- "compression": "^1.7.4",
- "connect": "^3.7.0",
- "debug": "^4.3.4",
- "dnssd-advertise": "^1.1.3",
- "expo-server": "55.0.7-canary-20260328-2049187",
- "fetch-nodeshim": "^0.4.6",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "lan-network": "^0.2.0",
- "multitars": "^0.2.3",
- "node-forge": "^1.3.3",
- "npm-package-arg": "^11.0.0",
- "ora": "^3.4.0",
- "picomatch": "^4.0.3",
- "pretty-format": "^29.7.0",
- "progress": "^2.0.3",
- "prompts": "^2.3.2",
- "resolve-from": "^5.0.0",
- "semver": "^7.6.0",
- "send": "^0.19.0",
- "slugify": "^1.3.4",
- "source-map-support": "~0.5.21",
- "stacktrace-parser": "^0.1.10",
- "structured-headers": "^0.4.1",
- "terminal-link": "^2.1.1",
- "toqr": "^0.1.1",
- "wrap-ansi": "^7.0.0",
- "ws": "^8.12.1",
- "zod": "^3.25.76"
- },
- "bin": {
- "expo-internal": "build/bin/cli"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-router": "55.0.9-canary-20260328-2049187",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "expo-router": {
- "optional": true
- },
- "react-native": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/cli/node_modules/glob": {
- "version": "13.0.6",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@expo/cli/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@expo/cli/node_modules/ws": {
- "version": "8.20.0",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/code-signing-certificates": {
- "version": "0.0.6",
- "license": "MIT",
- "dependencies": {
- "node-forge": "^1.3.3"
- }
- },
- "node_modules/@expo/config": {
- "version": "55.0.12-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/config-plugins": "55.0.8-canary-20260328-2049187",
- "@expo/config-types": "55.0.6-canary-20260328-2049187",
- "@expo/json-file": "10.0.13-canary-20260328-2049187",
- "@expo/require-utils": "55.0.4-canary-20260328-2049187",
- "deepmerge": "^4.3.1",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "resolve-from": "^5.0.0",
- "resolve-workspace-root": "^2.0.0",
- "semver": "^7.6.0",
- "slugify": "^1.3.4"
- }
- },
- "node_modules/@expo/config-plugins": {
- "version": "55.0.8-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/config-types": "55.0.6-canary-20260328-2049187",
- "@expo/json-file": "10.0.13-canary-20260328-2049187",
- "@expo/plist": "0.5.3-canary-20260328-2049187",
- "@expo/sdk-runtime-versions": "^1.0.0",
- "chalk": "^4.1.2",
- "debug": "^4.3.5",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "resolve-from": "^5.0.0",
- "semver": "^7.5.4",
- "slugify": "^1.6.6",
- "xcode": "^3.0.1",
- "xml2js": "0.6.0"
- }
- },
- "node_modules/@expo/config-plugins/node_modules/glob": {
- "version": "13.0.6",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@expo/config-plugins/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@expo/config-plugins/node_modules/xml2js": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz",
- "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==",
- "license": "MIT",
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/@expo/config-plugins/node_modules/xmlbuilder": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
- "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/@expo/config-types": {
- "version": "55.0.6-canary-20260328-2049187",
- "license": "MIT"
- },
- "node_modules/@expo/config/node_modules/glob": {
- "version": "13.0.6",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@expo/config/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@expo/devcert": {
- "version": "1.2.1",
- "license": "MIT",
- "dependencies": {
- "@expo/sudo-prompt": "^9.3.1",
- "debug": "^3.1.0"
- }
- },
- "node_modules/@expo/devcert/node_modules/debug": {
- "version": "3.2.7",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/@expo/devtools": {
- "version": "55.0.3-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.1.2"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "react": {
- "optional": true
- },
- "react-native": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/dom-webview": {
- "version": "55.0.4-canary-20260328-2049187",
- "license": "MIT",
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/@expo/env": {
- "version": "2.1.2-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.0.0",
- "debug": "^4.3.4",
- "getenv": "^2.0.0"
- },
- "engines": {
- "node": ">=20.12.0"
- }
- },
- "node_modules/@expo/fingerprint": {
- "version": "0.16.7-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/env": "2.1.2-canary-20260328-2049187",
- "@expo/spawn-async": "^1.7.2",
- "arg": "^5.0.2",
- "chalk": "^4.1.2",
- "debug": "^4.3.4",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "ignore": "^5.3.1",
- "minimatch": "^10.2.2",
- "resolve-from": "^5.0.0",
- "semver": "^7.6.0"
- },
- "bin": {
- "fingerprint": "bin/cli.js"
- }
- },
- "node_modules/@expo/fingerprint/node_modules/glob": {
- "version": "13.0.6",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@expo/fingerprint/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@expo/image-utils": {
- "version": "0.8.13-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/spawn-async": "^1.7.2",
- "chalk": "^4.0.0",
- "getenv": "^2.0.0",
- "jimp-compact": "0.16.1",
- "parse-png": "^2.1.0",
- "resolve-from": "^5.0.0",
- "semver": "^7.6.0"
- }
- },
- "node_modules/@expo/image-utils/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@expo/json-file": {
- "version": "10.0.13-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.20.0",
- "json5": "^2.2.3"
- }
- },
- "node_modules/@expo/local-build-cache-provider": {
- "version": "55.0.8-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/config": "55.0.12-canary-20260328-2049187",
- "chalk": "^4.1.2"
- }
- },
- "node_modules/@expo/log-box": {
- "version": "55.0.9-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/dom-webview": "55.0.4-canary-20260328-2049187",
- "anser": "^1.4.9",
- "stacktrace-parser": "^0.1.10"
- },
- "peerDependencies": {
- "@expo/dom-webview": "55.0.4-canary-20260328-2049187",
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/@expo/metro": {
- "version": "54.2.0",
- "license": "MIT",
- "dependencies": {
- "metro": "0.83.3",
- "metro-babel-transformer": "0.83.3",
- "metro-cache": "0.83.3",
- "metro-cache-key": "0.83.3",
- "metro-config": "0.83.3",
- "metro-core": "0.83.3",
- "metro-file-map": "0.83.3",
- "metro-minify-terser": "0.83.3",
- "metro-resolver": "0.83.3",
- "metro-runtime": "0.83.3",
- "metro-source-map": "0.83.3",
- "metro-symbolicate": "0.83.3",
- "metro-transform-plugins": "0.83.3",
- "metro-transform-worker": "0.83.3"
- }
- },
- "node_modules/@expo/metro-config": {
- "version": "55.0.12-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.20.0",
- "@babel/core": "^7.20.0",
- "@babel/generator": "^7.20.5",
- "@expo/config": "55.0.12-canary-20260328-2049187",
- "@expo/env": "2.1.2-canary-20260328-2049187",
- "@expo/json-file": "10.0.13-canary-20260328-2049187",
- "@expo/metro": "~54.2.0",
- "@expo/spawn-async": "^1.7.2",
- "browserslist": "^4.25.0",
- "chalk": "^4.1.0",
- "debug": "^4.3.2",
- "getenv": "^2.0.0",
- "glob": "^13.0.0",
- "hermes-parser": "^0.32.0",
- "jsc-safe-url": "^0.2.4",
- "lightningcss": "^1.30.1",
- "picomatch": "^4.0.3",
- "postcss": "~8.4.32",
- "resolve-from": "^5.0.0"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187"
- },
- "peerDependenciesMeta": {
- "expo": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/metro-config/node_modules/glob": {
- "version": "13.0.6",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "minimatch": "^10.2.2",
- "minipass": "^7.1.3",
- "path-scurry": "^2.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@expo/metro-runtime": {
- "version": "55.0.8-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/log-box": "55.0.9-canary-20260328-2049187",
- "anser": "^1.4.9",
- "pretty-format": "^29.7.0",
- "stacktrace-parser": "^0.1.10",
- "whatwg-fetch": "^3.0.0"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-dom": "*",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/osascript": {
- "version": "2.4.3-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/spawn-async": "^1.7.2"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@expo/package-manager": {
- "version": "1.10.4-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/json-file": "10.0.13-canary-20260328-2049187",
- "@expo/spawn-async": "^1.7.2",
- "chalk": "^4.0.0",
- "npm-package-arg": "^11.0.0",
- "ora": "^3.4.0",
- "resolve-workspace-root": "^2.0.0"
- }
- },
- "node_modules/@expo/plist": {
- "version": "0.5.3-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@xmldom/xmldom": "^0.8.8",
- "base64-js": "^1.5.1",
- "xmlbuilder": "^15.1.1"
- }
- },
- "node_modules/@expo/prebuild-config": {
- "version": "55.0.12-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/config": "55.0.12-canary-20260328-2049187",
- "@expo/config-plugins": "55.0.8-canary-20260328-2049187",
- "@expo/config-types": "55.0.6-canary-20260328-2049187",
- "@expo/image-utils": "0.8.13-canary-20260328-2049187",
- "@expo/json-file": "10.0.13-canary-20260328-2049187",
- "@react-native/normalize-colors": "0.83.4",
- "debug": "^4.3.1",
- "resolve-from": "^5.0.0",
- "semver": "^7.6.0",
- "xml2js": "0.6.0"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187"
- }
- },
- "node_modules/@expo/prebuild-config/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@expo/prebuild-config/node_modules/xml2js": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz",
- "integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==",
- "license": "MIT",
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/@expo/prebuild-config/node_modules/xmlbuilder": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
- "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/@expo/require-utils": {
- "version": "55.0.4-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.20.0",
- "@babel/core": "^7.25.2",
- "@babel/plugin-transform-modules-commonjs": "^7.24.8"
- },
- "peerDependencies": {
- "typescript": "^5.0.0 || ^5.0.0-0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/router-server": {
- "version": "55.0.12-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.3.4"
- },
- "peerDependencies": {
- "@expo/metro-runtime": "55.0.8-canary-20260328-2049187",
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "expo-font": "55.0.5-canary-20260328-2049187",
- "expo-router": "55.0.9-canary-20260328-2049187",
- "expo-server": "55.0.7-canary-20260328-2049187",
- "react": "*",
- "react-dom": "*",
- "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1"
- },
- "peerDependenciesMeta": {
- "@expo/metro-runtime": {
- "optional": true
- },
- "expo-router": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- },
- "react-server-dom-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/@expo/schema-utils": {
- "version": "55.0.3-canary-20260328-2049187",
- "license": "MIT"
- },
- "node_modules/@expo/sdk-runtime-versions": {
- "version": "1.0.0",
- "license": "MIT"
- },
- "node_modules/@expo/spawn-async": {
- "version": "1.7.2",
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.3"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@expo/sudo-prompt": {
- "version": "9.3.2",
- "license": "MIT"
- },
- "node_modules/@expo/vector-icons": {
- "version": "15.1.1",
- "license": "MIT",
- "peerDependencies": {
- "expo-font": ">=14.0.4",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/@expo/ws-tunnel": {
- "version": "1.0.6",
- "license": "MIT"
- },
- "node_modules/@expo/xcpretty": {
- "version": "4.4.1",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@babel/code-frame": "^7.20.0",
- "chalk": "^4.1.0",
- "js-yaml": "^4.1.0"
- },
- "bin": {
- "excpretty": "build/cli.js"
- }
- },
- "node_modules/@isaacs/ttlcache": {
- "version": "1.4.1",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config": {
- "version": "1.1.0",
- "license": "ISC",
- "dependencies": {
- "camelcase": "^5.3.1",
- "find-up": "^4.1.0",
- "get-package-type": "^0.1.0",
- "js-yaml": "^3.13.1",
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": {
- "version": "5.3.1",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
- "version": "3.14.2",
- "license": "MIT",
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml/node_modules/argparse": {
- "version": "1.0.10",
- "license": "MIT",
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "node_modules/@istanbuljs/schema": {
- "version": "0.1.3",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@jest/create-cache-key-function": {
- "version": "29.7.0",
- "license": "MIT",
- "dependencies": {
- "@jest/types": "^29.6.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/environment": {
- "version": "29.7.0",
- "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/@jest/fake-timers": {
- "version": "29.7.0",
- "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/@jest/schemas": {
- "version": "29.6.3",
- "license": "MIT",
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/transform": {
- "version": "29.7.0",
- "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/@jest/types": {
- "version": "29.6.3",
- "license": "MIT",
- "dependencies": {
- "@jest/schemas": "^29.6.3",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^17.0.8",
- "chalk": "^4.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.13",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/remapping": {
- "version": "2.3.5",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/source-map": {
- "version": "0.3.11",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.31",
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@jsamr/counter-style": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/@jsamr/counter-style/-/counter-style-2.0.2.tgz",
- "integrity": "sha512-2mXudGVtSzVxWEA7B9jZLKjoXUeUFYDDtFrQoC0IFX9/Dszz4t1vZOmafi3JSw/FxD+udMQ+4TAFR8Qs0J3URQ==",
- "license": "MIT"
- },
- "node_modules/@jsamr/react-native-li": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/@jsamr/react-native-li/-/react-native-li-2.3.1.tgz",
- "integrity": "sha512-Qbo4NEj48SQ4k8FZJHFE2fgZDKTWaUGmVxcIQh3msg5JezLdTMMHuRRDYctfdHI6L0FZGObmEv3haWbIvmol8w==",
- "license": "MIT",
- "peerDependencies": {
- "@jsamr/counter-style": "^1.0.0 || ^2.0.0",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/@native-html/css-processor": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/@native-html/css-processor/-/css-processor-1.11.0.tgz",
- "integrity": "sha512-NnhBEbJX5M2gBGltPKOetiLlKhNf3OHdRafc8//e2ZQxXN8JaSW/Hy8cm94pnIckQxwaMKxrtaNT3x4ZcffoNQ==",
- "license": "MIT",
- "dependencies": {
- "css-to-react-native": "^3.0.0",
- "csstype": "^3.0.8"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-native": "*"
- }
- },
- "node_modules/@native-html/transient-render-engine": {
- "version": "11.2.3",
- "resolved": "https://registry.npmjs.org/@native-html/transient-render-engine/-/transient-render-engine-11.2.3.tgz",
- "integrity": "sha512-zXwgA3gPUEmFs3I3syfnvDvS6WiUHXEE6jY09OBzK+trq7wkweOSFWIoyXiGkbXrozGYG0KY90YgPyr8Tg8Uyg==",
- "license": "MIT",
- "dependencies": {
- "@native-html/css-processor": "1.11.0",
- "@types/ramda": "^0.27.44",
- "csstype": "^3.0.9",
- "domelementtype": "^2.2.0",
- "domhandler": "^4.2.2",
- "domutils": "^2.8.0",
- "htmlparser2": "^7.1.2",
- "ramda": "^0.27.2"
- },
- "peerDependencies": {
- "@types/react-native": "*",
- "react-native": "^*"
- }
- },
- "node_modules/@radix-ui/primitive": {
- "version": "1.1.3",
- "license": "MIT"
- },
- "node_modules/@radix-ui/react-collection": {
- "version": "1.1.7",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-compose-refs": {
- "version": "1.1.2",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-context": {
- "version": "1.1.2",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dialog": {
- "version": "1.1.15",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-dismissable-layer": "1.1.11",
- "@radix-ui/react-focus-guards": "1.1.3",
- "@radix-ui/react-focus-scope": "1.1.7",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-portal": "1.1.9",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-slot": "1.2.3",
- "@radix-ui/react-use-controllable-state": "1.2.2",
- "aria-hidden": "^1.2.4",
- "react-remove-scroll": "^2.6.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-direction": {
- "version": "1.1.1",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-dismissable-layer": {
- "version": "1.1.11",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-escape-keydown": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-focus-guards": {
- "version": "1.1.3",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-focus-scope": {
- "version": "1.1.7",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-id": {
- "version": "1.1.1",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-portal": {
- "version": "1.1.9",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-presence": {
- "version": "1.1.5",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-primitive": {
- "version": "2.1.3",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-slot": "1.2.3"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": {
- "version": "1.2.3",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-roving-focus": {
- "version": "1.1.11",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-collection": "1.1.7",
- "@radix-ui/react-compose-refs": "1.1.2",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-use-callback-ref": "1.1.1",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-slot": {
- "version": "1.2.4",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-compose-refs": "1.1.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-tabs": {
- "version": "1.1.13",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/primitive": "1.1.3",
- "@radix-ui/react-context": "1.1.2",
- "@radix-ui/react-direction": "1.1.1",
- "@radix-ui/react-id": "1.1.1",
- "@radix-ui/react-presence": "1.1.5",
- "@radix-ui/react-primitive": "2.1.3",
- "@radix-ui/react-roving-focus": "1.1.11",
- "@radix-ui/react-use-controllable-state": "1.2.2"
- },
- "peerDependencies": {
- "@types/react": "*",
- "@types/react-dom": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "@types/react-dom": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-callback-ref": {
- "version": "1.1.1",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-controllable-state": {
- "version": "1.2.2",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-effect-event": "0.0.2",
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-effect-event": {
- "version": "0.0.2",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-layout-effect": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-escape-keydown": {
- "version": "1.1.1",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-use-callback-ref": "1.1.1"
- },
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@radix-ui/react-use-layout-effect": {
- "version": "1.1.1",
- "license": "MIT",
- "peerDependencies": {
- "@types/react": "*",
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@react-native-async-storage/async-storage": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-3.0.2.tgz",
- "integrity": "sha512-XP0zDIl+1XoeuQ7f878qXKdl77zLwzLALPpxvNRc7ZtDh9ew36WSvOdQOhFkexMySapFAWxEbZxS8K8J2DU4eg==",
- "license": "MIT",
- "dependencies": {
- "idb": "8.0.3"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/@react-native/assets-registry": {
- "version": "0.83.4",
- "license": "MIT",
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/babel-plugin-codegen": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.3",
- "@react-native/codegen": "0.83.4"
- },
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/babel-preset": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/plugin-proposal-export-default-from": "^7.24.7",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-export-default-from": "^7.24.7",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-transform-arrow-functions": "^7.24.7",
- "@babel/plugin-transform-async-generator-functions": "^7.25.4",
- "@babel/plugin-transform-async-to-generator": "^7.24.7",
- "@babel/plugin-transform-block-scoping": "^7.25.0",
- "@babel/plugin-transform-class-properties": "^7.25.4",
- "@babel/plugin-transform-classes": "^7.25.4",
- "@babel/plugin-transform-computed-properties": "^7.24.7",
- "@babel/plugin-transform-destructuring": "^7.24.8",
- "@babel/plugin-transform-flow-strip-types": "^7.25.2",
- "@babel/plugin-transform-for-of": "^7.24.7",
- "@babel/plugin-transform-function-name": "^7.25.1",
- "@babel/plugin-transform-literals": "^7.25.2",
- "@babel/plugin-transform-logical-assignment-operators": "^7.24.7",
- "@babel/plugin-transform-modules-commonjs": "^7.24.8",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7",
- "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7",
- "@babel/plugin-transform-numeric-separator": "^7.24.7",
- "@babel/plugin-transform-object-rest-spread": "^7.24.7",
- "@babel/plugin-transform-optional-catch-binding": "^7.24.7",
- "@babel/plugin-transform-optional-chaining": "^7.24.8",
- "@babel/plugin-transform-parameters": "^7.24.7",
- "@babel/plugin-transform-private-methods": "^7.24.7",
- "@babel/plugin-transform-private-property-in-object": "^7.24.7",
- "@babel/plugin-transform-react-display-name": "^7.24.7",
- "@babel/plugin-transform-react-jsx": "^7.25.2",
- "@babel/plugin-transform-react-jsx-self": "^7.24.7",
- "@babel/plugin-transform-react-jsx-source": "^7.24.7",
- "@babel/plugin-transform-regenerator": "^7.24.7",
- "@babel/plugin-transform-runtime": "^7.24.7",
- "@babel/plugin-transform-shorthand-properties": "^7.24.7",
- "@babel/plugin-transform-spread": "^7.24.7",
- "@babel/plugin-transform-sticky-regex": "^7.24.7",
- "@babel/plugin-transform-typescript": "^7.25.2",
- "@babel/plugin-transform-unicode-regex": "^7.24.7",
- "@babel/template": "^7.25.0",
- "@react-native/babel-plugin-codegen": "0.83.4",
- "babel-plugin-syntax-hermes-parser": "0.32.0",
- "babel-plugin-transform-flow-enums": "^0.0.2",
- "react-refresh": "^0.14.0"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@babel/core": "*"
- }
- },
- "node_modules/@react-native/codegen": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/parser": "^7.25.3",
- "glob": "^7.1.1",
- "hermes-parser": "0.32.0",
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1",
- "yargs": "^17.6.2"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@babel/core": "*"
- }
- },
- "node_modules/@react-native/codegen/node_modules/hermes-parser": {
- "version": "0.32.0",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.32.0"
- }
- },
- "node_modules/@react-native/codegen/node_modules/hermes-parser/node_modules/hermes-estree": {
- "version": "0.32.0",
- "license": "MIT"
- },
- "node_modules/@react-native/community-cli-plugin": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "@react-native/dev-middleware": "0.83.4",
- "debug": "^4.4.0",
- "invariant": "^2.2.4",
- "metro": "^0.83.3",
- "metro-config": "^0.83.3",
- "metro-core": "^0.83.3",
- "semver": "^7.1.3"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@react-native-community/cli": "*",
- "@react-native/metro-config": "*"
- },
- "peerDependenciesMeta": {
- "@react-native-community/cli": {
- "optional": true
- },
- "@react-native/metro-config": {
- "optional": true
- }
- }
- },
- "node_modules/@react-native/community-cli-plugin/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@react-native/debugger-frontend": {
- "version": "0.83.4",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/debugger-shell": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "fb-dotslash": "0.5.8"
- },
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/dev-middleware": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "@isaacs/ttlcache": "^1.4.1",
- "@react-native/debugger-frontend": "0.83.4",
- "@react-native/debugger-shell": "0.83.4",
- "chrome-launcher": "^0.15.2",
- "chromium-edge-launcher": "^0.2.0",
- "connect": "^3.6.5",
- "debug": "^4.4.0",
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1",
- "open": "^7.0.3",
- "serve-static": "^1.16.2",
- "ws": "^7.5.10"
- },
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/gradle-plugin": {
- "version": "0.83.4",
- "license": "MIT",
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/js-polyfills": {
- "version": "0.83.4",
- "license": "MIT",
- "engines": {
- "node": ">= 20.19.4"
- }
- },
- "node_modules/@react-native/normalize-colors": {
- "version": "0.83.4",
- "license": "MIT"
- },
- "node_modules/@react-native/virtualized-lists": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@types/react": "^19.2.0",
- "react": "*",
- "react-native": "*"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/@react-navigation/bottom-tabs": {
- "version": "7.15.9",
- "license": "MIT",
- "dependencies": {
- "@react-navigation/elements": "^2.9.14",
- "color": "^4.2.3",
- "sf-symbols-typescript": "^2.1.0"
- },
- "peerDependencies": {
- "@react-navigation/native": "^7.2.2",
- "react": ">= 18.2.0",
- "react-native": "*",
- "react-native-safe-area-context": ">= 4.0.0",
- "react-native-screens": ">= 4.0.0"
- }
- },
- "node_modules/@react-navigation/core": {
- "version": "7.17.2",
- "license": "MIT",
- "dependencies": {
- "@react-navigation/routers": "^7.5.3",
- "escape-string-regexp": "^4.0.0",
- "fast-deep-equal": "^3.1.3",
- "nanoid": "^3.3.11",
- "query-string": "^7.1.3",
- "react-is": "^19.1.0",
- "use-latest-callback": "^0.2.4",
- "use-sync-external-store": "^1.5.0"
- },
- "peerDependencies": {
- "react": ">= 18.2.0"
- }
- },
- "node_modules/@react-navigation/elements": {
- "version": "2.9.14",
- "license": "MIT",
- "dependencies": {
- "color": "^4.2.3",
- "use-latest-callback": "^0.2.4",
- "use-sync-external-store": "^1.5.0"
- },
- "peerDependencies": {
- "@react-native-masked-view/masked-view": ">= 0.2.0",
- "@react-navigation/native": "^7.2.2",
- "react": ">= 18.2.0",
- "react-native": "*",
- "react-native-safe-area-context": ">= 4.0.0"
- },
- "peerDependenciesMeta": {
- "@react-native-masked-view/masked-view": {
- "optional": true
- }
- }
- },
- "node_modules/@react-navigation/native": {
- "version": "7.2.2",
- "license": "MIT",
- "dependencies": {
- "@react-navigation/core": "^7.17.2",
- "escape-string-regexp": "^4.0.0",
- "fast-deep-equal": "^3.1.3",
- "nanoid": "^3.3.11",
- "use-latest-callback": "^0.2.4"
- },
- "peerDependencies": {
- "react": ">= 18.2.0",
- "react-native": "*"
- }
- },
- "node_modules/@react-navigation/native-stack": {
- "version": "7.14.10",
- "license": "MIT",
- "dependencies": {
- "@react-navigation/elements": "^2.9.14",
- "color": "^4.2.3",
- "sf-symbols-typescript": "^2.1.0",
- "warn-once": "^0.1.1"
- },
- "peerDependencies": {
- "@react-navigation/native": "^7.2.2",
- "react": ">= 18.2.0",
- "react-native": "*",
- "react-native-safe-area-context": ">= 4.0.0",
- "react-native-screens": ">= 4.0.0"
- }
- },
- "node_modules/@react-navigation/routers": {
- "version": "7.5.3",
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.11"
- }
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.27.10",
- "license": "MIT"
- },
- "node_modules/@sinonjs/commons": {
- "version": "3.0.1",
- "license": "BSD-3-Clause",
- "dependencies": {
- "type-detect": "4.0.8"
- }
- },
- "node_modules/@sinonjs/fake-timers": {
- "version": "10.3.0",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@sinonjs/commons": "^3.0.0"
- }
- },
- "node_modules/@tanstack/query-core": {
- "version": "5.95.2",
- "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.95.2.tgz",
- "integrity": "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/tannerlinsley"
- }
- },
- "node_modules/@tanstack/react-query": {
- "version": "5.95.2",
- "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.95.2.tgz",
- "integrity": "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA==",
- "license": "MIT",
- "dependencies": {
- "@tanstack/query-core": "5.95.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/tannerlinsley"
- },
- "peerDependencies": {
- "react": "^18 || ^19"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "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",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.28.0",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.28.2"
- }
- },
- "node_modules/@types/graceful-fs": {
- "version": "4.1.9",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/hammerjs": {
- "version": "2.0.46",
- "license": "MIT"
- },
- "node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.6",
- "license": "MIT"
- },
- "node_modules/@types/istanbul-lib-report": {
- "version": "3.0.3",
- "license": "MIT",
- "dependencies": {
- "@types/istanbul-lib-coverage": "*"
- }
- },
- "node_modules/@types/istanbul-reports": {
- "version": "3.0.4",
- "license": "MIT",
- "dependencies": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "node_modules/@types/node": {
- "version": "25.5.0",
- "license": "MIT",
- "dependencies": {
- "undici-types": "~7.18.0"
- }
- },
- "node_modules/@types/ramda": {
- "version": "0.27.66",
- "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.66.tgz",
- "integrity": "sha512-i2YW+E2U6NfMt3dp0RxNcejox+bxJUNDjB7BpYuRuoHIzv5juPHkJkNgcUOu+YSQEmaWu8cnAo/8r63C0NnuVA==",
- "license": "MIT",
- "dependencies": {
- "ts-toolbelt": "^6.15.1"
- }
- },
- "node_modules/@types/react": {
- "version": "19.2.14",
- "license": "MIT",
- "dependencies": {
- "csstype": "^3.2.2"
- }
- },
- "node_modules/@types/react-native": {
- "version": "0.72.8",
- "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.72.8.tgz",
- "integrity": "sha512-St6xA7+EoHN5mEYfdWnfYt0e8u6k2FR0P9s2arYgakQGFgU1f9FlPrIEcj0X24pLCF5c5i3WVuLCUdiCYHmOoA==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@react-native/virtualized-lists": "^0.72.4",
- "@types/react": "*"
- }
- },
- "node_modules/@types/react-native/node_modules/@react-native/virtualized-lists": {
- "version": "0.72.8",
- "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.72.8.tgz",
- "integrity": "sha512-J3Q4Bkuo99k7mu+jPS9gSUSgq+lLRSI/+ahXNwV92XgJ/8UgOTxu2LPwhJnBk/sQKxq7E8WkZBnBiozukQMqrw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "invariant": "^2.2.4",
- "nullthrows": "^1.1.1"
- },
- "peerDependencies": {
- "react-native": "*"
- }
- },
- "node_modules/@types/stack-utils": {
- "version": "2.0.3",
- "license": "MIT"
- },
- "node_modules/@types/urijs": {
- "version": "1.19.26",
- "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.26.tgz",
- "integrity": "sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg==",
- "license": "MIT"
- },
- "node_modules/@types/xml2js": {
- "version": "0.4.14",
- "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz",
- "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/yargs": {
- "version": "17.0.35",
- "license": "MIT",
- "dependencies": {
- "@types/yargs-parser": "*"
- }
- },
- "node_modules/@types/yargs-parser": {
- "version": "21.0.3",
- "license": "MIT"
- },
- "node_modules/@ungap/structured-clone": {
- "version": "1.3.0",
- "license": "ISC"
- },
- "node_modules/@xmldom/xmldom": {
- "version": "0.8.11",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/abort-controller": {
- "version": "3.0.0",
- "license": "MIT",
- "dependencies": {
- "event-target-shim": "^5.0.0"
- },
- "engines": {
- "node": ">=6.5"
- }
- },
- "node_modules/accepts": {
- "version": "1.3.8",
- "license": "MIT",
- "dependencies": {
- "mime-types": "~2.1.34",
- "negotiator": "0.6.3"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/acorn": {
- "version": "8.16.0",
- "license": "MIT",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/agent-base": {
- "version": "7.1.4",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/anser": {
- "version": "1.4.10",
- "license": "MIT"
- },
- "node_modules/ansi-escapes": {
- "version": "4.3.2",
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.21.3"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-escapes/node_modules/type-fest": {
- "version": "0.21.3",
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "5.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/anymatch/node_modules/picomatch": {
- "version": "2.3.2",
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/arg": {
- "version": "5.0.2",
- "license": "MIT"
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "license": "Python-2.0"
- },
- "node_modules/aria-hidden": {
- "version": "1.2.6",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/asap": {
- "version": "2.0.6",
- "license": "MIT"
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "license": "MIT"
- },
- "node_modules/await-lock": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz",
- "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==",
- "license": "MIT"
- },
- "node_modules/axios": {
- "version": "1.14.0",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.14.0.tgz",
- "integrity": "sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.11",
- "form-data": "^4.0.5",
- "proxy-from-env": "^2.1.0"
- }
- },
- "node_modules/babel-jest": {
- "version": "29.7.0",
- "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/babel-plugin-istanbul": {
- "version": "6.1.1",
- "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/babel-plugin-jest-hoist": {
- "version": "29.6.3",
- "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/babel-plugin-polyfill-corejs2": {
- "version": "0.4.17",
- "license": "MIT",
- "dependencies": {
- "@babel/compat-data": "^7.28.6",
- "@babel/helper-define-polyfill-provider": "^0.6.8",
- "semver": "^6.3.1"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.13.0",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.5",
- "core-js-compat": "^3.43.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.6.8",
- "license": "MIT",
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.6.8"
- },
- "peerDependencies": {
- "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
- }
- },
- "node_modules/babel-plugin-react-compiler": {
- "version": "1.0.0",
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.26.0"
- }
- },
- "node_modules/babel-plugin-react-native-web": {
- "version": "0.21.2",
- "license": "MIT"
- },
- "node_modules/babel-plugin-syntax-hermes-parser": {
- "version": "0.32.0",
- "license": "MIT",
- "dependencies": {
- "hermes-parser": "0.32.0"
- }
- },
- "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser": {
- "version": "0.32.0",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.32.0"
- }
- },
- "node_modules/babel-plugin-syntax-hermes-parser/node_modules/hermes-parser/node_modules/hermes-estree": {
- "version": "0.32.0",
- "license": "MIT"
- },
- "node_modules/babel-plugin-transform-flow-enums": {
- "version": "0.0.2",
- "license": "MIT",
- "dependencies": {
- "@babel/plugin-syntax-flow": "^7.12.1"
- }
- },
- "node_modules/babel-preset-current-node-syntax": {
- "version": "1.2.0",
- "license": "MIT",
- "dependencies": {
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-bigint": "^7.8.3",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-import-attributes": "^7.24.7",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0 || ^8.0.0-0"
- }
- },
- "node_modules/babel-preset-expo": {
- "version": "55.0.14-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@babel/generator": "^7.20.5",
- "@babel/helper-module-imports": "^7.25.9",
- "@babel/plugin-proposal-decorators": "^7.12.9",
- "@babel/plugin-proposal-export-default-from": "^7.24.7",
- "@babel/plugin-syntax-export-default-from": "^7.24.7",
- "@babel/plugin-transform-class-static-block": "^7.27.1",
- "@babel/plugin-transform-export-namespace-from": "^7.25.9",
- "@babel/plugin-transform-flow-strip-types": "^7.25.2",
- "@babel/plugin-transform-modules-commonjs": "^7.24.8",
- "@babel/plugin-transform-object-rest-spread": "^7.24.7",
- "@babel/plugin-transform-parameters": "^7.24.7",
- "@babel/plugin-transform-private-methods": "^7.24.7",
- "@babel/plugin-transform-private-property-in-object": "^7.24.7",
- "@babel/plugin-transform-runtime": "^7.24.7",
- "@babel/preset-react": "^7.22.15",
- "@babel/preset-typescript": "^7.23.0",
- "@react-native/babel-preset": "0.83.4",
- "babel-plugin-react-compiler": "^1.0.0",
- "babel-plugin-react-native-web": "~0.21.0",
- "babel-plugin-syntax-hermes-parser": "^0.32.0",
- "babel-plugin-transform-flow-enums": "^0.0.2",
- "debug": "^4.3.4",
- "resolve-from": "^5.0.0"
- },
- "peerDependencies": {
- "@babel/runtime": "^7.20.0",
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-widgets": "55.0.9-canary-20260328-2049187",
- "react-refresh": ">=0.14.0 <1.0.0"
- },
- "peerDependenciesMeta": {
- "@babel/runtime": {
- "optional": true
- },
- "expo": {
- "optional": true
- },
- "expo-widgets": {
- "optional": true
- }
- }
- },
- "node_modules/babel-preset-expo/node_modules/babel-plugin-syntax-hermes-parser": {
- "version": "0.32.1",
- "license": "MIT",
- "dependencies": {
- "hermes-parser": "0.32.1"
- }
- },
- "node_modules/babel-preset-jest": {
- "version": "29.6.3",
- "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/badgin": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/badgin/-/badgin-1.2.3.tgz",
- "integrity": "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw==",
- "license": "MIT"
- },
- "node_modules/balanced-match": {
- "version": "4.0.4",
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/baseline-browser-mapping": {
- "version": "2.10.12",
- "license": "Apache-2.0",
- "bin": {
- "baseline-browser-mapping": "dist/cli.cjs"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/better-opn": {
- "version": "3.0.2",
- "license": "MIT",
- "dependencies": {
- "open": "^8.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/better-opn/node_modules/open": {
- "version": "8.4.2",
- "license": "MIT",
- "dependencies": {
- "define-lazy-prop": "^2.0.0",
- "is-docker": "^2.1.1",
- "is-wsl": "^2.2.0"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/big-integer": {
- "version": "1.6.52",
- "license": "Unlicense",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/bplist-creator": {
- "version": "0.1.0",
- "license": "MIT",
- "dependencies": {
- "stream-buffers": "2.2.x"
- }
- },
- "node_modules/bplist-parser": {
- "version": "0.3.1",
- "license": "MIT",
- "dependencies": {
- "big-integer": "1.6.x"
- },
- "engines": {
- "node": ">= 5.10.0"
- }
- },
- "node_modules/brace-expansion": {
- "version": "5.0.5",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.28.1",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "baseline-browser-mapping": "^2.9.0",
- "caniuse-lite": "^1.0.30001759",
- "electron-to-chromium": "^1.5.263",
- "node-releases": "^2.0.27",
- "update-browserslist-db": "^1.2.0"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/bser": {
- "version": "2.1.1",
- "license": "Apache-2.0",
- "dependencies": {
- "node-int64": "^0.4.0"
- }
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "license": "MIT"
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/camelcase": {
- "version": "6.3.0",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "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.30001781",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "CC-BY-4.0"
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/chalk/node_modules/ansi-styles": {
- "version": "4.3.0",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/character-entities-html4": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.4.tgz",
- "integrity": "sha512-HRcDxZuZqMx3/a+qrzxdBKBPUpxWEq9xw2OPZ3a/174ihfrQKVsFhqtthBInFy1zZ9GgZyFXOatNujm8M+El3g==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/character-entities-legacy": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz",
- "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/chrome-launcher": {
- "version": "0.15.2",
- "license": "Apache-2.0",
- "dependencies": {
- "@types/node": "*",
- "escape-string-regexp": "^4.0.0",
- "is-wsl": "^2.2.0",
- "lighthouse-logger": "^1.0.0"
- },
- "bin": {
- "print-chrome-path": "bin/print-chrome-path.js"
- },
- "engines": {
- "node": ">=12.13.0"
- }
- },
- "node_modules/chromium-edge-launcher": {
- "version": "0.2.0",
- "license": "Apache-2.0",
- "dependencies": {
- "@types/node": "*",
- "escape-string-regexp": "^4.0.0",
- "is-wsl": "^2.2.0",
- "lighthouse-logger": "^1.0.0",
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- }
- },
- "node_modules/ci-info": {
- "version": "3.9.0",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cli-cursor": {
- "version": "2.1.0",
- "license": "MIT",
- "dependencies": {
- "restore-cursor": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/cli-spinners": {
- "version": "2.9.2",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/client-only": {
- "version": "0.0.1",
- "license": "MIT"
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/cliui/node_modules/strip-ansi": {
- "version": "6.0.1",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/clone": {
- "version": "1.0.4",
- "license": "MIT",
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/color": {
- "version": "4.2.3",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1",
- "color-string": "^1.9.0"
- },
- "engines": {
- "node": ">=12.5.0"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "license": "MIT"
- },
- "node_modules/color-string": {
- "version": "1.9.1",
- "license": "MIT",
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/commander": {
- "version": "12.1.0",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/compressible": {
- "version": "2.0.18",
- "license": "MIT",
- "dependencies": {
- "mime-db": ">= 1.43.0 < 2"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/compression": {
- "version": "1.8.1",
- "license": "MIT",
- "dependencies": {
- "bytes": "3.1.2",
- "compressible": "~2.0.18",
- "debug": "2.6.9",
- "negotiator": "~0.6.4",
- "on-headers": "~1.1.0",
- "safe-buffer": "5.2.1",
- "vary": "~1.1.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/compression/node_modules/debug": {
- "version": "2.6.9",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/compression/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/compression/node_modules/negotiator": {
- "version": "0.6.4",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "license": "MIT"
- },
- "node_modules/connect": {
- "version": "3.7.0",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "finalhandler": "1.1.2",
- "parseurl": "~1.3.3",
- "utils-merge": "1.0.1"
- },
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/connect/node_modules/debug": {
- "version": "2.6.9",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/connect/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/core-js-compat": {
- "version": "3.49.0",
- "license": "MIT",
- "dependencies": {
- "browserslist": "^4.28.1"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/core-js"
- }
- },
- "node_modules/cross-fetch": {
- "version": "3.2.0",
- "license": "MIT",
- "dependencies": {
- "node-fetch": "^2.7.0"
- }
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "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",
- "license": "MIT",
- "dependencies": {
- "hyphenate-style-name": "^1.0.3"
- }
- },
- "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/csstype": {
- "version": "3.2.3",
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decode-uri-component": {
- "version": "0.2.2",
- "license": "MIT",
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/defaults": {
- "version": "1.0.4",
- "license": "MIT",
- "dependencies": {
- "clone": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/define-lazy-prop": {
- "version": "2.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/destroy": {
- "version": "1.2.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8",
- "npm": "1.2.8000 || >= 1.4.16"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/detect-node-es": {
- "version": "1.1.0",
- "license": "MIT"
- },
- "node_modules/dnssd-advertise": {
- "version": "1.1.4",
- "license": "MIT"
- },
- "node_modules/dom-serializer": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
- "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
- "license": "MIT",
- "dependencies": {
- "domelementtype": "^2.0.1",
- "domhandler": "^4.2.0",
- "entities": "^2.0.0"
- },
- "funding": {
- "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
- }
- },
- "node_modules/domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "license": "BSD-2-Clause"
- },
- "node_modules/domhandler": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
- "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "domelementtype": "^2.2.0"
- },
- "engines": {
- "node": ">= 4"
- },
- "funding": {
- "url": "https://github.com/fb55/domhandler?sponsor=1"
- }
- },
- "node_modules/domutils": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
- "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "dom-serializer": "^1.0.1",
- "domelementtype": "^2.2.0",
- "domhandler": "^4.2.0"
- },
- "funding": {
- "url": "https://github.com/fb55/domutils?sponsor=1"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "license": "MIT"
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.328",
- "license": "ISC"
- },
- "node_modules/emoji-regex": {
- "version": "8.0.0",
- "license": "MIT"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/entities": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
- "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
- "license": "BSD-2-Clause",
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/error-stack-parser": {
- "version": "2.1.4",
- "license": "MIT",
- "dependencies": {
- "stackframe": "^1.3.4"
- }
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "license": "MIT"
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/esprima": {
- "version": "4.0.1",
- "license": "BSD-2-Clause",
- "bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/event-target-shim": {
- "version": "5.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/expo": {
- "version": "55.0.10-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.20.0",
- "@expo/cli": "55.0.20-canary-20260328-2049187",
- "@expo/config": "55.0.12-canary-20260328-2049187",
- "@expo/config-plugins": "55.0.8-canary-20260328-2049187",
- "@expo/devtools": "55.0.3-canary-20260328-2049187",
- "@expo/fingerprint": "0.16.7-canary-20260328-2049187",
- "@expo/local-build-cache-provider": "55.0.8-canary-20260328-2049187",
- "@expo/log-box": "55.0.9-canary-20260328-2049187",
- "@expo/metro": "~54.2.0",
- "@expo/metro-config": "55.0.12-canary-20260328-2049187",
- "@expo/vector-icons": "^15.0.2",
- "@ungap/structured-clone": "^1.3.0",
- "babel-preset-expo": "55.0.14-canary-20260328-2049187",
- "expo-asset": "55.0.11-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "expo-file-system": "55.0.13-canary-20260328-2049187",
- "expo-font": "55.0.5-canary-20260328-2049187",
- "expo-keep-awake": "55.0.5-canary-20260328-2049187",
- "expo-modules-autolinking": "55.0.13-canary-20260328-2049187",
- "expo-modules-core": "55.0.19-canary-20260328-2049187",
- "pretty-format": "^29.7.0",
- "react-refresh": "^0.14.2",
- "whatwg-url-minimum": "^0.1.1"
- },
- "bin": {
- "expo": "bin/cli",
- "expo-modules-autolinking": "bin/autolinking",
- "fingerprint": "bin/fingerprint"
- },
- "peerDependencies": {
- "@expo/dom-webview": "55.0.4-canary-20260328-2049187",
- "@expo/metro-runtime": "55.0.8-canary-20260328-2049187",
- "react": "*",
- "react-native": "*",
- "react-native-webview": "*"
- },
- "peerDependenciesMeta": {
- "@expo/dom-webview": {
- "optional": true
- },
- "@expo/metro-runtime": {
- "optional": true
- },
- "react-native-webview": {
- "optional": true
- }
- }
- },
- "node_modules/expo-application": {
- "version": "55.0.11-canary-20260328-2049187",
- "resolved": "https://registry.npmjs.org/expo-application/-/expo-application-55.0.11-canary-20260328-2049187.tgz",
- "integrity": "sha512-XrWghJefOb3fTdxK0B3RKuz9l31nZn2SIPqn2qhYx4kOPXa/CytaUvH5wG5gHJ2ZGtonk4JPmw+a69OiDj7MfQ==",
- "license": "MIT",
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187"
- }
- },
- "node_modules/expo-asset": {
- "version": "55.0.11-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/image-utils": "0.8.13-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-constants": {
- "version": "55.0.10-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/config": "55.0.12-canary-20260328-2049187",
- "@expo/env": "2.1.2-canary-20260328-2049187"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react-native": "*"
- }
- },
- "node_modules/expo-device": {
- "version": "55.0.11-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "ua-parser-js": "^0.7.33"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187"
- }
- },
- "node_modules/expo-file-system": {
- "version": "55.0.13-canary-20260328-2049187",
- "license": "MIT",
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react-native": "*"
- }
- },
- "node_modules/expo-font": {
- "version": "55.0.5-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "fontfaceobserver": "^2.1.0"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-glass-effect": {
- "version": "55.0.9-canary-20260328-2049187",
- "license": "MIT",
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-image": {
- "version": "55.0.7-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "sf-symbols-typescript": "^2.2.0"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*",
- "react-native-web": "*"
- },
- "peerDependenciesMeta": {
- "react-native-web": {
- "optional": true
- }
- }
- },
- "node_modules/expo-keep-awake": {
- "version": "55.0.5-canary-20260328-2049187",
- "license": "MIT",
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*"
- }
- },
- "node_modules/expo-linking": {
- "version": "55.0.10-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "invariant": "^2.2.4"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-localization": {
- "version": "55.0.10-canary-20260328-2049187",
- "resolved": "https://registry.npmjs.org/expo-localization/-/expo-localization-55.0.10-canary-20260328-2049187.tgz",
- "integrity": "sha512-4ZxHWAssJzQzkzcEGNzSxB/BpoN5IWE/FvMbJExByYqh2/x7EVJqamT8lNvFmfTdwrVCwGX6AhzMB6MGmf38Yg==",
- "license": "MIT",
- "dependencies": {
- "rtl-detect": "^1.0.2"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*"
- }
- },
- "node_modules/expo-modules-autolinking": {
- "version": "55.0.13-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/require-utils": "55.0.4-canary-20260328-2049187",
- "@expo/spawn-async": "^1.7.2",
- "chalk": "^4.1.0",
- "commander": "^7.2.0"
- },
- "bin": {
- "expo-modules-autolinking": "bin/expo-modules-autolinking.js"
- }
- },
- "node_modules/expo-modules-autolinking/node_modules/commander": {
- "version": "7.2.0",
- "license": "MIT",
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/expo-modules-core": {
- "version": "55.0.19-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "invariant": "^2.2.4"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-notifications": {
- "version": "55.0.15-canary-20260328-2049187",
- "resolved": "https://registry.npmjs.org/expo-notifications/-/expo-notifications-55.0.15-canary-20260328-2049187.tgz",
- "integrity": "sha512-Z6eQ5HPs2q71O+tt+dmINigAT+WxB2pCp/EAmvhtIPVYhopSuxJDmPGd+sMjeUe/npiwJqbr2agDLPcH8NxsHA==",
- "license": "MIT",
- "dependencies": {
- "@expo/image-utils": "0.8.13-canary-20260328-2049187",
- "abort-controller": "^3.0.0",
- "badgin": "^1.1.5",
- "expo-application": "55.0.11-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-router": {
- "version": "55.0.9-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/metro-runtime": "55.0.8-canary-20260328-2049187",
- "@expo/schema-utils": "55.0.3-canary-20260328-2049187",
- "@radix-ui/react-slot": "^1.2.0",
- "@radix-ui/react-tabs": "^1.1.12",
- "@react-navigation/bottom-tabs": "^7.15.5",
- "@react-navigation/native": "^7.1.33",
- "@react-navigation/native-stack": "^7.14.5",
- "client-only": "^0.0.1",
- "debug": "^4.3.4",
- "escape-string-regexp": "^4.0.0",
- "expo-glass-effect": "55.0.9-canary-20260328-2049187",
- "expo-image": "55.0.7-canary-20260328-2049187",
- "expo-server": "55.0.7-canary-20260328-2049187",
- "expo-symbols": "55.0.6-canary-20260328-2049187",
- "fast-deep-equal": "^3.1.3",
- "invariant": "^2.2.4",
- "nanoid": "^3.3.8",
- "query-string": "^7.1.3",
- "react-fast-compare": "^3.2.2",
- "react-native-is-edge-to-edge": "^1.2.1",
- "semver": "~7.6.3",
- "server-only": "^0.0.1",
- "sf-symbols-typescript": "^2.1.0",
- "shallowequal": "^1.1.0",
- "use-latest-callback": "^0.2.1",
- "vaul": "^1.1.2"
- },
- "peerDependencies": {
- "@expo/log-box": "55.0.9-canary-20260328-2049187",
- "@expo/metro-runtime": "55.0.8-canary-20260328-2049187",
- "@react-navigation/drawer": "^7.9.4",
- "@testing-library/react-native": ">= 13.2.0",
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "expo-linking": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-dom": "*",
- "react-native": "*",
- "react-native-gesture-handler": "*",
- "react-native-reanimated": "*",
- "react-native-safe-area-context": ">= 5.4.0",
- "react-native-screens": "*",
- "react-native-web": "*",
- "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4"
- },
- "peerDependenciesMeta": {
- "@react-navigation/drawer": {
- "optional": true
- },
- "@testing-library/react-native": {
- "optional": true
- },
- "react-dom": {
- "optional": true
- },
- "react-native-gesture-handler": {
- "optional": true
- },
- "react-native-reanimated": {
- "optional": true
- },
- "react-native-web": {
- "optional": true
- },
- "react-server-dom-webpack": {
- "optional": true
- }
- }
- },
- "node_modules/expo-server": {
- "version": "55.0.7-canary-20260328-2049187",
- "license": "MIT",
- "engines": {
- "node": ">=20.16.0"
- }
- },
- "node_modules/expo-splash-screen": {
- "version": "55.0.14-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo/prebuild-config": "55.0.12-canary-20260328-2049187"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187"
- }
- },
- "node_modules/expo-sqlite": {
- "version": "55.0.12-canary-20260328-2049187",
- "resolved": "https://registry.npmjs.org/expo-sqlite/-/expo-sqlite-55.0.12-canary-20260328-2049187.tgz",
- "integrity": "sha512-pzcd8T1A1a/SKDkFrUXQP/VQXdmsSRpE1XJwFps6Jt3+7DT1kQlFuQEp1xx7hqko/Qhjo7i1X0s67b1pt0lYWg==",
- "license": "MIT",
- "dependencies": {
- "await-lock": "^2.2.2"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-status-bar": {
- "version": "55.0.5-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "react-native-is-edge-to-edge": "^1.2.1"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-symbols": {
- "version": "55.0.6-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@expo-google-fonts/material-symbols": "^0.4.1",
- "sf-symbols-typescript": "^2.0.0"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-font": "55.0.5-canary-20260328-2049187",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/expo-system-ui": {
- "version": "55.0.12-canary-20260328-2049187",
- "license": "MIT",
- "dependencies": {
- "@react-native/normalize-colors": "0.83.4",
- "debug": "^4.3.2"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react-native": "*",
- "react-native-web": "*"
- },
- "peerDependenciesMeta": {
- "react-native-web": {
- "optional": true
- }
- }
- },
- "node_modules/expo-task-manager": {
- "version": "55.0.11-canary-20260328-2049187",
- "resolved": "https://registry.npmjs.org/expo-task-manager/-/expo-task-manager-55.0.11-canary-20260328-2049187.tgz",
- "integrity": "sha512-eneHR2t2WLWeRKfFuY2UDREh9OSryVDGWXy2V+IBlAKdOEQBQ1FlJESbLrYCEkhu6qiLUYMd61e0tgn3fbRhWQ==",
- "license": "MIT",
- "dependencies": {
- "unimodules-app-loader": "55.0.3-canary-20260328-2049187"
- },
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react-native": "*"
- }
- },
- "node_modules/expo-web-browser": {
- "version": "55.0.11-canary-20260328-2049187",
- "license": "MIT",
- "peerDependencies": {
- "expo": "55.0.10-canary-20260328-2049187",
- "react-native": "*"
- }
- },
- "node_modules/exponential-backoff": {
- "version": "3.1.3",
- "license": "Apache-2.0"
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "license": "MIT"
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "license": "MIT"
- },
- "node_modules/fb-dotslash": {
- "version": "0.5.8",
- "license": "(MIT OR Apache-2.0)",
- "bin": {
- "dotslash": "bin/dotslash"
- },
- "engines": {
- "node": ">=20"
- }
- },
- "node_modules/fb-watchman": {
- "version": "2.0.2",
- "license": "Apache-2.0",
- "dependencies": {
- "bser": "2.1.1"
- }
- },
- "node_modules/fbjs": {
- "version": "3.0.5",
- "license": "MIT",
- "dependencies": {
- "cross-fetch": "^3.1.5",
- "fbjs-css-vars": "^1.0.0",
- "loose-envify": "^1.0.0",
- "object-assign": "^4.1.0",
- "promise": "^7.1.1",
- "setimmediate": "^1.0.5",
- "ua-parser-js": "^1.0.35"
- }
- },
- "node_modules/fbjs-css-vars": {
- "version": "1.0.2",
- "license": "MIT"
- },
- "node_modules/fbjs/node_modules/promise": {
- "version": "7.3.1",
- "license": "MIT",
- "dependencies": {
- "asap": "~2.0.3"
- }
- },
- "node_modules/fbjs/node_modules/ua-parser-js": {
- "version": "1.0.41",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- }
- ],
- "license": "MIT",
- "bin": {
- "ua-parser-js": "script/cli.js"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/fetch-nodeshim": {
- "version": "0.4.10",
- "license": "MIT"
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/filter-obj": {
- "version": "1.1.0",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.1.2",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/debug": {
- "version": "2.6.9",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/finalhandler/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/finalhandler/node_modules/encodeurl": {
- "version": "1.0.2",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/on-finished": {
- "version": "2.3.0",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/statuses": {
- "version": "1.5.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/find-up": {
- "version": "4.1.0",
- "license": "MIT",
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/flow-enums-runtime": {
- "version": "0.0.6",
- "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",
- "license": "BSD-2-Clause"
- },
- "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/fresh": {
- "version": "0.5.2",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "license": "ISC"
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "license": "MIT",
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-nonce": {
- "version": "1.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/get-package-type": {
- "version": "0.1.0",
- "license": "MIT",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/getenv": {
- "version": "2.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "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/glob/node_modules/minimatch": {
- "version": "3.1.5",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/glob/node_modules/minimatch/node_modules/brace-expansion": {
- "version": "1.1.13",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match": {
- "version": "1.0.2",
- "license": "MIT"
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "license": "MIT",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/hermes-compiler": {
- "version": "0.14.1",
- "license": "MIT"
- },
- "node_modules/hermes-estree": {
- "version": "0.32.1",
- "license": "MIT"
- },
- "node_modules/hermes-parser": {
- "version": "0.32.1",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.32.1"
- }
- },
- "node_modules/hoist-non-react-statics": {
- "version": "3.3.2",
- "license": "BSD-3-Clause",
- "dependencies": {
- "react-is": "^16.7.0"
- }
- },
- "node_modules/hoist-non-react-statics/node_modules/react-is": {
- "version": "16.13.1",
- "license": "MIT"
- },
- "node_modules/hosted-git-info": {
- "version": "7.0.2",
- "license": "ISC",
- "dependencies": {
- "lru-cache": "^10.0.1"
- },
- "engines": {
- "node": "^16.14.0 || >=18.0.0"
- }
- },
- "node_modules/hosted-git-info/node_modules/lru-cache": {
- "version": "10.4.3",
- "license": "ISC"
- },
- "node_modules/htmlparser2": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz",
- "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==",
- "funding": [
- "https://github.com/fb55/htmlparser2?sponsor=1",
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "domelementtype": "^2.0.1",
- "domhandler": "^4.2.2",
- "domutils": "^2.8.0",
- "entities": "^3.0.1"
- }
- },
- "node_modules/htmlparser2/node_modules/entities": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
- "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/http-errors": {
- "version": "2.0.1",
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/hyphenate-style-name": {
- "version": "1.1.0",
- "license": "BSD-3-Clause"
- },
- "node_modules/idb": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.3.tgz",
- "integrity": "sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg==",
- "license": "ISC"
- },
- "node_modules/ignore": {
- "version": "5.3.2",
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/image-size": {
- "version": "1.2.1",
- "license": "MIT",
- "dependencies": {
- "queue": "6.0.2"
- },
- "bin": {
- "image-size": "bin/image-size.js"
- },
- "engines": {
- "node": ">=16.x"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "license": "ISC",
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "license": "ISC"
- },
- "node_modules/inline-style-prefixer": {
- "version": "7.0.1",
- "license": "MIT",
- "dependencies": {
- "css-in-js-utils": "^3.1.0"
- }
- },
- "node_modules/invariant": {
- "version": "2.2.4",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.0.0"
- }
- },
- "node_modules/is-arrayish": {
- "version": "0.3.4",
- "license": "MIT"
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-docker": {
- "version": "2.2.1",
- "license": "MIT",
- "bin": {
- "is-docker": "cli.js"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-wsl": {
- "version": "2.2.0",
- "license": "MIT",
- "dependencies": {
- "is-docker": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "license": "ISC"
- },
- "node_modules/istanbul-lib-coverage": {
- "version": "3.2.2",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-instrument": {
- "version": "5.2.1",
- "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/istanbul-lib-instrument/node_modules/semver": {
- "version": "6.3.1",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/jest-environment-node": {
- "version": "29.7.0",
- "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/jest-get-type": {
- "version": "29.6.3",
- "license": "MIT",
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-haste-map": {
- "version": "29.7.0",
- "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/jest-message-util": {
- "version": "29.7.0",
- "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/jest-mock": {
- "version": "29.7.0",
- "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/jest-regex-util": {
- "version": "29.6.3",
- "license": "MIT",
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-util": {
- "version": "29.7.0",
- "license": "MIT",
- "dependencies": {
- "@jest/types": "^29.6.3",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "ci-info": "^3.2.0",
- "graceful-fs": "^4.2.9",
- "picomatch": "^2.2.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-util/node_modules/picomatch": {
- "version": "2.3.2",
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/jest-validate": {
- "version": "29.7.0",
- "license": "MIT",
- "dependencies": {
- "@jest/types": "^29.6.3",
- "camelcase": "^6.2.0",
- "chalk": "^4.0.0",
- "jest-get-type": "^29.6.3",
- "leven": "^3.1.0",
- "pretty-format": "^29.7.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-worker": {
- "version": "29.7.0",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "jest-util": "^29.7.0",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-worker/node_modules/supports-color": {
- "version": "8.1.1",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
- "node_modules/jimp-compact": {
- "version": "0.16.1",
- "license": "MIT"
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "license": "MIT"
- },
- "node_modules/js-yaml": {
- "version": "4.1.1",
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/jsc-safe-url": {
- "version": "0.2.4",
- "license": "0BSD"
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "license": "MIT",
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/kleur": {
- "version": "3.0.3",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/lan-network": {
- "version": "0.2.0",
- "license": "MIT",
- "bin": {
- "lan-network": "dist/lan-network-cli.js"
- }
- },
- "node_modules/leven": {
- "version": "3.1.0",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/lighthouse-logger": {
- "version": "1.4.2",
- "license": "Apache-2.0",
- "dependencies": {
- "debug": "^2.6.9",
- "marky": "^1.2.2"
- }
- },
- "node_modules/lighthouse-logger/node_modules/debug": {
- "version": "2.6.9",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/lighthouse-logger/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/lightningcss": {
- "version": "1.32.0",
- "license": "MPL-2.0",
- "dependencies": {
- "detect-libc": "^2.0.3"
- },
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- },
- "optionalDependencies": {
- "lightningcss-android-arm64": "1.32.0",
- "lightningcss-darwin-arm64": "1.32.0",
- "lightningcss-darwin-x64": "1.32.0",
- "lightningcss-freebsd-x64": "1.32.0",
- "lightningcss-linux-arm-gnueabihf": "1.32.0",
- "lightningcss-linux-arm64-gnu": "1.32.0",
- "lightningcss-linux-arm64-musl": "1.32.0",
- "lightningcss-linux-x64-gnu": "1.32.0",
- "lightningcss-linux-x64-musl": "1.32.0",
- "lightningcss-win32-arm64-msvc": "1.32.0",
- "lightningcss-win32-x64-msvc": "1.32.0"
- }
- },
- "node_modules/lightningcss-linux-x64-gnu": {
- "version": "1.32.0",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/lightningcss-linux-x64-musl": {
- "version": "1.32.0",
- "cpu": [
- "x64"
- ],
- "license": "MPL-2.0",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 12.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/parcel"
- }
- },
- "node_modules/locate-path": {
- "version": "5.0.0",
- "license": "MIT",
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/lodash.debounce": {
- "version": "4.0.8",
- "license": "MIT"
- },
- "node_modules/lodash.throttle": {
- "version": "4.1.1",
- "license": "MIT"
- },
- "node_modules/log-symbols": {
- "version": "2.2.0",
- "license": "MIT",
- "dependencies": {
- "chalk": "^2.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "2.4.2",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/log-symbols/node_modules/chalk/node_modules/ansi-styles": {
- "version": "3.2.1",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/log-symbols/node_modules/chalk/node_modules/ansi-styles/node_modules/color-convert": {
- "version": "1.9.3",
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/log-symbols/node_modules/chalk/node_modules/ansi-styles/node_modules/color-convert/node_modules/color-name": {
- "version": "1.1.3",
- "license": "MIT"
- },
- "node_modules/log-symbols/node_modules/chalk/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/log-symbols/node_modules/chalk/node_modules/supports-color": {
- "version": "5.5.0",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/log-symbols/node_modules/chalk/node_modules/supports-color/node_modules/has-flag": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/loose-envify": {
- "version": "1.4.0",
- "license": "MIT",
- "dependencies": {
- "js-tokens": "^3.0.0 || ^4.0.0"
- },
- "bin": {
- "loose-envify": "cli.js"
- }
- },
- "node_modules/lru-cache": {
- "version": "5.1.1",
- "license": "ISC",
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/makeerror": {
- "version": "1.0.12",
- "license": "BSD-3-Clause",
- "dependencies": {
- "tmpl": "1.0.5"
- }
- },
- "node_modules/marky": {
- "version": "1.3.0",
- "license": "Apache-2.0"
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/memoize-one": {
- "version": "5.2.1",
- "license": "MIT"
- },
- "node_modules/merge-stream": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/metro": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/core": "^7.25.2",
- "@babel/generator": "^7.25.0",
- "@babel/parser": "^7.25.3",
- "@babel/template": "^7.25.0",
- "@babel/traverse": "^7.25.3",
- "@babel/types": "^7.25.2",
- "accepts": "^1.3.7",
- "chalk": "^4.0.0",
- "ci-info": "^2.0.0",
- "connect": "^3.6.5",
- "debug": "^4.4.0",
- "error-stack-parser": "^2.0.6",
- "flow-enums-runtime": "^0.0.6",
- "graceful-fs": "^4.2.4",
- "hermes-parser": "0.32.0",
- "image-size": "^1.0.2",
- "invariant": "^2.2.4",
- "jest-worker": "^29.7.0",
- "jsc-safe-url": "^0.2.2",
- "lodash.throttle": "^4.1.1",
- "metro-babel-transformer": "0.83.3",
- "metro-cache": "0.83.3",
- "metro-cache-key": "0.83.3",
- "metro-config": "0.83.3",
- "metro-core": "0.83.3",
- "metro-file-map": "0.83.3",
- "metro-resolver": "0.83.3",
- "metro-runtime": "0.83.3",
- "metro-source-map": "0.83.3",
- "metro-symbolicate": "0.83.3",
- "metro-transform-plugins": "0.83.3",
- "metro-transform-worker": "0.83.3",
- "mime-types": "^2.1.27",
- "nullthrows": "^1.1.1",
- "serialize-error": "^2.1.0",
- "source-map": "^0.5.6",
- "throat": "^5.0.0",
- "ws": "^7.5.10",
- "yargs": "^17.6.2"
- },
- "bin": {
- "metro": "src/cli.js"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-babel-transformer": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "flow-enums-runtime": "^0.0.6",
- "hermes-parser": "0.32.0",
- "nullthrows": "^1.1.1"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-babel-transformer/node_modules/hermes-parser": {
- "version": "0.32.0",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.32.0"
- }
- },
- "node_modules/metro-babel-transformer/node_modules/hermes-parser/node_modules/hermes-estree": {
- "version": "0.32.0",
- "license": "MIT"
- },
- "node_modules/metro-cache": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "exponential-backoff": "^3.1.1",
- "flow-enums-runtime": "^0.0.6",
- "https-proxy-agent": "^7.0.5",
- "metro-core": "0.83.3"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-cache-key": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "flow-enums-runtime": "^0.0.6"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-config": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "connect": "^3.6.5",
- "flow-enums-runtime": "^0.0.6",
- "jest-validate": "^29.7.0",
- "metro": "0.83.3",
- "metro-cache": "0.83.3",
- "metro-core": "0.83.3",
- "metro-runtime": "0.83.3",
- "yaml": "^2.6.1"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-core": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "flow-enums-runtime": "^0.0.6",
- "lodash.throttle": "^4.1.1",
- "metro-resolver": "0.83.3"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-file-map": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "fb-watchman": "^2.0.0",
- "flow-enums-runtime": "^0.0.6",
- "graceful-fs": "^4.2.4",
- "invariant": "^2.2.4",
- "jest-worker": "^29.7.0",
- "micromatch": "^4.0.4",
- "nullthrows": "^1.1.1",
- "walker": "^1.0.7"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-minify-terser": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "flow-enums-runtime": "^0.0.6",
- "terser": "^5.15.0"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-resolver": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "flow-enums-runtime": "^0.0.6"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-runtime": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.25.0",
- "flow-enums-runtime": "^0.0.6"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-source-map": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "@babel/traverse": "^7.25.3",
- "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3",
- "@babel/types": "^7.25.2",
- "flow-enums-runtime": "^0.0.6",
- "invariant": "^2.2.4",
- "metro-symbolicate": "0.83.3",
- "nullthrows": "^1.1.1",
- "ob1": "0.83.3",
- "source-map": "^0.5.6",
- "vlq": "^1.0.0"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-symbolicate": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "flow-enums-runtime": "^0.0.6",
- "invariant": "^2.2.4",
- "metro-source-map": "0.83.3",
- "nullthrows": "^1.1.1",
- "source-map": "^0.5.6",
- "vlq": "^1.0.0"
- },
- "bin": {
- "metro-symbolicate": "src/index.js"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-transform-plugins": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/generator": "^7.25.0",
- "@babel/template": "^7.25.0",
- "@babel/traverse": "^7.25.3",
- "flow-enums-runtime": "^0.0.6",
- "nullthrows": "^1.1.1"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro-transform-worker": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "@babel/core": "^7.25.2",
- "@babel/generator": "^7.25.0",
- "@babel/parser": "^7.25.3",
- "@babel/types": "^7.25.2",
- "flow-enums-runtime": "^0.0.6",
- "metro": "0.83.3",
- "metro-babel-transformer": "0.83.3",
- "metro-cache": "0.83.3",
- "metro-cache-key": "0.83.3",
- "metro-minify-terser": "0.83.3",
- "metro-source-map": "0.83.3",
- "metro-transform-plugins": "0.83.3",
- "nullthrows": "^1.1.1"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/metro/node_modules/ci-info": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/metro/node_modules/hermes-parser": {
- "version": "0.32.0",
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.32.0"
- }
- },
- "node_modules/metro/node_modules/hermes-parser/node_modules/hermes-estree": {
- "version": "0.32.0",
- "license": "MIT"
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/micromatch/node_modules/picomatch": {
- "version": "2.3.2",
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/mime": {
- "version": "1.6.0",
- "license": "MIT",
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/mime-db": {
- "version": "1.52.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "2.1.35",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mimic-fn": {
- "version": "1.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/minimatch": {
- "version": "10.2.4",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minipass": {
- "version": "7.1.3",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/mkdirp": {
- "version": "1.0.4",
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "license": "MIT"
- },
- "node_modules/multitars": {
- "version": "0.2.4",
- "license": "MIT"
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/negotiator": {
- "version": "0.6.3",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-fetch": {
- "version": "2.7.0",
- "license": "MIT",
- "dependencies": {
- "whatwg-url": "^5.0.0"
- },
- "engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
- }
- },
- "node_modules/node-forge": {
- "version": "1.4.0",
- "license": "(BSD-3-Clause OR GPL-2.0)",
- "engines": {
- "node": ">= 6.13.0"
- }
- },
- "node_modules/node-int64": {
- "version": "0.4.0",
- "license": "MIT"
- },
- "node_modules/node-releases": {
- "version": "2.0.36",
- "license": "MIT"
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-package-arg": {
- "version": "11.0.3",
- "license": "ISC",
- "dependencies": {
- "hosted-git-info": "^7.0.0",
- "proc-log": "^4.0.0",
- "semver": "^7.3.5",
- "validate-npm-package-name": "^5.0.0"
- },
- "engines": {
- "node": "^16.14.0 || >=18.0.0"
- }
- },
- "node_modules/npm-package-arg/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/nullthrows": {
- "version": "1.1.1",
- "license": "MIT"
- },
- "node_modules/ob1": {
- "version": "0.83.3",
- "license": "MIT",
- "dependencies": {
- "flow-enums-runtime": "^0.0.6"
- },
- "engines": {
- "node": ">=20.19.4"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/on-headers": {
- "version": "1.1.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "2.0.1",
- "license": "MIT",
- "dependencies": {
- "mimic-fn": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/open": {
- "version": "7.4.2",
- "license": "MIT",
- "dependencies": {
- "is-docker": "^2.0.0",
- "is-wsl": "^2.1.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ora": {
- "version": "3.4.0",
- "license": "MIT",
- "dependencies": {
- "chalk": "^2.4.2",
- "cli-cursor": "^2.1.0",
- "cli-spinners": "^2.0.0",
- "log-symbols": "^2.2.0",
- "strip-ansi": "^5.2.0",
- "wcwidth": "^1.0.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ora/node_modules/chalk": {
- "version": "2.4.2",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/chalk/node_modules/ansi-styles": {
- "version": "3.2.1",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/chalk/node_modules/ansi-styles/node_modules/color-convert": {
- "version": "1.9.3",
- "license": "MIT",
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/ora/node_modules/chalk/node_modules/ansi-styles/node_modules/color-convert/node_modules/color-name": {
- "version": "1.1.3",
- "license": "MIT"
- },
- "node_modules/ora/node_modules/chalk/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/ora/node_modules/chalk/node_modules/supports-color": {
- "version": "5.5.0",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/chalk/node_modules/supports-color/node_modules/has-flag": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/p-limit": {
- "version": "2.3.0",
- "license": "MIT",
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "license": "MIT",
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-try": {
- "version": "2.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/parse-png": {
- "version": "2.1.0",
- "license": "MIT",
- "dependencies": {
- "pngjs": "^3.3.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "license": "MIT"
- },
- "node_modules/path-scurry": {
- "version": "2.0.2",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^11.0.0",
- "minipass": "^7.1.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/path-scurry/node_modules/lru-cache": {
- "version": "11.2.7",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "4.0.4",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pirates": {
- "version": "4.0.7",
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/plist": {
- "version": "3.1.0",
- "license": "MIT",
- "dependencies": {
- "@xmldom/xmldom": "^0.8.8",
- "base64-js": "^1.5.1",
- "xmlbuilder": "^15.1.1"
- },
- "engines": {
- "node": ">=10.4.0"
- }
- },
- "node_modules/pngjs": {
- "version": "3.4.0",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/postcss": {
- "version": "8.4.49",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.7",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "license": "MIT"
- },
- "node_modules/pretty-format": {
- "version": "29.7.0",
- "license": "MIT",
- "dependencies": {
- "@jest/schemas": "^29.6.3",
- "ansi-styles": "^5.0.0",
- "react-is": "^18.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/react-is": {
- "version": "18.3.1",
- "license": "MIT"
- },
- "node_modules/proc-log": {
- "version": "4.2.0",
- "license": "ISC",
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/progress": {
- "version": "2.0.3",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/promise": {
- "version": "8.3.0",
- "license": "MIT",
- "dependencies": {
- "asap": "~2.0.6"
- }
- },
- "node_modules/prompts": {
- "version": "2.4.2",
- "license": "MIT",
- "dependencies": {
- "kleur": "^3.0.3",
- "sisteransi": "^1.0.5"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/prop-types": {
- "version": "15.8.1",
- "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
- "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "license": "MIT",
- "dependencies": {
- "loose-envify": "^1.4.0",
- "object-assign": "^4.1.1",
- "react-is": "^16.13.1"
- }
- },
- "node_modules/prop-types/node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "license": "MIT"
- },
- "node_modules/proxy-from-env": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
- "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/query-string": {
- "version": "7.1.3",
- "license": "MIT",
- "dependencies": {
- "decode-uri-component": "^0.2.2",
- "filter-obj": "^1.1.0",
- "split-on-first": "^1.0.0",
- "strict-uri-encode": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/queue": {
- "version": "6.0.2",
- "license": "MIT",
- "dependencies": {
- "inherits": "~2.0.3"
- }
- },
- "node_modules/ramda": {
- "version": "0.27.2",
- "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz",
- "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==",
- "license": "MIT"
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/react": {
- "version": "19.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-devtools-core": {
- "version": "6.1.5",
- "license": "MIT",
- "dependencies": {
- "shell-quote": "^1.6.1",
- "ws": "^7"
- }
- },
- "node_modules/react-dom": {
- "version": "19.2.0",
- "license": "MIT",
- "dependencies": {
- "scheduler": "^0.27.0"
- },
- "peerDependencies": {
- "react": "^19.2.0"
- }
- },
- "node_modules/react-fast-compare": {
- "version": "3.2.2",
- "license": "MIT"
- },
- "node_modules/react-freeze": {
- "version": "1.0.4",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "react": ">=17.0.0"
- }
- },
- "node_modules/react-is": {
- "version": "19.2.4",
- "license": "MIT"
- },
- "node_modules/react-native": {
- "version": "0.83.4",
- "license": "MIT",
- "dependencies": {
- "@jest/create-cache-key-function": "^29.7.0",
- "@react-native/assets-registry": "0.83.4",
- "@react-native/codegen": "0.83.4",
- "@react-native/community-cli-plugin": "0.83.4",
- "@react-native/gradle-plugin": "0.83.4",
- "@react-native/js-polyfills": "0.83.4",
- "@react-native/normalize-colors": "0.83.4",
- "@react-native/virtualized-lists": "0.83.4",
- "abort-controller": "^3.0.0",
- "anser": "^1.4.9",
- "ansi-regex": "^5.0.0",
- "babel-jest": "^29.7.0",
- "babel-plugin-syntax-hermes-parser": "0.32.0",
- "base64-js": "^1.5.1",
- "commander": "^12.0.0",
- "flow-enums-runtime": "^0.0.6",
- "glob": "^7.1.1",
- "hermes-compiler": "0.14.1",
- "invariant": "^2.2.4",
- "jest-environment-node": "^29.7.0",
- "memoize-one": "^5.0.0",
- "metro-runtime": "^0.83.3",
- "metro-source-map": "^0.83.3",
- "nullthrows": "^1.1.1",
- "pretty-format": "^29.7.0",
- "promise": "^8.3.0",
- "react-devtools-core": "^6.1.5",
- "react-refresh": "^0.14.0",
- "regenerator-runtime": "^0.13.2",
- "scheduler": "0.27.0",
- "semver": "^7.1.3",
- "stacktrace-parser": "^0.1.10",
- "whatwg-fetch": "^3.0.0",
- "ws": "^7.5.10",
- "yargs": "^17.6.2"
- },
- "bin": {
- "react-native": "cli.js"
- },
- "engines": {
- "node": ">= 20.19.4"
- },
- "peerDependencies": {
- "@types/react": "^19.1.1",
- "react": "^19.2.0"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- }
- }
- },
- "node_modules/react-native-gesture-handler": {
- "version": "2.30.1",
- "license": "MIT",
- "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-is-edge-to-edge": {
- "version": "1.3.1",
- "license": "MIT",
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-reanimated": {
- "version": "4.2.1",
- "license": "MIT",
- "dependencies": {
- "react-native-is-edge-to-edge": "1.2.1",
- "semver": "7.7.3"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*",
- "react-native-worklets": ">=0.7.0"
- }
- },
- "node_modules/react-native-reanimated/node_modules/react-native-is-edge-to-edge": {
- "version": "1.2.1",
- "license": "MIT",
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-reanimated/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/react-native-render-html": {
- "version": "6.3.4",
- "resolved": "https://registry.npmjs.org/react-native-render-html/-/react-native-render-html-6.3.4.tgz",
- "integrity": "sha512-H2jSMzZjidE+Wo3qCWPUMU1nm98Vs2SGCvQCz/i6xf0P3Y9uVtG/b0sDbG/cYFir2mSYBYCIlS1Dv0WC1LjYig==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "@jsamr/counter-style": "^2.0.1",
- "@jsamr/react-native-li": "^2.3.0",
- "@native-html/transient-render-engine": "11.2.3",
- "@types/ramda": "^0.27.40",
- "@types/urijs": "^1.19.15",
- "prop-types": "^15.5.7",
- "ramda": "^0.27.2",
- "stringify-entities": "^3.1.0",
- "urijs": "^1.19.6"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-safe-area-context": {
- "version": "5.6.2",
- "license": "MIT",
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-screens": {
- "version": "4.23.0",
- "license": "MIT",
- "dependencies": {
- "react-freeze": "^1.0.0",
- "warn-once": "^0.1.0"
- },
- "peerDependencies": {
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-web": {
- "version": "0.21.2",
- "license": "MIT",
- "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",
- "license": "MIT"
- },
- "node_modules/react-native-web/node_modules/memoize-one": {
- "version": "6.0.0",
- "license": "MIT"
- },
- "node_modules/react-native-worklets": {
- "version": "0.7.2",
- "license": "MIT",
- "dependencies": {
- "@babel/plugin-transform-arrow-functions": "7.27.1",
- "@babel/plugin-transform-class-properties": "7.27.1",
- "@babel/plugin-transform-classes": "7.28.4",
- "@babel/plugin-transform-nullish-coalescing-operator": "7.27.1",
- "@babel/plugin-transform-optional-chaining": "7.27.1",
- "@babel/plugin-transform-shorthand-properties": "7.27.1",
- "@babel/plugin-transform-template-literals": "7.27.1",
- "@babel/plugin-transform-unicode-regex": "7.27.1",
- "@babel/preset-typescript": "7.27.1",
- "convert-source-map": "2.0.0",
- "semver": "7.7.3"
- },
- "peerDependencies": {
- "@babel/core": "*",
- "react": "*",
- "react-native": "*"
- }
- },
- "node_modules/react-native-worklets/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/react-native/node_modules/semver": {
- "version": "7.7.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/react-refresh": {
- "version": "0.14.2",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/react-remove-scroll": {
- "version": "2.7.2",
- "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"
- },
- "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/react-remove-scroll-bar": {
- "version": "2.3.8",
- "license": "MIT",
- "dependencies": {
- "react-style-singleton": "^2.2.2",
- "tslib": "^2.0.0"
- },
- "engines": {
- "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/react-style-singleton": {
- "version": "2.2.3",
- "license": "MIT",
- "dependencies": {
- "get-nonce": "^1.0.0",
- "tslib": "^2.0.0"
- },
- "engines": {
- "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/regenerate": {
- "version": "1.4.2",
- "license": "MIT"
- },
- "node_modules/regenerate-unicode-properties": {
- "version": "10.2.2",
- "license": "MIT",
- "dependencies": {
- "regenerate": "^1.4.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/regenerator-runtime": {
- "version": "0.13.11",
- "license": "MIT"
- },
- "node_modules/regexpu-core": {
- "version": "6.4.0",
- "license": "MIT",
- "dependencies": {
- "regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^10.2.2",
- "regjsgen": "^0.8.0",
- "regjsparser": "^0.13.0",
- "unicode-match-property-ecmascript": "^2.0.0",
- "unicode-match-property-value-ecmascript": "^2.2.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/regjsgen": {
- "version": "0.8.0",
- "license": "MIT"
- },
- "node_modules/regjsparser": {
- "version": "0.13.0",
- "license": "BSD-2-Clause",
- "dependencies": {
- "jsesc": "~3.1.0"
- },
- "bin": {
- "regjsparser": "bin/parser"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.11",
- "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"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/resolve-from": {
- "version": "5.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/resolve-workspace-root": {
- "version": "2.0.1",
- "license": "MIT"
- },
- "node_modules/restore-cursor": {
- "version": "2.0.0",
- "license": "MIT",
- "dependencies": {
- "onetime": "^2.0.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "license": "ISC",
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/rtl-detect": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz",
- "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==",
- "license": "BSD-3-Clause"
- },
- "node_modules/safe-buffer": {
- "version": "5.2.1",
- "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/sax": {
- "version": "1.6.0",
- "license": "BlueOak-1.0.0",
- "engines": {
- "node": ">=11.0.0"
- }
- },
- "node_modules/scheduler": {
- "version": "0.27.0",
- "license": "MIT"
- },
- "node_modules/semver": {
- "version": "7.6.3",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/send": {
- "version": "0.19.2",
- "license": "MIT",
- "dependencies": {
- "debug": "2.6.9",
- "depd": "2.0.0",
- "destroy": "1.2.0",
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "fresh": "~0.5.2",
- "http-errors": "~2.0.1",
- "mime": "1.6.0",
- "ms": "2.1.3",
- "on-finished": "~2.4.1",
- "range-parser": "~1.2.1",
- "statuses": "~2.0.2"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/send/node_modules/debug": {
- "version": "2.6.9",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/send/node_modules/debug/node_modules/ms": {
- "version": "2.0.0",
- "license": "MIT"
- },
- "node_modules/serialize-error": {
- "version": "2.1.0",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/serve-static": {
- "version": "1.16.3",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "~2.0.0",
- "escape-html": "~1.0.3",
- "parseurl": "~1.3.3",
- "send": "~0.19.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/server-only": {
- "version": "0.0.1",
- "license": "MIT"
- },
- "node_modules/setimmediate": {
- "version": "1.0.5",
- "license": "MIT"
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "license": "ISC"
- },
- "node_modules/sf-symbols-typescript": {
- "version": "2.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/shallowequal": {
- "version": "1.1.0",
- "license": "MIT"
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shell-quote": {
- "version": "1.8.3",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "license": "ISC"
- },
- "node_modules/simple-plist": {
- "version": "1.3.1",
- "license": "MIT",
- "dependencies": {
- "bplist-creator": "0.1.0",
- "bplist-parser": "0.3.1",
- "plist": "^3.0.5"
- }
- },
- "node_modules/simple-swizzle": {
- "version": "0.2.4",
- "license": "MIT",
- "dependencies": {
- "is-arrayish": "^0.3.1"
- }
- },
- "node_modules/sisteransi": {
- "version": "1.0.5",
- "license": "MIT"
- },
- "node_modules/slash": {
- "version": "3.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/slugify": {
- "version": "1.6.8",
- "license": "MIT",
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/source-map": {
- "version": "0.5.7",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-support": {
- "version": "0.5.21",
- "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",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/split-on-first": {
- "version": "1.1.0",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.0.3",
- "license": "BSD-3-Clause"
- },
- "node_modules/stack-utils": {
- "version": "2.0.6",
- "license": "MIT",
- "dependencies": {
- "escape-string-regexp": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/stack-utils/node_modules/escape-string-regexp": {
- "version": "2.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/stackframe": {
- "version": "1.3.4",
- "license": "MIT"
- },
- "node_modules/stacktrace-parser": {
- "version": "0.1.11",
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.7.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/statuses": {
- "version": "2.0.2",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/stream-buffers": {
- "version": "2.2.0",
- "license": "Unlicense",
- "engines": {
- "node": ">= 0.10.0"
- }
- },
- "node_modules/strict-uri-encode": {
- "version": "2.0.0",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/string-width": {
- "version": "4.2.3",
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width/node_modules/strip-ansi": {
- "version": "6.0.1",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/stringify-entities": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-3.1.0.tgz",
- "integrity": "sha512-3FP+jGMmMV/ffZs86MoghGqAoqXAdxLrJP4GUdrDN1aIScYih5tuIO3eF4To5AJZ79KDZ8Fpdy7QJnK8SsL1Vg==",
- "license": "MIT",
- "dependencies": {
- "character-entities-html4": "^1.0.0",
- "character-entities-legacy": "^1.0.0",
- "xtend": "^4.0.0"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/strip-ansi": {
- "version": "5.2.0",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^4.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/strip-ansi/node_modules/ansi-regex": {
- "version": "4.1.1",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/structured-headers": {
- "version": "0.4.1",
- "license": "MIT"
- },
- "node_modules/styleq": {
- "version": "0.1.3",
- "license": "MIT"
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-hyperlinks": {
- "version": "2.3.0",
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0",
- "supports-color": "^7.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/terminal-link": {
- "version": "2.1.1",
- "license": "MIT",
- "dependencies": {
- "ansi-escapes": "^4.2.1",
- "supports-hyperlinks": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/terser": {
- "version": "5.46.1",
- "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": ">=10"
- }
- },
- "node_modules/terser/node_modules/commander": {
- "version": "2.20.3",
- "license": "MIT"
- },
- "node_modules/test-exclude": {
- "version": "6.0.0",
- "license": "ISC",
- "dependencies": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/test-exclude/node_modules/minimatch": {
- "version": "3.1.5",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/test-exclude/node_modules/minimatch/node_modules/brace-expansion": {
- "version": "1.1.13",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/test-exclude/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match": {
- "version": "1.0.2",
- "license": "MIT"
- },
- "node_modules/throat": {
- "version": "5.0.0",
- "license": "MIT"
- },
- "node_modules/tmpl": {
- "version": "1.0.5",
- "license": "BSD-3-Clause"
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/toqr": {
- "version": "0.1.1",
- "license": "MIT"
- },
- "node_modules/tr46": {
- "version": "0.0.3",
- "license": "MIT"
- },
- "node_modules/ts-toolbelt": {
- "version": "6.15.5",
- "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz",
- "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==",
- "license": "Apache-2.0"
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "license": "0BSD"
- },
- "node_modules/type-detect": {
- "version": "4.0.8",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/type-fest": {
- "version": "0.7.1",
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/typescript": {
- "version": "5.9.3",
- "devOptional": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/ua-parser-js": {
- "version": "0.7.41",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/ua-parser-js"
- },
- {
- "type": "paypal",
- "url": "https://paypal.me/faisalman"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/faisalman"
- }
- ],
- "license": "MIT",
- "bin": {
- "ua-parser-js": "script/cli.js"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/undici-types": {
- "version": "7.18.2",
- "license": "MIT"
- },
- "node_modules/unicode-canonical-property-names-ecmascript": {
- "version": "2.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-ecmascript": {
- "version": "2.0.0",
- "license": "MIT",
- "dependencies": {
- "unicode-canonical-property-names-ecmascript": "^2.0.0",
- "unicode-property-aliases-ecmascript": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-value-ecmascript": {
- "version": "2.2.1",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-property-aliases-ecmascript": {
- "version": "2.2.0",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unimodules-app-loader": {
- "version": "55.0.3-canary-20260328-2049187",
- "resolved": "https://registry.npmjs.org/unimodules-app-loader/-/unimodules-app-loader-55.0.3-canary-20260328-2049187.tgz",
- "integrity": "sha512-kqGCLCS35FFs4ue6BCIMuCVLO/KTco9WOHq/ghEVsR4NgGnhb9D3td2/D6KAFRY3c8qQ83x8mBAsHTwN7EUnNA==",
- "license": "MIT"
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.2.3",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/urijs": {
- "version": "1.19.11",
- "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz",
- "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==",
- "license": "MIT"
- },
- "node_modules/use-callback-ref": {
- "version": "1.3.3",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "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/use-latest-callback": {
- "version": "0.2.6",
- "license": "MIT",
- "peerDependencies": {
- "react": ">=16.8"
- }
- },
- "node_modules/use-sidecar": {
- "version": "1.1.3",
- "license": "MIT",
- "dependencies": {
- "detect-node-es": "^1.1.0",
- "tslib": "^2.0.0"
- },
- "engines": {
- "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/use-sync-external-store": {
- "version": "1.6.0",
- "license": "MIT",
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
- }
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/uuid": {
- "version": "7.0.3",
- "license": "MIT",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/validate-npm-package-name": {
- "version": "5.0.1",
- "license": "ISC",
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/vaul": {
- "version": "1.1.2",
- "license": "MIT",
- "dependencies": {
- "@radix-ui/react-dialog": "^1.1.1"
- },
- "peerDependencies": {
- "react": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc",
- "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc"
- }
- },
- "node_modules/vlq": {
- "version": "1.0.1",
- "license": "MIT"
- },
- "node_modules/walker": {
- "version": "1.0.8",
- "license": "Apache-2.0",
- "dependencies": {
- "makeerror": "1.0.12"
- }
- },
- "node_modules/warn-once": {
- "version": "0.1.1",
- "license": "MIT"
- },
- "node_modules/wcwidth": {
- "version": "1.0.1",
- "license": "MIT",
- "dependencies": {
- "defaults": "^1.0.3"
- }
- },
- "node_modules/webidl-conversions": {
- "version": "3.0.1",
- "license": "BSD-2-Clause"
- },
- "node_modules/whatwg-fetch": {
- "version": "3.6.20",
- "license": "MIT"
- },
- "node_modules/whatwg-url": {
- "version": "5.0.0",
- "license": "MIT",
- "dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
- "node_modules/whatwg-url-minimum": {
- "version": "0.1.1",
- "license": "MIT"
- },
- "node_modules/which": {
- "version": "2.0.2",
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/ansi-styles": {
- "version": "4.3.0",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "6.0.1",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrappy": {
- "version": "1.0.2",
- "license": "ISC"
- },
- "node_modules/write-file-atomic": {
- "version": "4.0.2",
- "license": "ISC",
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^3.0.7"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/ws": {
- "version": "7.5.10",
- "license": "MIT",
- "engines": {
- "node": ">=8.3.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/xcode": {
- "version": "3.0.1",
- "license": "Apache-2.0",
- "dependencies": {
- "simple-plist": "^1.1.0",
- "uuid": "^7.0.3"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/xml2js": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
- "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
- "license": "MIT",
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/xml2js/node_modules/xmlbuilder": {
- "version": "11.0.1",
- "license": "MIT",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/xmlbuilder": {
- "version": "15.1.1",
- "license": "MIT",
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "license": "ISC"
- },
- "node_modules/yaml": {
- "version": "2.8.3",
- "license": "ISC",
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/eemeli"
- }
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/zod": {
- "version": "3.25.76",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- },
- "node_modules/zustand": {
- "version": "5.0.12",
- "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.12.tgz",
- "integrity": "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==",
- "license": "MIT",
- "engines": {
- "node": ">=12.20.0"
- },
- "peerDependencies": {
- "@types/react": ">=18.0.0",
- "immer": ">=9.0.6",
- "react": ">=18.0.0",
- "use-sync-external-store": ">=1.2.0"
- },
- "peerDependenciesMeta": {
- "@types/react": {
- "optional": true
- },
- "immer": {
- "optional": true
- },
- "react": {
- "optional": true
- },
- "use-sync-external-store": {
- "optional": true
- }
- }
- }
- }
-}
diff --git a/package.json b/package.json
deleted file mode 100644
index 6dd72dc..0000000
--- a/package.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "name": "rssuper",
- "main": "expo-router/entry",
- "version": "1.0.0",
- "scripts": {
- "start": "expo start",
- "reset-project": "node ./scripts/reset-project.js",
- "android": "expo start --android",
- "ios": "expo start --ios",
- "web": "expo start --web",
- "lint": "expo lint"
- },
- "dependencies": {
- "@react-native-async-storage/async-storage": "^3.0.2",
- "@react-navigation/bottom-tabs": "^7.15.5",
- "@react-navigation/elements": "^2.9.10",
- "@react-navigation/native": "^7.1.33",
- "@tanstack/react-query": "^5.95.2",
- "axios": "^1.14.0",
- "buffer": "^6.0.3",
- "events": "^3.3.0",
- "expo": "55.0.10-canary-20260328-2049187",
- "expo-constants": "55.0.10-canary-20260328-2049187",
- "expo-device": "55.0.11-canary-20260328-2049187",
- "expo-font": "55.0.5-canary-20260328-2049187",
- "expo-glass-effect": "55.0.9-canary-20260328-2049187",
- "expo-image": "55.0.7-canary-20260328-2049187",
- "expo-linking": "55.0.10-canary-20260328-2049187",
- "expo-localization": "55.0.10-canary-20260328-2049187",
- "expo-notifications": "55.0.15-canary-20260328-2049187",
- "expo-router": "55.0.9-canary-20260328-2049187",
- "expo-splash-screen": "55.0.14-canary-20260328-2049187",
- "expo-sqlite": "55.0.12-canary-20260328-2049187",
- "expo-status-bar": "55.0.5-canary-20260328-2049187",
- "expo-symbols": "55.0.6-canary-20260328-2049187",
- "expo-system-ui": "55.0.12-canary-20260328-2049187",
- "expo-task-manager": "55.0.11-canary-20260328-2049187",
- "expo-web-browser": "55.0.11-canary-20260328-2049187",
- "fast-xml-parser": "^5.5.9",
- "react": "19.2.0",
- "react-dom": "19.2.0",
- "react-native": "0.83.4",
- "react-native-gesture-handler": "~2.30.0",
- "react-native-reanimated": "4.2.1",
- "react-native-render-html": "^6.3.4",
- "react-native-safe-area-context": "~5.6.2",
- "react-native-screens": "~4.23.0",
- "react-native-web": "~0.21.0",
- "react-native-worklets": "0.7.2",
- "stream-browserify": "^3.0.0",
- "zustand": "^5.0.12"
- },
- "devDependencies": {
- "@types/react": "~19.2.2",
- "@types/xml2js": "^0.4.14",
- "eslint": "^9.0.0",
- "eslint-config-expo": "55.0.1-canary-20260328-2049187",
- "typescript": "~5.9.2"
- },
- "private": true
-}
diff --git a/src/ISSUE_PLAN.md b/src/ISSUE_PLAN.md
deleted file mode 100644
index bb45feb..0000000
--- a/src/ISSUE_PLAN.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Plan
-
-## FRE-517: Build settings and preferences screen
-
-### Overview
-Create a settings screen with the following sections:
-- Sync intervals
-- Notifications
-- Theme (light/dark/system)
-- Reading preferences
-- Account management
-
-### Implementation Plan
-
-#### 1. Types and Interfaces
-- [ ] Add `SyncInterval` type to `src/types/feed.ts`
-- [ ] Add `NotificationPreference` type to `src/types/feed.ts`
-- [ ] Add `ReadingPreference` type to `src/types/feed.ts`
-- [ ] Add `AccountSettings` type to `src/types/global.d.ts`
-
-#### 2. Settings State Management
-- [ ] Create `settings-store` in `src/stores/settings-store.ts`
-- [ ] Initialize default settings
-- [ ] Add actions for updating all preference types
-
-#### 3. Settings Screen Component
-- [ ] Create `src/components/settings.tsx` with:
- - Sync interval selector
- - Notification toggle switches
- - Theme selector
- - Reading preference toggles
- - Account section placeholder
-
-#### 4. Settings Navigation
-- [ ] Add route `src/app/settings.tsx`
-- [ ] Update `app-tabs.tsx` to include settings tab
-- [ ] Add navigation to `AppLayout.tsx`
-
-#### 5. Integration
-- [ ] Connect settings to feed subscription intervals
-- [ ] Connect theme settings to `useTheme` hook
-- [ ] Connect notifications to expo-notifications
-
----
-
-## FRE-520: Add push notifications
-
-### Overview
-Implement push notifications for new articles, episode releases, and custom alerts using expo-notifications.
-
-### Implementation Plan
-
-#### 1. Notifications Types
-- [ ] Add `NotificationType` enum to `src/types/global.d.ts`
-- [ ] Add `NotificationConfig` interface to `src/types/global.d.ts`
-- [ ] Add `PushNotificationConfig` interface to `src/types/global.d.ts`
-
-#### 2. Notifications Service
-- [ ] Create `src/services/notification-service.ts`
-- [ ] Implement `requestPermission()`
-- [ ] Implement `scheduleNotification(type: NotificationType)`
-- [ ] Implement `onNotificationReceived()`
-- [ ] Implement `onNotificationOpened()`
-- [ ] Implement `clearAllNotifications()`
-
-#### 3. Notification Handlers
-- [ ] Create `src/hooks/use-notifications.ts`
-- [ ] Add notification state and actions
-- [ ] Add notification display component
-
-#### 4. Notification Settings
-- [ ] Add notification type preferences in settings
-- [ ] Add push notification toggle in settings
-- [ ] Add custom alert configuration
-
-#### 5. Integration
-- [ ] Connect notifications to feed updates
-- [ ] Schedule notifications on feed fetch
-- [ ] Handle notification deep linking
-
----
-
-## Dependencies and Tools
-- expo-notifications (already installed)
-- expo-task-manager (already installed)
-- expo-sqlite (already installed)
-- zustand (already installed)
-
-## Notes
-- Settings will persist via zustand persist middleware
-- Notifications will use Expo's token-based system
-- Feed subscriptions will respect sync interval settings
diff --git a/src/app/_layout.tsx b/src/app/_layout.tsx
deleted file mode 100644
index b04d0a8..0000000
--- a/src/app/_layout.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
-import React from 'react';
-import { useColorScheme } from 'react-native';
-
-import { AnimatedSplashOverlay } from '@/components/animated-icon';
-import AppTabs from '@/components/app-tabs';
-
-export default function TabLayout() {
- const colorScheme = useColorScheme();
- return (
-
-
-
-
- );
-}
diff --git a/src/app/add-feed.tsx b/src/app/add-feed.tsx
deleted file mode 100644
index eac91ef..0000000
--- a/src/app/add-feed.tsx
+++ /dev/null
@@ -1,186 +0,0 @@
-// Add Feed Screen
-
-import React, { useState } from 'react';
-import {
- View,
- TextInput,
- Button,
- Text,
- StyleSheet,
- Alert,
- ActivityIndicator,
-} from 'react-native';
-import { useRouter } from 'expo-router';
-import { useFeedStore } from '@/stores/feed-store';
-import { parseFeed } from '@/services/feed-service';
-import { generateId } from '@/utils/helpers';
-import { t } from '@/i18n';
-
-export default function AddFeedScreen() {
- const router = useRouter();
- const [url, setUrl] = useState('');
- const [title, setTitle] = useState('');
- const [loading, setLoading] = useState(false);
- const [preview, setPreview] = useState(null);
- const addSubscription = useFeedStore((state) => state.addSubscription);
-
- const handlePreview = async () => {
- if (!url) {
- Alert.alert('Error', 'Please enter a feed URL');
- return;
- }
-
- setLoading(true);
- setPreview(null);
-
- try {
- const response = await fetch(url);
- const text = await response.text();
- const result = await parseFeed(url, text);
-
- if (result.success && result.feed) {
- setPreview(result.feed);
- } else {
- Alert.alert('Error', result.error || 'Failed to parse feed');
- }
- } catch (error) {
- Alert.alert('Error', 'Failed to fetch feed');
- } finally {
- setLoading(false);
- }
- };
-
- const handleAdd = async () => {
- if (!url) {
- Alert.alert('Error', 'Please enter a feed URL');
- return;
- }
-
- if (!preview) {
- Alert.alert('Error', 'Please preview the feed first');
- return;
- }
-
- setLoading(true);
-
- try {
- const subscription = {
- id: generateId(),
- url,
- title: title || preview.title,
- enabled: true,
- fetchInterval: 60, // Default 1 hour
- createdAt: new Date(),
- updatedAt: new Date(),
- };
-
- await addSubscription(subscription);
- router.back();
- } catch (error) {
- Alert.alert('Error', 'Failed to add subscription');
- } finally {
- setLoading(false);
- }
- };
-
- return (
-
- {t('feed.add')}
-
-
- URL
-
-
-
-
- Title (optional)
-
-
-
-
-
- {preview && (
-
- {preview.title}
-
- {preview.description || 'No description'}
-
-
- {preview.items.length} items
-
-
- )}
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- padding: 20,
- paddingTop: 60,
- },
- title: {
- fontSize: 24,
- fontWeight: 'bold',
- marginBottom: 30,
- },
- inputContainer: {
- marginBottom: 20,
- },
- label: {
- fontSize: 14,
- marginBottom: 8,
- },
- input: {
- borderWidth: 1,
- borderColor: '#ccc',
- borderRadius: 8,
- padding: 12,
- fontSize: 16,
- },
- previewContainer: {
- marginTop: 20,
- padding: 16,
- borderWidth: 1,
- borderColor: '#ddd',
- borderRadius: 8,
- },
- previewTitle: {
- fontSize: 18,
- fontWeight: 'bold',
- marginBottom: 8,
- },
- previewDescription: {
- fontSize: 14,
- color: '#666',
- marginBottom: 8,
- },
- previewItems: {
- fontSize: 12,
- color: '#999',
- },
-});
diff --git a/src/app/article/[id].tsx b/src/app/article/[id].tsx
deleted file mode 100644
index 57b029c..0000000
--- a/src/app/article/[id].tsx
+++ /dev/null
@@ -1,340 +0,0 @@
-// Article Detail View
-
-import React, { useEffect, useState } from 'react';
-import {
- View,
- ScrollView,
- StyleSheet,
- Share,
- Linking,
- Image,
- Pressable,
-} from 'react-native';
-import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { SymbolView } from 'expo-symbols';
-import { useLocalSearchParams } from 'expo-router';
-import RenderHtml from 'react-native-render-html';
-
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { useTheme } from '@/hooks/use-theme';
-import { useBookmarkStore } from '@/stores/bookmark-store';
-import { FeedItem } from '@/types/feed';
-import { getFeedItems, getAllFeedItems } from '@/services/database';
-import { Colors, Spacing, MaxContentWidth, BottomTabInset } from '@/constants/theme';
-
-export default function ArticleDetailScreen() {
- const { id } = useLocalSearchParams<{ id: string }>();
- const insets = useSafeAreaInsets();
- const theme = useTheme();
- const { isBookmarked, toggleBookmark } = useBookmarkStore();
-
- const [article, setArticle] = useState(null);
- const [loading, setLoading] = useState(true);
-
- const bookmarked = id ? isBookmarked(id) : false;
-
- useEffect(() => {
- async function loadArticle() {
- if (!id) return;
-
- try {
- setLoading(true);
- const items = await getFeedItems(undefined, 500);
- const found = items.find(item => item.id === id);
- setArticle(found || null);
- } catch (error) {
- console.error('Failed to load article:', error);
- } finally {
- setLoading(false);
- }
- }
-
- loadArticle();
- }, [id]);
-
- const handleShare = async () => {
- if (!article?.link) return;
-
- try {
- await Share.share({
- message: `${article.title}\n\n${article.link}`,
- title: article.title,
- url: article.link,
- });
- } catch (error) {
- console.error('Share error:', error);
- }
- };
-
- const handleOpenInBrowser = () => {
- if (article?.link) {
- Linking.openURL(article.link);
- }
- };
-
- const formatDate = (date?: Date) => {
- if (!date) return '';
- return new Date(date).toLocaleDateString('en-US', {
- year: 'numeric',
- month: 'long',
- day: 'numeric',
- });
- };
-
- const extractImagesFromHtml = (html: string): string[] => {
- const imgRegex = /
]+src=["']([^"']+)["'][^>]*>/gi;
- const images: string[] = [];
- let match;
- while ((match = imgRegex.exec(html)) !== null) {
- if (match[1] && !images.includes(match[1])) {
- images.push(match[1]);
- }
- }
- return images;
- };
-
- const getGalleryImages = (): string[] => {
- const images: string[] = [];
- if (article?.content) {
- images.push(...extractImagesFromHtml(article.content));
- }
- if (article?.description) {
- images.push(...extractImagesFromHtml(article.description));
- }
- return [...new Set(images)];
- };
-
- const galleryImages = getGalleryImages();
-
- const renderContent = (content?: string) => {
- if (!content) return null;
-
- const isHtml = /<[a-z][\s\S]*>/i.test(content);
-
- if (isHtml) {
- return (
-
- );
- }
-
- return (
-
- {content}
-
- );
- };
-
- if (loading) {
- return (
-
-
- Loading...
-
-
- );
- }
-
- if (!article) {
- return (
-
-
- Article not found
-
-
- );
- }
-
- return (
-
-
-
-
- {article.title}
-
-
- {article.author && (
-
- By {article.author}
-
- )}
-
- {article.published && (
-
- {formatDate(article.published)}
-
- )}
-
-
-
- id && toggleBookmark(id)}>
-
-
-
-
-
-
-
-
-
-
-
-
- {galleryImages.length > 0 && (
-
-
- {galleryImages.map((imgUrl, index) => (
- Linking.openURL(imgUrl)}>
-
-
- ))}
-
-
- )}
-
- {article.description && (
-
-
- {article.description}
-
-
- )}
-
- {article.content && (
-
- {renderContent(article.content)}
-
- )}
-
- {article.link && (
-
-
- Read Full Article
-
-
- )}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- scrollView: {
- flex: 1,
- },
- contentContainer: {
- maxWidth: MaxContentWidth,
- marginHorizontal: 'auto',
- flexGrow: 1,
- },
- loadingContainer: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- },
- errorContainer: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- },
- header: {
- padding: Spacing.four,
- gap: Spacing.two,
- },
- title: {
- fontSize: 24,
- fontWeight: '700',
- lineHeight: 32,
- },
- author: {
- marginTop: Spacing.two,
- },
- actions: {
- flexDirection: 'row',
- paddingHorizontal: Spacing.four,
- paddingVertical: Spacing.two,
- gap: Spacing.two,
- },
- actionButton: {
- width: 44,
- height: 44,
- borderRadius: 22,
- justifyContent: 'center',
- alignItems: 'center',
- },
- gallery: {
- paddingVertical: Spacing.two,
- },
- galleryContent: {
- paddingHorizontal: Spacing.four,
- gap: Spacing.two,
- },
- galleryImage: {
- width: 200,
- height: 150,
- borderRadius: Spacing.two,
- },
- section: {
- padding: Spacing.four,
- paddingTop: 0,
- },
- description: {
- fontSize: 16,
- lineHeight: 24,
- color: '#333',
- },
- content: {
- fontSize: 16,
- lineHeight: 26,
- },
- readMoreButton: {
- margin: Spacing.four,
- padding: Spacing.three,
- borderRadius: Spacing.three,
- alignItems: 'center',
- },
- readMoreText: {
- fontSize: 16,
- fontWeight: '600',
- },
-});
\ No newline at end of file
diff --git a/src/app/explore.tsx b/src/app/explore.tsx
deleted file mode 100644
index e5f6380..0000000
--- a/src/app/explore.tsx
+++ /dev/null
@@ -1,415 +0,0 @@
-import React, { useState } from 'react';
-import {
- Platform,
- Pressable,
- ScrollView,
- StyleSheet,
- TextInput,
- View,
-} from 'react-native';
-import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { SymbolView } from 'expo-symbols';
-
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { BottomTabInset, MaxContentWidth, Spacing } from '@/constants/theme';
-import { useTheme } from '@/hooks/use-theme';
-import { t } from '@/i18n';
-
-type CategoryIcon = {
- ios: string;
- android: string;
- web: string;
-};
-
-const CATEGORY_ICONS: Record = {
- tech: { ios: 'laptopcomputer', android: 'laptop', web: 'laptop' },
- news: { ios: 'doc.text', android: 'article', web: 'article' },
- sports: { ios: 'figure.run', android: 'run', web: 'run' },
- business: { ios: 'briefcase', android: 'briefcase', web: 'briefcase' },
- entertainment: { ios: 'star', android: 'star', web: 'star' },
- health: { ios: 'heart.fill', android: 'heart', web: 'heart' },
- science: { ios: 'beaker', android: 'flask', web: 'flask' },
- food: { ios: 'bowl.with.spoon', android: 'restaurant', web: 'restaurant' },
-};
-
-const CATEGORIES = [
- { id: 'tech', name: 'Technology' },
- { id: 'news', name: 'News' },
- { id: 'sports', name: 'Sports' },
- { id: 'business', name: 'Business' },
- { id: 'entertainment', name: 'Entertainment' },
- { id: 'health', name: 'Health' },
- { id: 'science', name: 'Science' },
- { id: 'food', name: 'Food' },
-];
-
-const TRENDING_FEEDS = [
- {
- id: '1',
- title: 'TechCrunch',
- description: 'Latest technology news and startups',
- category: 'tech',
- subscribers: 125000,
- },
- {
- id: '2',
- title: 'The Verge',
- description: 'Technology, science, art, and culture',
- category: 'tech',
- subscribers: 98000,
- },
- {
- id: '3',
- title: 'Hacker News',
- description: 'News about hacking and startups',
- category: 'tech',
- subscribers: 87000,
- },
- {
- id: '4',
- title: 'BBC News',
- description: 'Breaking news and features',
- category: 'news',
- subscribers: 156000,
- },
- {
- id: '5',
- title: 'ESPN',
- description: 'Sports news and highlights',
- category: 'sports',
- subscribers: 112000,
- },
-];
-
-const RECOMMENDED_PODCASTS = [
- {
- id: '1',
- title: 'The Daily',
- description: 'News explained',
- publisher: 'The New York Times',
- },
- {
- id: '2',
- title: 'Reply All',
- description: 'About the internet',
- publisher: 'Gimlet Media',
- },
- {
- id: '3',
- title: '99% Invisible',
- description: 'Design and architecture',
- publisher: 'Roman Mars',
- },
-];
-
-export default function ExploreScreen() {
- const safeAreaInsets = useSafeAreaInsets();
- const insets = {
- ...safeAreaInsets,
- bottom: safeAreaInsets.bottom + BottomTabInset + Spacing.three,
- };
- const theme = useTheme();
- const [searchQuery, setSearchQuery] = useState('');
- const [selectedCategory, setSelectedCategory] = useState(null);
-
- const contentPlatformStyle = Platform.select({
- android: {
- paddingTop: insets.top,
- paddingLeft: insets.left,
- paddingRight: insets.right,
- paddingBottom: insets.bottom,
- },
- web: {
- paddingTop: Spacing.six,
- paddingBottom: Spacing.four,
- },
- });
-
- const filteredTrending = TRENDING_FEEDS.filter((feed) => {
- const matchesSearch =
- feed.title.toLowerCase().includes(searchQuery.toLowerCase()) ||
- feed.description.toLowerCase().includes(searchQuery.toLowerCase());
- const matchesCategory = selectedCategory ? feed.category === selectedCategory : true;
- return matchesSearch && matchesCategory;
- });
-
- return (
-
-
-
- {t('tab.explore')}
- {t('explore.discover')}
-
-
-
-
-
-
-
-
-
- setSelectedCategory(null)}>
-
- {t('explore.all')}
-
-
- {CATEGORIES.map((category) => (
-
- setSelectedCategory(
- selectedCategory === category.id ? null : category.id
- )
- }>
-
-
- {category.name}
-
-
- ))}
-
-
-
-
-
- {t('explore.trending')}
-
-
- {filteredTrending.map((feed) => (
-
-
-
- {feed.title}
-
-
- {feed.description}
-
-
-
- {(feed.subscribers / 1000).toFixed(1)}K subscribers
-
-
-
-
-
-
-
- ))}
- {filteredTrending.length === 0 && (
-
-
- {t('explore.noFeeds')}
-
-
- )}
-
-
-
-
-
- {t('explore.recommended')}
-
-
- {RECOMMENDED_PODCASTS.map((podcast) => (
-
-
-
-
-
- {podcast.title}
-
-
-
- {podcast.description} • {podcast.publisher}
-
-
-
-
-
-
- ))}
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- scrollView: {
- flex: 1,
- },
- contentContainer: {
- flexDirection: 'row',
- justifyContent: 'center',
- },
- container: {
- maxWidth: MaxContentWidth,
- flexGrow: 1,
- },
- header: {
- paddingHorizontal: Spacing.four,
- paddingVertical: Spacing.four,
- gap: Spacing.two,
- },
- searchContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingHorizontal: Spacing.four,
- paddingVertical: Spacing.two,
- marginHorizontal: Spacing.four,
- marginBottom: Spacing.two,
- borderRadius: Spacing.three,
- },
- searchIcon: {
- marginRight: Spacing.two,
- },
- searchInput: {
- flex: 1,
- fontSize: 16,
- paddingVertical: Spacing.one,
- },
- categoriesContainer: {
- marginBottom: Spacing.four,
- },
- categoriesContent: {
- paddingHorizontal: Spacing.four,
- gap: Spacing.two,
- },
- categoryChip: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- borderRadius: Spacing.six,
- backgroundColor: '#e5e5ea',
- minWidth: 80,
- },
- categoryChipText: {
- fontSize: 14,
- fontWeight: '500',
- },
- categoryIcon: {
- marginRight: Spacing.one,
- },
- section: {
- marginBottom: Spacing.four,
- },
- sectionHeader: {
- paddingHorizontal: Spacing.four,
- paddingVertical: Spacing.two,
- },
- feedsList: {
- gap: Spacing.two,
- paddingHorizontal: Spacing.four,
- },
- feedCard: {
- flexDirection: 'row',
- alignItems: 'center',
- padding: Spacing.three,
- borderRadius: Spacing.three,
- },
- feedCardContent: {
- flex: 1,
- gap: Spacing.one,
- },
- feedDescription: {
- fontSize: 14,
- marginTop: Spacing.one,
- },
- feedMeta: {
- marginTop: Spacing.one,
- },
- addButton: {
- width: 32,
- height: 32,
- borderRadius: 16,
- justifyContent: 'center',
- alignItems: 'center',
- marginLeft: Spacing.two,
- },
- podcastHeader: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing.two,
- },
- podcastIcon: {
- flexShrink: 0,
- },
- emptyState: {
- paddingVertical: Spacing.six,
- alignItems: 'center',
- },
-});
diff --git a/src/app/index.tsx b/src/app/index.tsx
deleted file mode 100644
index e31ddd3..0000000
--- a/src/app/index.tsx
+++ /dev/null
@@ -1,176 +0,0 @@
-import React from 'react';
-import { FlatList, StyleSheet, View, Platform } from 'react-native';
-import { RefreshControl } from 'react-native';
-import { Animated, Easing } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import { useFeedList } from '@/hooks/use-feed-list';
-import { FeedItemCard } from '@/components/feed-item-card';
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { Colors, MaxContentWidth, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-const EXTRACT_HTML_TEXT = (html: string): string => html.replace(/<[^>]*>/g, '');
-const EXCERPT_LENGTH = 200;
-const ANIMATION_DELAY_MULTIPLIER = 50;
-const MAX_ANIMATION_DELAY = 500;
-
-export default function HomeScreen() {
- const { feedItems, loading, hasMore, loadMore, refreshFeed, isRefreshing, error } = useFeedList();
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- const fadeInAnim = React.useRef(new Animated.Value(0)).current;
-
- React.useEffect(() => {
- const anim = Animated.timing(fadeInAnim, {
- toValue: 1,
- duration: 300,
- easing: Easing.ease,
- useNativeDriver: true,
- });
- anim.start();
- return () => anim.stop();
- }, []);
-
- const renderFeedItem = React.useCallback(({ item, index }: { item: any; index: number }) => {
- const itemFadeIn = React.useMemo(() => new Animated.Value(0), []);
-
- React.useEffect(() => {
- const anim = Animated.timing(itemFadeIn, {
- toValue: 1,
- duration: 200,
- delay: Math.min(index * ANIMATION_DELAY_MULTIPLIER, MAX_ANIMATION_DELAY),
- easing: Easing.ease,
- useNativeDriver: true,
- });
- const timeout = setTimeout(() => anim.start(), 100);
- return () => {
- clearTimeout(timeout);
- anim.stop();
- };
- }, [itemFadeIn, index]);
-
- return (
-
-
-
- );
- }, []);
-
- const renderHeader = () => (
-
- Today
-
- );
-
- const renderFooter = () => {
- if (!loading) return null;
- return (
-
- Loading more...
-
- );
- };
-
- const renderEmpty = () => (
-
- {error ? (
- <>
- Error Loading Feed
-
- {error}
-
-
- Pull down to retry
-
- >
- ) : (
- <>
- No articles yet
-
- Add a feed to start reading
-
- >
- )}
-
- );
-
- return (
-
-
- {renderHeader()}
-
-
- {feedItems.length === 0 ? (
- renderEmpty()
- ) : (
- item.id}
- renderItem={renderFeedItem}
- onEndReached={loadMore}
- onEndReachedThreshold={0.5}
- ListFooterComponent={renderFooter}
- refreshControl={
-
- }
- contentContainerStyle={styles.listContent}
- showsVerticalScrollIndicator={false}
- />
- )}
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: Colors.light.background,
- },
- safeArea: {
- flex: 1,
- },
- header: {
- paddingHorizontal: Spacing.four,
- paddingVertical: Spacing.three,
- maxWidth: MaxContentWidth,
- },
- headerTitle: {
- fontSize: 32,
- fontWeight: '700',
- },
- listContent: {
- paddingHorizontal: Spacing.four,
- paddingBottom: Spacing.six,
- },
- itemContainer: {
- maxWidth: MaxContentWidth,
- },
- footer: {
- paddingVertical: Spacing.four,
- alignItems: 'center',
- },
- emptyContainer: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- paddingHorizontal: Spacing.four,
- gap: Spacing.two,
- },
- emptySubtitle: {
- textAlign: 'center',
- color: '#8e8e93',
- },
- retryHint: {
- marginTop: Spacing.three,
- color: '#007AFF',
- fontSize: 12,
- },
-});
diff --git a/src/app/search.tsx b/src/app/search.tsx
deleted file mode 100644
index 8a9ac40..0000000
--- a/src/app/search.tsx
+++ /dev/null
@@ -1,200 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { StyleSheet, ScrollView, KeyboardAvoidingView, Platform, TouchableOpacity } from 'react-native';
-import { SearchInput } from '@/components/search-input';
-import { SearchSort } from '@/components/search-sort';
-import { SearchResults } from '@/components/search-results';
-import { SearchFilters } from '@/components/search-filters';
-import { FilterOptions } from '@/components/filter-options';
-import { combinedSearch } from '@/services/search-service';
-import { useSearchStore } from '@/stores/search-store';
-import { getAllSubscriptions } from '@/services/database';
-import { SearchResult, SearchSortOption, SearchFilters as SearchFiltersType } from '@/types/feed';
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-export default function SearchScreen() {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- const { query, setSort, setPage, setLoading, setError, sort, page, pageSize, loadHistory, loading, filters, setFilters } = useSearchStore();
-
- const [articles, setArticles] = useState([]);
- const [feeds, setFeeds] = useState([]);
- const [hasMore, setHasMore] = useState(false);
- const [isInitialLoad, setIsInitialLoad] = useState(true);
- const [filterModalVisible, setFilterModalVisible] = useState(false);
- const [availableFeeds, setAvailableFeeds] = useState>([]);
-
- // Load search history and available feeds on mount
- useEffect(() => {
- loadHistory();
-
- const loadAvailableFeeds = async () => {
- try {
- const subscriptions = await getAllSubscriptions();
- setAvailableFeeds(subscriptions.map(s => ({ id: s.id, title: s.title })));
- } catch (error) {
- console.error('Failed to load available feeds:', error);
- }
- };
-
- loadAvailableFeeds();
- }, []);
-
- // Perform search when query, sort, filters, or page changes
- useEffect(() => {
- const performSearch = async () => {
- if (!query || query.trim().length === 0) {
- setArticles([]);
- setFeeds([]);
- setHasMore(false);
- return;
- }
-
- if (isInitialLoad) {
- setLoading(true);
- }
-
- try {
- const results = await combinedSearch(query, {
- filters,
- sort,
- page,
- pageSize,
- });
-
- if (page === 1) {
- setArticles(results.articles);
- setFeeds(results.feeds);
- } else {
- setArticles(prev => [...prev, ...results.articles]);
- }
-
- setHasMore(results.articles.length >= pageSize);
- setError(null);
- } catch (error) {
- setError(error instanceof Error ? error.message : 'Search failed');
- console.error('Search error:', error);
- } finally {
- setLoading(false);
- setIsInitialLoad(false);
- }
- };
-
- const timer = setTimeout(performSearch, 300);
- return () => clearTimeout(timer);
- }, [query, sort, filters, page, pageSize]);
-
- const handleSortChange = (newSort: SearchSortOption) => {
- setSort(newSort);
- setPage(1);
- };
-
- const handleFilterChange = (newFilters: Partial) => {
- setFilters(newFilters);
- setPage(1);
- };
-
- const handleClearAllFilters = () => {
- setFilters({});
- setPage(1);
- };
-
- const handleApplyFilters = (newFilters: SearchFiltersType) => {
- setFilters(newFilters);
- setPage(1);
- };
-
- const handleLoadMore = () => {
- if (!loading && hasMore) {
- setPage(page + 1);
- }
- };
-
- const handleResultPress = (result: SearchResult) => {
- console.log('Result pressed:', result);
- };
-
- return (
-
-
-
-
-
- setFilterModalVisible(true)}
- >
- 🔍 Filters
-
-
-
-
-
-
-
-
-
- setFilterModalVisible(false)}
- currentFilters={filters}
- onApplyFilters={handleApplyFilters}
- availableFeeds={availableFeeds}
- />
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- scrollView: {
- zIndex: 10,
- },
- filtersRow: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- },
- filterButton: {
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- borderRadius: Spacing.two,
- backgroundColor: '#e5e5ea',
- marginLeft: Spacing.two,
- },
- filterButtonText: {
- fontSize: 14,
- color: '#8e8e93',
- },
- resultsContainer: {
- flex: 1,
- },
-});
diff --git a/src/app/settings.tsx b/src/app/settings.tsx
deleted file mode 100644
index 5099dbb..0000000
--- a/src/app/settings.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react';
-import SettingsScreen from '@/components/settings';
-
-export default function SettingsPage() {
- return ;
-}
diff --git a/src/components/animated-icon.module.css b/src/components/animated-icon.module.css
deleted file mode 100644
index f8156fe..0000000
--- a/src/components/animated-icon.module.css
+++ /dev/null
@@ -1,6 +0,0 @@
-.expoLogoBackground {
- background-image: linear-gradient(180deg, #3c9ffe, #0274df);
- border-radius: 40px;
- width: 128px;
- height: 128px;
-}
diff --git a/src/components/animated-icon.tsx b/src/components/animated-icon.tsx
deleted file mode 100644
index 91a480f..0000000
--- a/src/components/animated-icon.tsx
+++ /dev/null
@@ -1,132 +0,0 @@
-import { Image } from 'expo-image';
-import { useState } from 'react';
-import { Dimensions, StyleSheet, View } from 'react-native';
-import Animated, { Easing, Keyframe } from 'react-native-reanimated';
-import { scheduleOnRN } from 'react-native-worklets';
-
-const INITIAL_SCALE_FACTOR = Dimensions.get('screen').height / 90;
-const DURATION = 600;
-
-export function AnimatedSplashOverlay() {
- const [visible, setVisible] = useState(true);
-
- if (!visible) return null;
-
- const splashKeyframe = new Keyframe({
- 0: {
- transform: [{ scale: INITIAL_SCALE_FACTOR }],
- opacity: 1,
- },
- 20: {
- opacity: 1,
- },
- 70: {
- opacity: 0,
- easing: Easing.elastic(0.7),
- },
- 100: {
- opacity: 0,
- transform: [{ scale: 1 }],
- easing: Easing.elastic(0.7),
- },
- });
-
- return (
- {
- 'worklet';
- if (finished) {
- scheduleOnRN(setVisible, false);
- }
- })}
- style={styles.backgroundSolidColor}
- />
- );
-}
-
-const keyframe = new Keyframe({
- 0: {
- transform: [{ scale: INITIAL_SCALE_FACTOR }],
- },
- 100: {
- transform: [{ scale: 1 }],
- easing: Easing.elastic(0.7),
- },
-});
-
-const logoKeyframe = new Keyframe({
- 0: {
- transform: [{ scale: 1.3 }],
- opacity: 0,
- },
- 40: {
- transform: [{ scale: 1.3 }],
- opacity: 0,
- easing: Easing.elastic(0.7),
- },
- 100: {
- opacity: 1,
- transform: [{ scale: 1 }],
- easing: Easing.elastic(0.7),
- },
-});
-
-const glowKeyframe = new Keyframe({
- 0: {
- transform: [{ rotateZ: '0deg' }],
- },
- 100: {
- transform: [{ rotateZ: '7200deg' }],
- },
-});
-
-export function AnimatedIcon() {
- return (
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- imageContainer: {
- justifyContent: 'center',
- alignItems: 'center',
- },
- glow: {
- width: 201,
- height: 201,
- position: 'absolute',
- },
- iconContainer: {
- justifyContent: 'center',
- alignItems: 'center',
- width: 128,
- height: 128,
- zIndex: 100,
- },
- image: {
- position: 'absolute',
- width: 76,
- height: 71,
- },
- background: {
- borderRadius: 40,
- experimental_backgroundImage: `linear-gradient(180deg, #3C9FFE, #0274DF)`,
- width: 128,
- height: 128,
- position: 'absolute',
- },
- backgroundSolidColor: {
- ...StyleSheet.absoluteFillObject,
- backgroundColor: '#208AEF',
- zIndex: 1000,
- },
-});
diff --git a/src/components/animated-icon.web.tsx b/src/components/animated-icon.web.tsx
deleted file mode 100644
index dfbb1fd..0000000
--- a/src/components/animated-icon.web.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-import { Image } from 'expo-image';
-import { StyleSheet, View } from 'react-native';
-import Animated, { Keyframe, Easing } from 'react-native-reanimated';
-
-import classes from './animated-icon.module.css';
-const DURATION = 300;
-
-export function AnimatedSplashOverlay() {
- return null;
-}
-
-const keyframe = new Keyframe({
- 0: {
- transform: [{ scale: 0 }],
- },
- 60: {
- transform: [{ scale: 1.2 }],
- easing: Easing.elastic(1.2),
- },
- 100: {
- transform: [{ scale: 1 }],
- easing: Easing.elastic(1.2),
- },
-});
-
-const logoKeyframe = new Keyframe({
- 0: {
- opacity: 0,
- },
- 60: {
- transform: [{ scale: 1.2 }],
- opacity: 0,
- easing: Easing.elastic(1.2),
- },
- 100: {
- transform: [{ scale: 1 }],
- opacity: 1,
- easing: Easing.elastic(1.2),
- },
-});
-
-const glowKeyframe = new Keyframe({
- 0: {
- transform: [{ rotateZ: '-180deg' }, { scale: 0.8 }],
- opacity: 0,
- },
- [DURATION / 1000]: {
- transform: [{ rotateZ: '0deg' }, { scale: 1 }],
- opacity: 1,
- easing: Easing.elastic(0.7),
- },
- 100: {
- transform: [{ rotateZ: '7200deg' }],
- },
-});
-
-export function AnimatedIcon() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- alignItems: 'center',
- width: '100%',
- zIndex: 1000,
- position: 'absolute',
- top: 128 / 2 + 138,
- },
- imageContainer: {
- justifyContent: 'center',
- alignItems: 'center',
- },
- glow: {
- width: 201,
- height: 201,
- position: 'absolute',
- },
- iconContainer: {
- justifyContent: 'center',
- alignItems: 'center',
- width: 128,
- height: 128,
- },
- image: {
- position: 'absolute',
- width: 76,
- height: 71,
- },
- background: {
- width: 128,
- height: 128,
- position: 'absolute',
- },
-});
diff --git a/src/components/app-tabs.tsx b/src/components/app-tabs.tsx
deleted file mode 100644
index af637b6..0000000
--- a/src/components/app-tabs.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { NativeTabs } from 'expo-router/unstable-native-tabs';
-import React from 'react';
-import { useColorScheme } from 'react-native';
-
-import { Colors } from '@/constants/theme';
-import { t } from '@/i18n';
-
-export default function AppTabs() {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- return (
-
-
- {t('tab.home')}
-
-
-
-
- {t('tab.explore')}
-
-
-
-
- Search
-
-
-
-
- {t('tab.settings')}
-
-
-
- );
-}
diff --git a/src/components/app-tabs.web.tsx b/src/components/app-tabs.web.tsx
deleted file mode 100644
index 6542e46..0000000
--- a/src/components/app-tabs.web.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import {
- Tabs,
- TabList,
- TabTrigger,
- TabSlot,
- TabTriggerSlotProps,
- TabListProps,
-} from 'expo-router/ui';
-import { SymbolView } from 'expo-symbols';
-import React from 'react';
-import { Pressable, useColorScheme, View, StyleSheet } from 'react-native';
-
-import { ExternalLink } from './external-link';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-
-import { Colors, MaxContentWidth, Spacing } from '@/constants/theme';
-
-export default function AppTabs() {
- return (
-
-
-
-
-
- Home
-
-
- Explore
-
-
-
-
- );
-}
-
-export function TabButton({ children, isFocused, ...props }: TabTriggerSlotProps) {
- return (
- pressed && styles.pressed}>
-
-
- {children}
-
-
-
- );
-}
-
-export function CustomTabList(props: TabListProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- return (
-
-
-
- Expo Starter
-
-
- {props.children}
-
-
-
- Docs
-
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- tabListContainer: {
- position: 'absolute',
- width: '100%',
- padding: Spacing.three,
- justifyContent: 'center',
- alignItems: 'center',
- flexDirection: 'row',
- },
- innerContainer: {
- paddingVertical: Spacing.two,
- paddingHorizontal: Spacing.five,
- borderRadius: Spacing.five,
- flexDirection: 'row',
- alignItems: 'center',
- flexGrow: 1,
- gap: Spacing.two,
- maxWidth: MaxContentWidth,
- },
- brandText: {
- marginRight: 'auto',
- },
- pressed: {
- opacity: 0.7,
- },
- tabButtonView: {
- paddingVertical: Spacing.one,
- paddingHorizontal: Spacing.three,
- borderRadius: Spacing.three,
- },
- externalPressable: {
- flexDirection: 'row',
- justifyContent: 'center',
- alignItems: 'center',
- gap: Spacing.one,
- marginLeft: Spacing.three,
- },
-});
diff --git a/src/components/article-card.tsx b/src/components/article-card.tsx
deleted file mode 100644
index f09447b..0000000
--- a/src/components/article-card.tsx
+++ /dev/null
@@ -1,134 +0,0 @@
-import React from 'react';
-import { StyleSheet, TouchableOpacity, Linking } from 'react-native';
-import { SearchResult } from '@/types/feed';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-interface ArticleCardProps {
- result: SearchResult;
- onPress?: (result: SearchResult) => void;
-}
-
-export function ArticleCard({ result, onPress }: ArticleCardProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- const handlePress = () => {
- if (onPress) {
- onPress(result);
- } else if (result.link) {
- Linking.openURL(result.link);
- }
- };
-
- const formatDate = (date?: Date) => {
- if (!date) return '';
- const now = new Date();
- const diff = now.getTime() - date.getTime();
- const days = Math.floor(diff / (1000 * 60 * 60 * 24));
-
- if (days === 0) {
- const hours = Math.floor(diff / (1000 * 60 * 60));
- return hours === 0 ? 'Just now' : `${hours}h ago`;
- } else if (days === 1) {
- return 'Yesterday';
- } else if (days < 7) {
- return `${days}d ago`;
- } else {
- return date.toLocaleDateString();
- }
- };
-
- return (
-
-
-
- {result.title}
-
-
- {result.snippet && (
-
- {result.snippet}
-
- )}
-
-
- {result.feedTitle && (
-
- {result.feedTitle}
-
- )}
- {result.published && (
-
- {formatDate(result.published)}
-
- )}
-
-
- {result.type === 'feed' && (
-
-
- Feed
-
-
- )}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- borderRadius: Spacing.three,
- padding: Spacing.three,
- marginBottom: Spacing.two,
- borderWidth: 1,
- borderColor: '#e5e5ea',
- },
- content: {
- flex: 1,
- },
- title: {
- fontSize: 16,
- marginBottom: Spacing.one,
- },
- snippet: {
- fontSize: 14,
- color: '#8e8e93',
- marginBottom: Spacing.two,
- lineHeight: 20,
- },
- metaRow: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing.two,
- },
- feedTitle: {
- color: '#007AFF',
- flex: 1,
- },
- date: {
- color: '#8e8e93',
- fontSize: 12,
- },
- feedBadge: {
- alignSelf: 'flex-start',
- paddingHorizontal: Spacing.two,
- paddingVertical: Spacing.one,
- backgroundColor: '#007AFF20',
- borderRadius: Spacing.one,
- marginTop: Spacing.two,
- },
- feedBadgeText: {
- color: '#007AFF',
- fontSize: 11,
- fontWeight: '600',
- textTransform: 'uppercase',
- },
-});
diff --git a/src/components/external-link.tsx b/src/components/external-link.tsx
deleted file mode 100644
index 883e515..0000000
--- a/src/components/external-link.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import { Href, Link } from 'expo-router';
-import { openBrowserAsync, WebBrowserPresentationStyle } from 'expo-web-browser';
-import { type ComponentProps } from 'react';
-
-type Props = Omit, 'href'> & { href: Href & string };
-
-export function ExternalLink({ href, ...rest }: Props) {
- return (
- {
- if (process.env.EXPO_OS !== 'web') {
- // Prevent the default behavior of linking to the default browser on native.
- event.preventDefault();
- // Open the link in an in-app browser.
- await openBrowserAsync(href, {
- presentationStyle: WebBrowserPresentationStyle.AUTOMATIC,
- });
- }
- }}
- />
- );
-}
diff --git a/src/components/feed-item-card.tsx b/src/components/feed-item-card.tsx
deleted file mode 100644
index d1d3a25..0000000
--- a/src/components/feed-item-card.tsx
+++ /dev/null
@@ -1,225 +0,0 @@
-import React from 'react';
-import { StyleSheet, TouchableOpacity, Linking } from 'react-native';
-import { useRouter } from 'expo-router';
-import { FeedItem } from '@/types/feed';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-const EXTRACT_HTML_TEXT = (html: string): string => html.replace(/<[^>]*>/g, '');
-const EXCERPT_LENGTH = 200;
-
-interface FeedItemCardProps {
- item: FeedItem;
- onPress?: (item: FeedItem) => void;
- onLongPress?: (item: FeedItem) => void;
-}
-
-export function FeedItemCard({ item, onPress, onLongPress }: FeedItemCardProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
- const router = useRouter();
-
- const handlePress = () => {
- if (onPress) {
- onPress(item);
- } else if (item.id) {
- router.push(`/article/${item.id}` as any);
- } else if (item.link) {
- Linking.openURL(item.link);
- }
- };
-
- const handleLongPress = () => {
- if (onLongPress) {
- onLongPress(item);
- }
- };
-
- const formatDate = (date?: Date) => {
- if (!date) return '';
- const now = new Date();
- const diff = now.getTime() - date.getTime();
- const days = Math.floor(diff / (1000 * 60 * 60 * 24));
-
- if (days === 0) {
- const hours = Math.floor(diff / (1000 * 60 * 60));
- return hours === 0 ? 'Just now' : `${hours}h ago`;
- } else if (days === 1) {
- return 'Yesterday';
- } else if (days < 7) {
- return `${days}d ago`;
- } else {
- return date.toLocaleDateString();
- }
- };
-
- const excerpt = React.useMemo(() => {
- if (item.content) {
- const htmlContent = EXTRACT_HTML_TEXT(item.content);
- return htmlContent.length > EXCERPT_LENGTH ? htmlContent.substring(0, EXCERPT_LENGTH) + '...' : htmlContent;
- }
- if (item.description) {
- const htmlDesc = EXTRACT_HTML_TEXT(item.description);
- return htmlDesc.length > EXCERPT_LENGTH ? htmlDesc.substring(0, EXCERPT_LENGTH) + '...' : htmlDesc;
- }
- return '';
- }, [item.content, item.description]);
-
- const cardContent = (
-
-
- {item.subscriptionTitle && (
-
- {item.subscriptionTitle}
-
- )}
-
-
- {item.title}
-
-
- {excerpt && (
-
- {excerpt}
-
- )}
-
-
- {item.author && (
-
- {item.author}
-
- )}
- {item.published && (
-
- {formatDate(item.published)}
-
- )}
-
-
- {item.enclosure && item.enclosure.type.includes('audio') && (
-
-
- 🎧 Audio
-
-
- )}
-
-
- );
-
- if (item.id) {
- return (
-
-
- {item.subscriptionTitle && (
-
- {item.subscriptionTitle}
-
- )}
-
-
- {item.title}
-
-
- {excerpt && (
-
- {excerpt}
-
- )}
-
-
- {item.author && (
-
- {item.author}
-
- )}
- {item.published && (
-
- {formatDate(item.published)}
-
- )}
-
-
- {item.enclosure && item.enclosure.type.includes('audio') && (
-
-
- 🎧 Audio
-
-
- )}
-
-
- );
-}
-
- return cardContent;
-}
-
-const styles = StyleSheet.create({
- container: {
- borderRadius: Spacing.three,
- padding: Spacing.three,
- marginBottom: Spacing.two,
- borderWidth: 1,
- borderColor: '#e5e5ea',
- },
- content: {
- flex: 1,
- },
- feedTitle: {
- fontSize: 12,
- color: '#007AFF',
- marginBottom: Spacing.half,
- fontWeight: '500',
- },
- title: {
- fontSize: 16,
- marginBottom: Spacing.one,
- },
- excerpt: {
- fontSize: 14,
- color: '#8e8e93',
- marginBottom: Spacing.two,
- lineHeight: 20,
- },
- metaRow: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing.two,
- },
- author: {
- color: '#8e8e93',
- fontSize: 12,
- flex: 1,
- },
- date: {
- color: '#8e8e93',
- fontSize: 12,
- },
- audioBadge: {
- alignSelf: 'flex-start',
- paddingHorizontal: Spacing.two,
- paddingVertical: Spacing.one,
- backgroundColor: '#007AFF20',
- borderRadius: Spacing.one,
- marginTop: Spacing.two,
- },
- audioBadgeText: {
- color: '#007AFF',
- fontSize: 11,
- fontWeight: '600',
- },
-});
diff --git a/src/components/filter-options.tsx b/src/components/filter-options.tsx
deleted file mode 100644
index 673c51e..0000000
--- a/src/components/filter-options.tsx
+++ /dev/null
@@ -1,337 +0,0 @@
-import React, { useState } from 'react';
-import { StyleSheet, ScrollView, TouchableOpacity, Modal, View } from 'react-native';
-import { SearchFilters } from '@/types/feed';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-interface FilterOptionsProps {
- visible: boolean;
- onClose: () => void;
- currentFilters: SearchFilters;
- onApplyFilters: (filters: SearchFilters) => void;
- availableFeeds: Array<{ id: string; title: string }>;
-}
-
-export function FilterOptions({ visible, onClose, currentFilters, onApplyFilters, availableFeeds }: FilterOptionsProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- const [localFilters, setLocalFilters] = useState(currentFilters);
- const [selectedContentType, setSelectedContentType] = useState<'all' | 'article' | 'audio' | 'video'>(
- localFilters.contentType || 'all'
- );
- const [selectedFeeds, setSelectedFeeds] = useState(localFilters.feedIds || []);
- const [dateFrom, setDateFrom] = useState(localFilters.dateFrom?.toISOString().split('T')[0] || '');
- const [dateTo, setDateTo] = useState(localFilters.dateTo?.toISOString().split('T')[0] || '');
-
- const handleApply = () => {
- const filters: SearchFilters = {};
-
- if (selectedContentType !== 'all') {
- filters.contentType = selectedContentType;
- }
-
- if (selectedFeeds.length > 0) {
- filters.feedIds = selectedFeeds;
- }
-
- if (dateFrom) {
- filters.dateFrom = new Date(dateFrom);
- }
-
- if (dateTo) {
- filters.dateTo = new Date(dateTo);
- }
-
- onApplyFilters(filters);
- onClose();
- };
-
- const handleReset = () => {
- setLocalFilters({});
- setSelectedContentType('all');
- setSelectedFeeds([]);
- setDateFrom('');
- setDateTo('');
- };
-
- const toggleFeed = (feedId: string) => {
- setSelectedFeeds(prev =>
- prev.includes(feedId)
- ? prev.filter(id => id !== feedId)
- : [...prev, feedId]
- );
- };
-
- const contentTypeOptions = [
- { value: 'all', label: 'All Types', icon: '📋' },
- { value: 'article', label: 'Articles', icon: '📄' },
- { value: 'audio', label: 'Audio', icon: '🎵' },
- { value: 'video', label: 'Video', icon: '🎬' },
- ];
-
- return (
-
-
- {/* Header */}
-
- Filters
-
- Done
-
-
-
- {/* Content */}
-
- {/* Content Type Filter */}
-
- Content Type
-
- {contentTypeOptions.map(option => (
- setSelectedContentType(option.value as any)}
- >
- {option.icon}
-
- {option.label}
-
-
- ))}
-
-
-
- {/* Date Range Filter */}
-
- Date Range
-
-
- From
-
- {dateFrom || 'Any date'}
-
-
- to
-
- To
-
- {dateTo || 'Now'}
-
-
-
- Tap to select dates (coming soon)
-
-
- {/* Feed Filter */}
-
- Feeds ({selectedFeeds.length} selected)
-
- {availableFeeds.map(feed => (
- toggleFeed(feed.id)}
- >
-
- {selectedFeeds.includes(feed.id) ? '☑' : '☐'}
-
-
- {feed.title}
-
-
- ))}
-
-
-
-
- {/* Footer Actions */}
-
-
- Reset
-
-
- Apply
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- header: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.three,
- borderBottomWidth: 1,
- borderBottomColor: '#e5e5ea',
- },
- headerTitle: {
- fontSize: 20,
- fontWeight: 'bold',
- },
- closeButton: {
- paddingHorizontal: Spacing.two,
- paddingVertical: Spacing.one,
- },
- closeButtonText: {
- fontSize: 16,
- color: '#007AFF',
- },
- content: {
- flex: 1,
- },
- section: {
- paddingVertical: Spacing.three,
- paddingHorizontal: Spacing.three,
- borderBottomWidth: 1,
- borderBottomColor: '#e5e5ea',
- },
- sectionTitle: {
- fontSize: 14,
- fontWeight: '600',
- marginBottom: Spacing.three,
- color: '#8e8e93',
- textTransform: 'uppercase',
- letterSpacing: 0.5,
- },
- optionRow: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- gap: Spacing.two,
- },
- optionButton: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- borderRadius: Spacing.two,
- backgroundColor: '#e5e5ea',
- gap: Spacing.one,
- },
- optionButtonSelected: {
- backgroundColor: '#007AFF',
- },
- optionIcon: {
- fontSize: 14,
- },
- optionLabel: {
- fontSize: 14,
- color: '#8e8e93',
- },
- optionLabelSelected: {
- color: '#ffffff',
- },
- dateRow: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing.two,
- },
- dateInputContainer: {
- flex: 1,
- },
- dateLabel: {
- fontSize: 12,
- color: '#8e8e93',
- marginBottom: Spacing.one,
- },
- dateValue: {
- fontSize: 16,
- paddingVertical: Spacing.two,
- paddingHorizontal: Spacing.two,
- borderRadius: Spacing.two,
- backgroundColor: '#e5e5ea',
- },
- dateSeparator: {
- fontSize: 16,
- color: '#8e8e93',
- },
- dateHint: {
- fontSize: 12,
- color: '#8e8e93',
- marginTop: Spacing.two,
- fontStyle: 'italic',
- },
- feedsList: {
- maxHeight: 200,
- },
- feedOption: {
- flexDirection: 'row',
- alignItems: 'center',
- paddingVertical: Spacing.two,
- paddingHorizontal: Spacing.two,
- gap: Spacing.two,
- },
- feedOptionSelected: {
- backgroundColor: '#e5f2ff',
- borderRadius: Spacing.two,
- marginLeft: -Spacing.two,
- marginRight: -Spacing.two,
- },
- feedCheckbox: {
- fontSize: 16,
- },
- feedTitle: {
- flex: 1,
- fontSize: 14,
- },
- footer: {
- flexDirection: 'row',
- padding: Spacing.three,
- gap: Spacing.three,
- borderTopWidth: 1,
- borderTopColor: '#e5e5ea',
- },
- footerButton: {
- flex: 1,
- paddingVertical: Spacing.three,
- borderRadius: Spacing.two,
- alignItems: 'center',
- },
- resetButton: {
- backgroundColor: '#e5e5ea',
- },
- resetButtonText: {
- fontSize: 16,
- fontWeight: '600',
- color: '#8e8e93',
- },
- applyButton: {
- backgroundColor: '#007AFF',
- },
- applyButtonText: {
- fontSize: 16,
- fontWeight: '600',
- color: '#ffffff',
- },
-});
diff --git a/src/components/hint-row.tsx b/src/components/hint-row.tsx
deleted file mode 100644
index a66062b..0000000
--- a/src/components/hint-row.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React, { type ReactNode } from 'react';
-import { View, StyleSheet } from 'react-native';
-
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-
-import { Spacing } from '@/constants/theme';
-
-type HintRowProps = {
- title?: string;
- hint?: ReactNode;
-};
-
-export function HintRow({ title = 'Try editing', hint = 'app/index.tsx' }: HintRowProps) {
- return (
-
- {title}
-
- {hint}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- stepRow: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- },
- codeSnippet: {
- borderRadius: Spacing.two,
- paddingVertical: Spacing.half,
- paddingHorizontal: Spacing.two,
- },
-});
diff --git a/src/components/search-filters.tsx b/src/components/search-filters.tsx
deleted file mode 100644
index 3ac8adf..0000000
--- a/src/components/search-filters.tsx
+++ /dev/null
@@ -1,224 +0,0 @@
-import React from "react";
-import { StyleSheet, ScrollView, TouchableOpacity, View } from "react-native";
-import { SearchFilters as SearchFiltersData } from "@/types/feed";
-import { ThemedView } from "./themed-view";
-import { Colors, Spacing } from "@/constants/theme";
-import { useColorScheme } from "react-native";
-
-interface FilterChipProps {
- label: string;
- value?: string;
- onRemove: () => void;
- icon?: string;
-}
-
-function FilterChip({ label, value, onRemove, icon }: FilterChipProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === "unspecified" ? "light" : scheme];
-
- return (
-
- {icon && {icon}}
- {label}:
- {value}
- ✕
-
- );
-}
-
-interface SearchFiltersProps {
- filters: SearchFiltersData;
- onFilterChange: (filters: Partial) => void;
- onClearAll: () => void;
- availableFeeds?: Array<{ id: string; title: string }>;
-}
-
-export function SearchFilters({
- filters,
- onFilterChange,
- onClearAll,
- availableFeeds,
-}: SearchFiltersProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === "unspecified" ? "light" : scheme];
-
- const getFeedTitle = (feedId: string) => {
- const feed = availableFeeds?.find((f) => f.id === feedId);
- return feed?.title || feedId;
- };
-
- const formatDate = (date: Date) => {
- return date.toLocaleDateString("en-US", {
- month: "short",
- day: "numeric",
- year: "numeric",
- });
- };
-
- const renderFilterChips = () => {
- const chips: any[] = [];
-
- // Date range filter
- if (filters.dateFrom || filters.dateTo) {
- const fromLabel = filters.dateFrom
- ? formatDate(filters.dateFrom)
- : "Any date";
- const toLabel = filters.dateTo ? formatDate(filters.dateTo) : "Now";
- chips.push(
-
- onFilterChange({ dateFrom: undefined, dateTo: undefined })
- }
- />,
- );
- }
-
- // Feed filters
- if (filters.feedIds && filters.feedIds.length > 0) {
- const feedCount = filters.feedIds.length;
- const feedTitle =
- feedCount === 1
- ? getFeedTitle(filters.feedIds[0])
- : `${feedCount} feeds`;
- chips.push(
- onFilterChange({ feedIds: undefined })}
- />,
- );
- }
-
- // Author filters
- if (filters.authors && filters.authors.length > 0) {
- const authorCount = filters.authors.length;
- const authorLabel =
- authorCount === 1 ? filters.authors[0] : `${authorCount} authors`;
- chips.push(
- onFilterChange({ authors: undefined })}
- />,
- );
- }
-
- // Content type filter
- if (filters.contentType) {
- const contentTypeLabels: Record = {
- article: "Articles",
- audio: "Audio",
- video: "Video",
- };
- const contentTypeIcons: Record = {
- article: "📄",
- audio: "🎵",
- video: "🎬",
- };
- chips.push(
- onFilterChange({ contentType: undefined })}
- />,
- );
- }
-
- return chips;
- };
-
- const hasActiveFilters =
- filters.dateFrom ||
- filters.dateTo ||
- (filters.feedIds?.length ?? 0) > 0 ||
- (filters.authors?.length ?? 0) > 0 ||
- filters.contentType !== undefined;
-
- if (!hasActiveFilters) {
- return null;
- }
-
- return (
-
-
- {renderFilterChips()}
-
- {hasActiveFilters && (
-
- Clear all
-
- )}
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flexDirection: "row",
- alignItems: "center",
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- gap: Spacing.two,
- },
- chipsContainer: {
- flex: 1,
- gap: Spacing.two,
- },
- chip: {
- flexDirection: "row",
- alignItems: "center",
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.one,
- borderRadius: Spacing.two,
- backgroundColor: "#e5e5ea",
- gap: Spacing.one,
- },
- chipIcon: {
- fontSize: 12,
- },
- chipText: {
- fontSize: 12,
- color: "#8e8e93",
- fontWeight: "600",
- },
- chipValue: {
- fontSize: 12,
- color: "#000000",
- },
- chipClose: {
- fontSize: 14,
- color: "#8e8e93",
- marginLeft: Spacing.one,
- },
- clearAllButton: {
- paddingHorizontal: Spacing.two,
- paddingVertical: Spacing.one,
- },
- clearAllText: {
- fontSize: 12,
- color: "#007AFF",
- fontWeight: "500",
- },
-});
diff --git a/src/components/search-input.tsx b/src/components/search-input.tsx
deleted file mode 100644
index 422c23b..0000000
--- a/src/components/search-input.tsx
+++ /dev/null
@@ -1,180 +0,0 @@
-import React, { useRef, useEffect } from 'react';
-import { StyleSheet, TouchableOpacity, TextInput, ViewStyle, TextStyle } from 'react-native';
-import { useSearchStore } from '@/stores/search-store';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-interface SearchInputProps {
- onSearch?: (query: string) => void;
- style?: ViewStyle;
- inputStyle?: TextStyle;
- placeholder?: string;
- autoFocus?: boolean;
-}
-
-export function SearchInput({
- onSearch,
- style,
- inputStyle,
- placeholder = 'Search articles and feeds...',
- autoFocus = false,
-}: SearchInputProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- const { query, setQuery, clearSearch, searchHistory } = useSearchStore();
- const inputRef = useRef(null);
-
- // Debounced search handler
- useEffect(() => {
- if (!onSearch) return;
-
- const timer = setTimeout(() => {
- onSearch(query);
- }, 300);
-
- return () => clearTimeout(timer);
- }, [query, onSearch]);
-
- const handleClear = () => {
- setQuery('');
- inputRef.current?.focus();
- };
-
- const handleClearSearch = () => {
- clearSearch();
- inputRef.current?.focus();
- };
-
- return (
-
-
- 🔍
-
- {query ? (
-
- ✕
-
- ) : null}
-
-
- {query && (
-
-
- Clear search
-
-
- )}
-
- {searchHistory.length > 0 && !query && (
-
-
- Recent searches:
-
-
- {searchHistory.map((item) => (
- {
- setQuery(item.query);
- onSearch?.(item.query);
- }}
- >
-
- {item.query}
-
-
- ))}
-
-
- )}
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- paddingHorizontal: Spacing.three,
- paddingBottom: Spacing.two,
- },
- inputContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- backgroundColor: '#f6f6f6',
- borderRadius: Spacing.three,
- paddingHorizontal: Spacing.three,
- height: 44,
- },
- searchIcon: {
- fontSize: 18,
- marginRight: Spacing.two,
- },
- input: {
- flex: 1,
- fontSize: 16,
- height: '100%',
- },
- clearButton: {
- width: 24,
- height: 24,
- borderRadius: 12,
- justifyContent: 'center',
- alignItems: 'center',
- },
- clearIcon: {
- fontSize: 14,
- fontWeight: 'bold',
- },
- clearSearchButton: {
- alignItems: 'center',
- paddingVertical: Spacing.two,
- },
- clearSearchText: {
- color: '#007AFF',
- },
- historyContainer: {
- marginTop: Spacing.two,
- },
- historyLabel: {
- fontSize: 12,
- color: '#8e8e93',
- marginBottom: Spacing.two,
- },
- historyList: {
- flexDirection: 'row',
- flexWrap: 'wrap',
- gap: Spacing.two,
- },
- historyItem: {
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- backgroundColor: '#e5e5ea',
- borderRadius: Spacing.two,
- },
- historyText: {
- fontSize: 14,
- },
-});
diff --git a/src/components/search-results.tsx b/src/components/search-results.tsx
deleted file mode 100644
index bec2bb4..0000000
--- a/src/components/search-results.tsx
+++ /dev/null
@@ -1,172 +0,0 @@
-import React, { useState } from 'react';
-import { StyleSheet, FlatList, ViewToken, ActivityIndicator } from 'react-native';
-import { SearchResult } from '@/types/feed';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-import { ArticleCard } from './article-card';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-interface SearchResultsProps {
- articles: SearchResult[];
- feeds: SearchResult[];
- loading: boolean;
- onLoadMore?: () => void;
- onResultPress?: (result: SearchResult) => void;
- hasMore?: boolean;
-}
-
-export function SearchResults({
- articles,
- feeds,
- loading,
- onLoadMore,
- onResultPress,
- hasMore = false,
-}: SearchResultsProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- const [visibleArticles, setVisibleArticles] = useState>(new Set());
- const [visibleFeeds, setVisibleFeeds] = useState>(new Set());
-
- const keyExtractor = (item: SearchResult) => item.id;
-
- const onViewableItemsChangedArticles = ({ viewableItems }: { viewableItems: ViewToken[] }) => {
- const newVisible = new Set(visibleArticles);
- viewableItems.forEach(item => {
- if (item.isViewable) {
- newVisible.add(item.key);
- }
- });
- setVisibleArticles(newVisible);
- };
-
- const onViewableItemsChangedFeeds = ({ viewableItems }: { viewableItems: ViewToken[] }) => {
- const newVisible = new Set(visibleFeeds);
- viewableItems.forEach(item => {
- if (item.isViewable) {
- newVisible.add(item.key);
- }
- });
- setVisibleFeeds(newVisible);
- };
-
- const viewabilityConfig = {
- itemVisiblePercentThreshold: 50,
- };
-
- const renderArticle = ({ item }: { item: SearchResult }) => (
-
- );
-
- const renderFeed = ({ item }: { item: SearchResult }) => (
-
- );
-
- const renderFooter = () => {
- if (!loading || !hasMore) return null;
- return (
-
-
-
- );
- };
-
- const renderEmptyState = () => {
- if (!loading && articles.length === 0 && feeds.length === 0) {
- return (
-
-
- No results found
-
-
- Try different keywords or check your filters
-
-
- );
- }
- return null;
- };
-
- return (
-
- {feeds.length > 0 && (
-
-
- Feeds ({feeds.length})
-
-
-
- )}
-
-
- {(articles.length > 0 || loading) && (
-
- Articles ({articles.length})
-
- )}
-
- {renderEmptyState()}
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- section: {
- paddingHorizontal: Spacing.three,
- paddingBottom: Spacing.three,
- },
- sectionHeader: {
- fontSize: 14,
- marginBottom: Spacing.three,
- marginTop: Spacing.two,
- },
- feedsList: {
- paddingRight: Spacing.three,
- },
- articlesList: {
- paddingBottom: Spacing.four,
- },
- loadingContainer: {
- paddingVertical: Spacing.four,
- alignItems: 'center',
- },
- emptyContainer: {
- paddingVertical: Spacing.six * 2,
- alignItems: 'center',
- },
- emptyTitle: {
- textAlign: 'center',
- marginBottom: Spacing.two,
- },
- emptySubtitle: {
- textAlign: 'center',
- color: '#8e8e93',
- },
-});
diff --git a/src/components/search-sort.tsx b/src/components/search-sort.tsx
deleted file mode 100644
index 60250a6..0000000
--- a/src/components/search-sort.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import React from 'react';
-import { StyleSheet, ScrollView, TouchableOpacity } from 'react-native';
-import { SearchSortOption } from '@/types/feed';
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-import { Colors, Spacing } from '@/constants/theme';
-import { useColorScheme } from 'react-native';
-
-const SORT_OPTIONS: { value: SearchSortOption; label: string; icon: string }[] = [
- { value: 'relevance', label: 'Relevance', icon: '⭐' },
- { value: 'date_desc', label: 'Newest', icon: '📅' },
- { value: 'date_asc', label: 'Oldest', icon: '🕐' },
- { value: 'title_asc', label: 'A-Z', icon: '🔤' },
- { value: 'title_desc', label: 'Z-A', icon: '🔡' },
- { value: 'feed_asc', label: 'Feed A-Z', icon: '📰' },
- { value: 'feed_desc', label: 'Feed Z-A', icon: '📰' },
-];
-
-interface SearchSortProps {
- sort: SearchSortOption;
- onSortChange: (sort: SearchSortOption) => void;
-}
-
-export function SearchSort({ sort, onSortChange }: SearchSortProps) {
- const scheme = useColorScheme();
- const colors = Colors[scheme === 'unspecified' ? 'light' : scheme];
-
- return (
-
- {SORT_OPTIONS.map((option) => {
- const isActive = sort === option.value;
- return (
- onSortChange(option.value)}
- activeOpacity={0.7}
- >
-
- {option.icon} {option.label}
-
-
- );
- })}
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- gap: Spacing.two,
- },
- button: {
- paddingHorizontal: Spacing.three,
- paddingVertical: Spacing.two,
- borderRadius: Spacing.two,
- backgroundColor: '#e5e5ea',
- minWidth: 80,
- alignItems: 'center',
- },
- buttonText: {
- fontSize: 14,
- color: '#8e8e93',
- },
- activeButtonText: {
- color: '#ffffff',
- },
-});
diff --git a/src/components/settings.tsx b/src/components/settings.tsx
deleted file mode 100644
index 0e2091d..0000000
--- a/src/components/settings.tsx
+++ /dev/null
@@ -1,548 +0,0 @@
-import React from 'react';
-import { ScrollView, StyleSheet, Switch, View, TextInput, Pressable } from 'react-native';
-import { useColorScheme } from 'react-native';
-
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { Collapsible } from '@/components/ui/collapsible';
-import { SYNC_INTERVALS, SyncInterval, NotificationPreferences, ReadingPreferences } from '@/types/feed';
-import { AccountSettings } from '@/types/global';
-import { useTheme } from '@/hooks/use-theme';
-import { useSettingsStore } from '@/stores/settings-store';
-
-export default function SettingsScreen() {
- const colorScheme = useColorScheme();
- const theme = useTheme();
-
- const {
- syncInterval,
- setSyncInterval,
- theme: themeSetting,
- setTheme,
- notificationPreferences,
- setNotificationPreferences,
- readingPreferences,
- setReadingPreferences,
- accountSettings,
- setAccountSettings,
- } = useSettingsStore();
-
- // Sync interval handler
- const handleSyncIntervalChange = (value: number) => {
- const interval = SYNC_INTERVALS.find((i) => i.value === value);
- if (interval) {
- setSyncInterval(interval);
- }
- };
-
- // Notification handlers
- const handleNotificationToggle = (key: keyof NotificationPreferences, value: boolean) => {
- setNotificationPreferences({ [key]: value });
- };
-
- // Reading preference handlers
- const handleReadingToggle = (key: keyof ReadingPreferences, value: boolean) => {
- setReadingPreferences({ [key]: value });
- };
-
- const handleFontSizeChange = (size: ReadingPreferences['fontSize']) => {
- setReadingPreferences({ fontSize: size });
- };
-
- const handleLineHeightChange = (height: ReadingPreferences['lineHeight']) => {
- setReadingPreferences({ lineHeight: height });
- };
-
- // Theme handler
- const handleThemeChange = (theme: 'light' | 'dark' | 'system') => {
- setTheme(theme);
- };
-
- // Account settings handlers
- const handleAccountSettingChange = (key: keyof AccountSettings, value: string | boolean) => {
- setAccountSettings({ [key]: value });
- };
-
- return (
-
-
- {/* Sync Settings */}
-
- Sync Settings
-
- Choose how often your feeds should be updated.
-
-
-
- {SYNC_INTERVALS.map((interval) => (
- handleSyncIntervalChange(interval.value)}
- style={({ pressed }) => [
- styles.intervalItem,
- {
- backgroundColor:
- syncInterval.value === interval.value
- ? theme.backgroundSelected
- : theme.backgroundElement,
- opacity: pressed ? 0.7 : 1,
- },
- ]}
- >
-
- {interval.label}
-
- {syncInterval.value === interval.value && (
-
-
-
- )}
-
- ))}
-
-
-
- {/* Theme */}
-
- Theme
-
- Choose your preferred appearance.
-
-
-
- handleThemeChange('light')}
- style={({ pressed }) => [
- styles.themeButton,
- { opacity: pressed ? 0.7 : 1 },
- ]}
- >
-
- Light
-
- handleThemeChange('dark')}
- style={({ pressed }) => [
- styles.themeButton,
- { opacity: pressed ? 0.7 : 1 },
- ]}
- >
-
- Dark
-
- handleThemeChange('system')}
- style={({ pressed }) => [
- styles.themeButton,
- { opacity: pressed ? 0.7 : 1 },
- ]}
- >
-
- System
-
-
-
-
- ⚠️ Note
-
- Changing theme will apply on app restart.
-
-
-
-
- {/* Notifications */}
-
- Notifications
-
- Manage how you receive notifications.
-
-
-
-
- New Articles
- handleNotificationToggle('newArticles', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- Episode Releases
- handleNotificationToggle('episodeReleases', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- Custom Alerts
- handleNotificationToggle('customAlerts', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
-
- Sound
- handleNotificationToggle('sound', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- Vibration
- handleNotificationToggle('vibration', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- {/* Reading Preferences */}
-
- Reading Preferences
-
- Customize your reading experience.
-
-
-
- Font Size
-
- {(['small', 'medium', 'large', 'xlarge'] as ReadingPreferences['fontSize'][]).map((size) => (
- handleFontSizeChange(size)}
- style={({ pressed }) => [
- styles.fontSizeButton,
- {
- backgroundColor:
- readingPreferences.fontSize === size
- ? theme.backgroundSelected
- : theme.backgroundElement,
- opacity: pressed ? 0.7 : 1,
- },
- ]}
- >
-
- {size === 'small' ? 'A' : size === 'medium' ? 'B' : size === 'large' ? 'C' : 'D'}
-
-
- ))}
-
-
-
-
- Line Height
-
- {(['normal', 'relaxed', 'loose'] as ReadingPreferences['lineHeight'][]).map((height) => (
- handleLineHeightChange(height)}
- style={({ pressed }) => [
- styles.lineHeightButton,
- {
- backgroundColor:
- readingPreferences.lineHeight === height
- ? theme.backgroundSelected
- : theme.backgroundElement,
- opacity: pressed ? 0.7 : 1,
- },
- ]}
- >
- {height.charAt(0).toUpperCase() + height.slice(1)}
-
- ))}
-
-
-
-
-
- Show Reading Time
- handleReadingToggle('showReadingTime', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- Show Author
- handleReadingToggle('showAuthor', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- Show Date
- handleReadingToggle('showDate', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
- {/* Account Settings */}
-
- Account Settings
-
- Manage your account preferences.
-
-
-
- Email
- handleAccountSettingChange('email', text)}
- keyboardType="email-address"
- autoCapitalize="none"
- />
-
-
-
- Privacy Level
-
- {(['public', 'private', 'anonymous'] as AccountSettings['privacy'][]).map((privacy) => (
- handleAccountSettingChange('privacy', privacy)}
- style={({ pressed }) => [
- styles.privacyButton,
- {
- backgroundColor:
- accountSettings.privacy === privacy
- ? theme.backgroundSelected
- : theme.backgroundElement,
- opacity: pressed ? 0.7 : 1,
- },
- ]}
- >
-
- {privacy.charAt(0).toUpperCase() + privacy.slice(1)}
-
-
- ))}
-
-
-
-
- Language
- handleAccountSettingChange('language', text)}
- />
-
-
-
- Timezone
- handleAccountSettingChange('timezone', text)}
- />
-
-
-
-
- Notifications Enabled
- handleAccountSettingChange('notificationsEnabled', value)}
- trackColor={{ false: theme.textSecondary, true: theme.text }}
- thumbColor="white"
- />
-
-
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- scrollView: {
- flex: 1,
- },
- scrollContent: {
- paddingBottom: 24,
- },
- section: {
- marginBottom: 24,
- paddingHorizontal: 16,
- },
- sectionTitle: {
- marginBottom: 4,
- },
- sectionDescription: {
- marginBottom: 16,
- },
- intervalContainer: {
- gap: 8,
- },
- intervalItem: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- padding: 16,
- borderRadius: 12,
- gap: 12,
- },
- intervalLabel: {
- fontSize: 14,
- },
- checkmark: {
- width: 20,
- height: 20,
- borderRadius: 10,
- justifyContent: 'center',
- alignItems: 'center',
- },
- checkmarkCircle: {
- width: 12,
- height: 12,
- borderRadius: 6,
- backgroundColor: '#4CAF50',
- },
- themeContainer: {
- flexDirection: 'row',
- justifyContent: 'space-around',
- alignItems: 'center',
- marginBottom: 16,
- },
- themeButton: {
- alignItems: 'center',
- gap: 4,
- },
- themeCircle: {
- width: 40,
- height: 40,
- borderRadius: 20,
- },
- themeLabel: {
- fontSize: 12,
- },
- warningBox: {
- padding: 12,
- borderRadius: 8,
- marginBottom: 16,
- },
- warningTitle: {
- marginBottom: 4,
- },
- warningText: {},
- prefGroup: {
- marginBottom: 8,
- },
- prefHeader: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- },
- prefTitle: {
- fontSize: 14,
- },
- fontSizeSelector: {
- flexDirection: 'row',
- gap: 8,
- },
- fontSizeButton: {
- padding: 12,
- borderRadius: 8,
- minWidth: 44,
- alignItems: 'center',
- justifyContent: 'center',
- },
- fontSizeLabel: {
- fontWeight: 'bold',
- },
- lineHeightSelector: {
- flexDirection: 'row',
- gap: 8,
- },
- lineHeightButton: {
- flex: 1,
- padding: 12,
- borderRadius: 8,
- alignItems: 'center',
- },
- lineHeightLabel: {
- fontSize: 12,
- textAlign: 'center',
- },
- input: {
- borderRadius: 8,
- padding: 12,
- fontSize: 14,
- marginTop: 4,
- },
- privacySelector: {
- flexDirection: 'row',
- gap: 8,
- marginTop: 4,
- },
- privacyButton: {
- flex: 1,
- padding: 12,
- borderRadius: 8,
- alignItems: 'center',
- },
- privacyLabel: {
- fontSize: 14,
- textAlign: 'center',
- },
-});
diff --git a/src/components/themed-text.tsx b/src/components/themed-text.tsx
deleted file mode 100644
index 8fa6014..0000000
--- a/src/components/themed-text.tsx
+++ /dev/null
@@ -1,85 +0,0 @@
-import { Platform, StyleSheet, Text, type TextProps } from 'react-native';
-
-import { Fonts, ThemeColor } from '@/constants/theme';
-import { useTheme } from '@/hooks/use-theme';
-
-export type ThemedTextProps = TextProps & {
- type?: 'default' | 'title' | 'small' | 'smallBold' | 'subtitle' | 'link' | 'linkPrimary' | 'code' | 'section' | 'defaultSemiBold';
- themeColor?: ThemeColor;
-};
-
-export function ThemedText({ style, type = 'default', themeColor, ...rest }: ThemedTextProps) {
- const theme = useTheme();
-
- return (
-
- );
-}
-
-const styles = StyleSheet.create({
- small: {
- fontSize: 14,
- lineHeight: 20,
- fontWeight: 500,
- },
- smallBold: {
- fontSize: 14,
- lineHeight: 20,
- fontWeight: 700,
- },
- default: {
- fontSize: 16,
- lineHeight: 24,
- fontWeight: 500,
- },
- defaultSemiBold: {
- fontSize: 16,
- lineHeight: 24,
- fontWeight: 600,
- },
- title: {
- fontSize: 48,
- fontWeight: 600,
- lineHeight: 52,
- },
- subtitle: {
- fontSize: 32,
- lineHeight: 44,
- fontWeight: 600,
- },
- section: {
- fontSize: 20,
- fontWeight: 600,
- lineHeight: 24,
- },
- link: {
- lineHeight: 30,
- fontSize: 14,
- },
- linkPrimary: {
- lineHeight: 30,
- fontSize: 14,
- color: '#3c87f7',
- },
- code: {
- fontFamily: Fonts.mono,
- fontWeight: Platform.select({ android: 700 }) ?? 500,
- fontSize: 12,
- },
-});
diff --git a/src/components/themed-view.tsx b/src/components/themed-view.tsx
deleted file mode 100644
index c710df9..0000000
--- a/src/components/themed-view.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { View, type ViewProps } from 'react-native';
-
-import { ThemeColor } from '@/constants/theme';
-import { useTheme } from '@/hooks/use-theme';
-
-export type ThemedViewProps = ViewProps & {
- lightColor?: string;
- darkColor?: string;
- type?: ThemeColor;
-};
-
-export function ThemedView({ style, lightColor, darkColor, type, ...otherProps }: ThemedViewProps) {
- const theme = useTheme();
-
- return ;
-}
diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible.tsx
deleted file mode 100644
index d0d745b..0000000
--- a/src/components/ui/collapsible.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { SymbolView } from 'expo-symbols';
-import { PropsWithChildren, useState } from 'react';
-import { Pressable, StyleSheet } from 'react-native';
-import Animated, { FadeIn } from 'react-native-reanimated';
-
-import { ThemedText } from '@/components/themed-text';
-import { ThemedView } from '@/components/themed-view';
-import { Spacing } from '@/constants/theme';
-import { useTheme } from '@/hooks/use-theme';
-
-export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
- const [isOpen, setIsOpen] = useState(false);
- const theme = useTheme();
-
- return (
-
- [styles.heading, pressed && styles.pressedHeading]}
- onPress={() => setIsOpen((value) => !value)}>
-
-
-
-
- {title}
-
- {isOpen && (
-
-
- {children}
-
-
- )}
-
- );
-}
-
-const styles = StyleSheet.create({
- heading: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: Spacing.two,
- },
- pressedHeading: {
- opacity: 0.7,
- },
- button: {
- width: Spacing.four,
- height: Spacing.four,
- borderRadius: 12,
- justifyContent: 'center',
- alignItems: 'center',
- },
- content: {
- marginTop: Spacing.three,
- borderRadius: Spacing.three,
- marginLeft: Spacing.four,
- padding: Spacing.four,
- },
-});
diff --git a/src/components/web-badge.tsx b/src/components/web-badge.tsx
deleted file mode 100644
index 23933d2..0000000
--- a/src/components/web-badge.tsx
+++ /dev/null
@@ -1,44 +0,0 @@
-import { version } from 'expo/package.json';
-import { Image } from 'expo-image';
-import React from 'react';
-import { useColorScheme, StyleSheet } from 'react-native';
-
-import { ThemedText } from './themed-text';
-import { ThemedView } from './themed-view';
-
-import { Spacing } from '@/constants/theme';
-
-export function WebBadge() {
- const scheme = useColorScheme();
-
- return (
-
-
- v{version}
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- padding: Spacing.five,
- alignItems: 'center',
- gap: Spacing.two,
- },
- versionText: {
- textAlign: 'center',
- },
- badgeImage: {
- width: 123,
- aspectRatio: 123 / 24,
- },
-});
diff --git a/src/constants/theme.ts b/src/constants/theme.ts
deleted file mode 100644
index c10ed27..0000000
--- a/src/constants/theme.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
- * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
- */
-
-import '@/global.css';
-
-import { Platform } from 'react-native';
-
-export const Colors = {
- light: {
- text: '#000000',
- background: '#ffffff',
- backgroundElement: '#F0F0F3',
- backgroundSelected: '#E0E1E6',
- textSecondary: '#60646C',
- },
- dark: {
- text: '#ffffff',
- background: '#000000',
- backgroundElement: '#212225',
- backgroundSelected: '#2E3135',
- textSecondary: '#B0B4BA',
- },
-} as const;
-
-export type ThemeColor = keyof typeof Colors.light & keyof typeof Colors.dark;
-
-export const Fonts = Platform.select({
- ios: {
- /** iOS `UIFontDescriptorSystemDesignDefault` */
- sans: 'system-ui',
- /** iOS `UIFontDescriptorSystemDesignSerif` */
- serif: 'ui-serif',
- /** iOS `UIFontDescriptorSystemDesignRounded` */
- rounded: 'ui-rounded',
- /** iOS `UIFontDescriptorSystemDesignMonospaced` */
- mono: 'ui-monospace',
- },
- default: {
- sans: 'normal',
- serif: 'serif',
- rounded: 'normal',
- mono: 'monospace',
- },
- web: {
- sans: 'var(--font-display)',
- serif: 'var(--font-serif)',
- rounded: 'var(--font-rounded)',
- mono: 'var(--font-mono)',
- },
-});
-
-export const Spacing = {
- half: 2,
- one: 4,
- two: 8,
- three: 16,
- four: 24,
- five: 32,
- six: 64,
-} as const;
-
-export const BottomTabInset = Platform.select({ ios: 50, android: 80 }) ?? 0;
-export const MaxContentWidth = 800;
diff --git a/src/global.css b/src/global.css
deleted file mode 100644
index c8fe503..0000000
--- a/src/global.css
+++ /dev/null
@@ -1,9 +0,0 @@
-:root {
- --font-display:
- Spline Sans, Inter, ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji,
- Segoe UI Symbol, Noto Color Emoji;
- --font-mono:
- ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
- --font-rounded: 'SF Pro Rounded', 'Hiragino Maru Gothic ProN', Meiryo, 'MS PGothic', sans-serif;
- --font-serif: Georgia, 'Times New Roman', serif;
-}
diff --git a/src/hooks/use-color-scheme.ts b/src/hooks/use-color-scheme.ts
deleted file mode 100644
index 17e3c63..0000000
--- a/src/hooks/use-color-scheme.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { useColorScheme } from 'react-native';
diff --git a/src/hooks/use-color-scheme.web.ts b/src/hooks/use-color-scheme.web.ts
deleted file mode 100644
index 7eb1c1b..0000000
--- a/src/hooks/use-color-scheme.web.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useEffect, useState } from 'react';
-import { useColorScheme as useRNColorScheme } from 'react-native';
-
-/**
- * To support static rendering, this value needs to be re-calculated on the client side for web
- */
-export function useColorScheme() {
- const [hasHydrated, setHasHydrated] = useState(false);
-
- useEffect(() => {
- setHasHydrated(true);
- }, []);
-
- const colorScheme = useRNColorScheme();
-
- if (hasHydrated) {
- return colorScheme;
- }
-
- return 'light';
-}
diff --git a/src/hooks/use-feed-list.ts b/src/hooks/use-feed-list.ts
deleted file mode 100644
index 1720154..0000000
--- a/src/hooks/use-feed-list.ts
+++ /dev/null
@@ -1,82 +0,0 @@
-import { useState, useCallback, useEffect } from 'react';
-import { FeedItem } from '@/types/feed';
-import { getAllFeedItems } from '@/services/database';
-
-const PAGE_SIZE = 20;
-
-export function useFeedList() {
- const [localFeedItems, setLocalFeedItems] = useState([]);
- const [page, setPage] = useState(0);
- const [hasMore, setHasMore] = useState(true);
- const [isRefreshing, setIsRefreshing] = useState(false);
- const [loadingMore, setLoadingMore] = useState(false);
- const [error, setError] = useState(null);
-
- const loadMore = useCallback(async () => {
- if (loadingMore || !hasMore || isRefreshing) return;
-
- setLoadingMore(true);
-
- try {
- const offset = page * PAGE_SIZE;
- const items = await getAllFeedItems(PAGE_SIZE + 1, offset);
-
- if (items.length > PAGE_SIZE) {
- const newItems = items.slice(0, PAGE_SIZE);
- setLocalFeedItems(prev => [...prev, ...newItems]);
- setHasMore(true);
- } else {
- setLocalFeedItems(prev => [...prev, ...items]);
- setHasMore(false);
- }
-
- setPage(prev => prev + 1);
- setError(null);
- } catch (err) {
- console.error('Failed to load more items:', err);
- setError('Failed to load more items. Please try again.');
- } finally {
- setLoadingMore(false);
- }
- }, [loadingMore, hasMore, isRefreshing, page]);
-
- const refreshFeed = useCallback(async () => {
- if (isRefreshing) return;
-
- setIsRefreshing(true);
- setPage(0);
- setHasMore(true);
- setError(null);
-
- try {
- const items = await getAllFeedItems(PAGE_SIZE + 1);
-
- if (items.length > PAGE_SIZE) {
- setLocalFeedItems(items.slice(0, PAGE_SIZE));
- setHasMore(true);
- } else {
- setLocalFeedItems(items);
- setHasMore(false);
- }
- } catch (err) {
- console.error('Failed to refresh feed:', err);
- setError('Failed to refresh feed. Please try again.');
- } finally {
- setIsRefreshing(false);
- }
- }, [isRefreshing]);
-
- useEffect(() => {
- refreshFeed();
- }, []);
-
- return {
- feedItems: localFeedItems,
- loading: loadingMore,
- hasMore,
- loadMore,
- refreshFeed,
- isRefreshing,
- error,
- };
-}
diff --git a/src/hooks/use-offline.ts b/src/hooks/use-offline.ts
deleted file mode 100644
index fdf2bfc..0000000
--- a/src/hooks/use-offline.ts
+++ /dev/null
@@ -1,99 +0,0 @@
-// Offline/Online Network Hook
-
-import { useState, useEffect, useCallback } from 'react';
-import { hasLocalData, getAllLocalFeedItems, getLocalFeedItems, syncAllFeeds } from '@/services/sync-service';
-import { FeedItem } from '@/types/feed';
-
-type NetworkStatus = 'online' | 'offline' | 'unknown';
-
-interface UseOfflineReturn {
- isOnline: boolean;
- networkStatus: NetworkStatus;
- hasOfflineData: boolean;
- isSyncing: boolean;
- lastSyncTime: Date | null;
- syncNow: () => Promise;
- getOfflineFeedItems: (subscriptionId?: string, limit?: number, offset?: number) => Promise;
-}
-
-export function useOffline(): UseOfflineReturn {
- const [networkStatus, setNetworkStatus] = useState('unknown');
- const [hasOfflineData, setHasOfflineData] = useState(false);
- const [isSyncing, setIsSyncing] = useState(false);
- const [lastSyncTime, setLastSyncTime] = useState(null);
-
- // Check network status (simplified - in production would use @react-native-community/netinfo)
- const checkNetworkStatus = useCallback(async () => {
- try {
- // Try to fetch from a known endpoint to test connectivity
- const response = await fetch('https://www.google.com/favicon.ico', {
- method: 'HEAD',
- mode: 'no-cors',
- });
- setNetworkStatus('online');
- return true;
- } catch {
- setNetworkStatus('offline');
- return false;
- }
- }, []);
-
- // Check if we have offline data
- const checkOfflineData = useCallback(async () => {
- const hasData = await hasLocalData();
- setHasOfflineData(hasData);
- return hasData;
- }, []);
-
- // Sync now
- const syncNow = useCallback(async () => {
- if (networkStatus === 'offline') {
- console.log('[Offline] Cannot sync while offline');
- return;
- }
-
- setIsSyncing(true);
- try {
- await syncAllFeeds();
- setLastSyncTime(new Date());
- await checkOfflineData();
- } finally {
- setIsSyncing(false);
- }
- }, [networkStatus, checkOfflineData]);
-
- // Get offline feed items
- const getOfflineFeedItems = useCallback(async (
- subscriptionId?: string,
- limit: number = 50,
- offset: number = 0
- ): Promise => {
- if (subscriptionId) {
- return getLocalFeedItems(subscriptionId, limit, offset);
- }
- return getAllLocalFeedItems(limit);
- }, []);
-
- // Initial checks
- useEffect(() => {
- checkNetworkStatus();
- checkOfflineData();
-
- // Periodic network check
- const interval = setInterval(() => {
- checkNetworkStatus();
- }, 30000); // Every 30 seconds
-
- return () => clearInterval(interval);
- }, [checkNetworkStatus, checkOfflineData]);
-
- return {
- isOnline: networkStatus === 'online',
- networkStatus,
- hasOfflineData,
- isSyncing,
- lastSyncTime,
- syncNow,
- getOfflineFeedItems,
- };
-}
\ No newline at end of file
diff --git a/src/hooks/use-theme.ts b/src/hooks/use-theme.ts
deleted file mode 100644
index 677e015..0000000
--- a/src/hooks/use-theme.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Learn more about light and dark modes:
- * https://docs.expo.dev/guides/color-schemes/
- */
-
-import { Colors } from '@/constants/theme';
-import { useColorScheme } from '@/hooks/use-color-scheme';
-
-export function useTheme() {
- const scheme = useColorScheme();
- const theme = scheme === 'unspecified' ? 'light' : scheme;
-
- return Colors[theme];
-}
diff --git a/src/i18n/index.ts b/src/i18n/index.ts
deleted file mode 100644
index 4b0f836..0000000
--- a/src/i18n/index.ts
+++ /dev/null
@@ -1,113 +0,0 @@
-// Internationalization Setup
-
-import { getLocales } from 'expo-localization';
-
-type IntlConfig = {
- enableHighAccuracy: boolean;
- fallbackLocale: string;
- supportedLocales: string[];
-};
-
-const intlConfig: IntlConfig = {
- enableHighAccuracy: true,
- fallbackLocale: 'en',
- supportedLocales: ['en', 'es', 'fr', 'de', 'ja', 'ko', 'zh'],
-};
-
-export const locales = {
- en: {
- name: 'English',
- strings: {
- 'app.name': 'Rssuper',
- 'tab.home': 'Home',
- 'tab.explore': 'Explore',
- 'tab.settings': 'Settings',
- 'feed.add': 'Add Feed',
- 'feed.loading': 'Loading feeds...',
- 'feed.error': 'Error loading feed',
- 'feed.noItems': 'No items in this feed',
- 'explore.discover': 'Discover new feeds and podcasts',
- 'explore.searchPlaceholder': 'Search feeds, topics, podcasts',
- 'explore.all': 'All',
- 'explore.trending': 'Trending Feeds',
- 'explore.recommended': 'Recommended Podcasts',
- 'explore.noFeeds': 'No feeds found matching your criteria',
- 'common.cancel': 'Cancel',
- 'common.save': 'Save',
- 'common.delete': 'Delete',
- 'common.edit': 'Edit',
- },
- },
- es: {
- name: 'Espa\u00f1ol',
- strings: {
- 'app.name': 'Rssuper',
- 'tab.home': 'Inicio',
- 'tab.explore': 'Explorar',
- 'tab.settings': 'Ajustes',
- 'feed.add': 'A\u00f1adir Feed',
- 'feed.loading': 'Cargando feeds...',
- 'feed.error': 'Error cargando feed',
- 'feed.noItems': 'No hay items en este feed',
- 'explore.discover': 'Descubre nuevos feeds y podcasts',
- 'explore.searchPlaceholder': 'Buscar feeds, temas, podcasts',
- 'explore.all': 'Todo',
- 'explore.trending': 'Feeds en tendencia',
- 'explore.recommended': 'Podcasts recomendados',
- 'explore.noFeeds': 'No se encontraron feeds',
- 'common.cancel': 'Cancelar',
- 'common.save': 'Guardar',
- 'common.delete': 'Eliminar',
- 'common.edit': 'Editar',
- },
- },
- fr: {
- name: 'Fran\u00e7ais',
- strings: {
- 'app.name': 'Rssuper',
- 'tab.home': 'Accueil',
- 'tab.explore': 'Explorer',
- 'tab.settings': 'Paramètres',
- 'feed.add': 'Ajouter un flux',
- 'feed.loading': 'Chargement des flux...',
- 'feed.error': 'Erreur de chargement',
- 'feed.noItems': 'Aucun \u00e9l\u00e9ment dans ce flux',
- 'explore.discover': 'D\u00e9couvrez de nouveaux flux et podcasts',
- 'explore.searchPlaceholder': 'Rechercher des flux, th\u00e8mes, podcasts',
- 'explore.all': 'Tout',
- 'explore.trending': 'Flux tendances',
- 'explore.recommended': 'Podcasts recommand\u00e9s',
- 'explore.noFeeds': 'Aucun flux trouv\u00e9',
- 'common.cancel': 'Annuler',
- 'common.save': 'Enregistrer',
- 'common.delete': 'Supprimer',
- 'common.edit': 'Modifier',
- },
- },
- // Add more languages as needed
-};
-
-export function t(key: string, locale?: string): string {
- const currentLocale = locale || getLocales()[0]?.languageTag?.split('-')[0] || 'en';
- const localeData = locales[currentLocale as keyof typeof locales];
-
- if (!localeData) return key;
-
- return localeData.strings[key as keyof typeof localeData.strings] || key;
-}
-
-export function useTranslation() {
- const currentLocale = getLocales()[0]?.languageTag?.split('-')[0] || 'en';
-
- return {
- t: (key: string) => t(key, currentLocale),
- locale: currentLocale,
- locales: Object.entries(locales).map(([code, data]) => ({
- code,
- name: data.name,
- })),
- };
-}
-
-export { intlConfig };
-export default intlConfig;
diff --git a/src/services/api.ts b/src/services/api.ts
deleted file mode 100644
index 0144a96..0000000
--- a/src/services/api.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-// API Layer Setup
-
-import axios, { AxiosInstance, AxiosError } from 'axios';
-
-const API_BASE_URL = process.env.EXPO_PUBLIC_API_URL || 'http://localhost:3000/api';
-
-// Create axios instance with defaults
-const apiClient: AxiosInstance = axios.create({
- baseURL: API_BASE_URL,
- timeout: 15000,
- headers: {
- 'Content-Type': 'application/json',
- },
-});
-
-// Request interceptor for auth tokens
-apiClient.interceptors.request.use(
- (config) => {
- // TODO: Add auth token from store
- // const token = useAuthStore.getState().token;
- // if (token) {
- // config.headers.Authorization = `Bearer ${token}`;
- // }
- return config;
- },
- (error) => Promise.reject(error)
-);
-
-// Response interceptor for error handling
-apiClient.interceptors.response.use(
- (response) => response,
- (error: AxiosError) => {
- // TODO: Add centralized error handling
- console.error('API Error:', error.response?.status, error.message);
- return Promise.reject(error);
- }
-);
-
-export default apiClient;
diff --git a/src/services/audio-player.ts b/src/services/audio-player.ts
deleted file mode 100644
index ae487cc..0000000
--- a/src/services/audio-player.ts
+++ /dev/null
@@ -1,162 +0,0 @@
-// Audio Player Service for Podcast Playback
-
-import { Audio, AVPlaybackStatus, AVPlaybackStatusSuccess } from 'expo-av';
-import { FeedItem } from '@/types/feed';
-
-type PlaybackState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
-type PlaybackSpeed = 0.5 | 0.75 | 1 | 1.25 | 1.5 | 1.75 | 2;
-
-interface PlayerState {
- state: PlaybackState;
- currentItem: FeedItem | null;
- position: number;
- duration: number;
- playbackSpeed: PlaybackSpeed;
- isBuffering: boolean;
-}
-
-type StateChangeCallback = (state: PlayerState) => void;
-
-class AudioPlayerService {
- private sound: Audio.Sound | null = null;
- private state: PlayerState = {
- state: 'idle',
- currentItem: null,
- position: 0,
- duration: 0,
- playbackSpeed: 1,
- isBuffering: false,
- };
- private listeners: Set = new Set();
-
- async initialize(): Promise {
- await Audio.setAudioModeAsync({
- allowsRecordingIOS: false,
- playsInSilentModeIOS: true,
- staysActiveInBackground: true,
- shouldDuckAndroid: true,
- playThroughEarpieceAndroid: false,
- });
- }
-
- subscribe(callback: StateChangeCallback): () => void {
- this.listeners.add(callback);
- callback(this.state);
- return () => this.listeners.delete(callback);
- }
-
- private updateState(updates: Partial): void {
- this.state = { ...this.state, ...updates };
- this.listeners.forEach(cb => cb(this.state));
- }
-
- async play(item: FeedItem): Promise {
- if (!item.enclosure?.url) {
- this.updateState({ state: 'error' });
- return;
- }
-
- try {
- this.updateState({ state: 'loading', currentItem: item, isBuffering: true });
-
- // Unload previous sound
- if (this.sound) {
- await this.sound.unloadAsync();
- this.sound = null;
- }
-
- // Create and load new sound
- const { sound } = await Audio.Sound.createAsync(
- { uri: item.enclosure.url },
- { shouldPlay: true, progressUpdateIntervalMillis: 1000 },
- this.onPlaybackStatusUpdate
- );
-
- this.sound = sound;
- } catch (error) {
- console.error('Playback error:', error);
- this.updateState({ state: 'error' });
- }
- }
-
- private onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
- if (!status.isLoaded) {
- if (status.error) {
- this.updateState({ state: 'error' });
- }
- return;
- }
-
- const loadedStatus = status as AVPlaybackStatusSuccess;
-
- this.updateState({
- state: loadedStatus.isPlaying ? 'playing' : 'paused',
- position: loadedStatus.positionMillis,
- duration: loadedStatus.durationMillis || 0,
- isBuffering: loadedStatus.isBuffering || false,
- });
- };
-
- async pause(): Promise {
- if (this.sound) {
- await this.sound.pauseAsync();
- }
- }
-
- async resume(): Promise {
- if (this.sound) {
- await this.sound.playAsync();
- }
- }
-
- async stop(): Promise {
- if (this.sound) {
- await this.sound.stopAsync();
- await this.sound.unloadAsync();
- this.sound = null;
- }
- this.updateState({
- state: 'idle',
- currentItem: null,
- position: 0,
- duration: 0,
- });
- }
-
- async seekTo(positionMs: number): Promise {
- if (this.sound) {
- await this.sound.setPositionAsync(positionMs);
- }
- }
-
- async setPlaybackSpeed(speed: PlaybackSpeed): Promise {
- if (this.sound) {
- await this.sound.setRateAsync(speed, true);
- this.updateState({ playbackSpeed: speed });
- }
- }
-
- async skipForward(seconds: number = 30): Promise {
- if (this.sound) {
- const newPosition = Math.min(
- this.state.position + seconds * 1000,
- this.state.duration
- );
- await this.sound.setPositionAsync(newPosition);
- }
- }
-
- async skipBackward(seconds: number = 10): Promise {
- if (this.sound) {
- const newPosition = Math.max(this.state.position - seconds * 1000, 0);
- await this.sound.setPositionAsync(newPosition);
- }
- }
-
- getState(): PlayerState {
- return this.state;
- }
-}
-
-export const audioPlayer = new AudioPlayerService();
-export type { PlaybackState, PlaybackSpeed, PlayerState };
\ No newline at end of file
diff --git a/src/services/background-sync.ts b/src/services/background-sync.ts
deleted file mode 100644
index d0941f7..0000000
--- a/src/services/background-sync.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-// Background Sync Service using expo-task-manager
-
-import * as TaskManager from 'expo-task-manager';
-import { syncAllFeeds, getFeedsDueForSync } from './sync-service';
-import { useFeedStore } from '@/stores/feed-store';
-
-const BACKGROUND_SYNC_TASK_NAME = 'BACKGROUND_SYNC_TASK';
-const BACKGROUND_SYNC_INTERVAL = 15; // minutes
-
-// Task manager result types
-enum BackgroundFetchResult {
- NoData = 'noData',
- NewData = 'newData',
- Failed = 'failed',
-}
-
-// Define the background task
-TaskManager.defineTask(BACKGROUND_SYNC_TASK_NAME, async () => {
- try {
- console.log('[Background] Starting background sync...');
-
- const subscriptions = useFeedStore.getState().subscriptions;
- if (subscriptions.length === 0) {
- console.log('[Background] No subscriptions to sync');
- return BackgroundFetchResult.NoData;
- }
-
- const result = await syncAllFeeds();
-
- if (result.success) {
- console.log(`[Background] Synced ${result.totalItemsSynced} items`);
- return BackgroundFetchResult.NewData;
- } else {
- console.log('[Background] Sync completed with errors');
- return BackgroundFetchResult.Failed;
- }
- } catch (error) {
- console.error('[Background] Sync error:', error);
- return BackgroundFetchResult.Failed;
- }
-});
-
-// Register background fetch task
-export async function registerBackgroundSync(): Promise {
- try {
- const task = TaskManager.defineTask(BACKGROUND_SYNC_TASK_NAME, async () => {
- try {
- console.log('[Background] Starting background sync...');
-
- const subscriptions = useFeedStore.getState().subscriptions;
- if (subscriptions.length === 0) {
- console.log('[Background] No subscriptions to sync');
- return;
- }
-
- const result = await syncAllFeeds();
- console.log(`[Background] Synced ${result.totalItemsSynced} items`);
- } catch (error) {
- console.error('[Background] Sync error:', error);
- }
- });
-
- const status = await TaskManager.isTaskRegisteredAsync(BACKGROUND_SYNC_TASK_NAME);
- if (status) {
- console.log('[Background] Background sync already registered');
- return true;
- }
-
- console.log('[Background] Background sync registered successfully');
- return true;
- } catch (error) {
- console.error('[Background] Failed to register background sync:', error);
- return false;
- }
-}
-
-// Unregister background fetch task
-export async function unregisterBackgroundSync(): Promise {
- try {
- await TaskManager.unregisterTaskAsync(BACKGROUND_SYNC_TASK_NAME);
- console.log('[Background] Background sync unregistered');
- } catch (error) {
- console.error('[Background] Failed to unregister:', error);
- }
-}
-
-// Check if background sync task is registered
-export async function isBackgroundSyncRegistered(): Promise {
- return TaskManager.isTaskRegisteredAsync(BACKGROUND_SYNC_TASK_NAME);
-}
\ No newline at end of file
diff --git a/src/services/database.ts b/src/services/database.ts
deleted file mode 100644
index 7fa26d9..0000000
--- a/src/services/database.ts
+++ /dev/null
@@ -1,320 +0,0 @@
-// Database Layer for Feed Storage
-
-import * as SQLite from 'expo-sqlite';
-import { FeedSubscription, FeedItem } from '@/types/feed';
-
-let db: SQLite.SQLiteDatabase | null = null;
-
-export async function initDatabase(): Promise {
- if (db) return;
-
- try {
- db = await SQLite.openDatabaseAsync('rssuper.db');
-
- await db.execAsync(`
- CREATE TABLE IF NOT EXISTS subscriptions (
- id TEXT PRIMARY KEY,
- url TEXT NOT NULL UNIQUE,
- title TEXT,
- category TEXT,
- enabled INTEGER DEFAULT 1,
- fetch_interval INTEGER DEFAULT 60,
- http_auth_username TEXT,
- http_auth_password TEXT,
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- last_fetched_at DATETIME,
- next_fetch_at DATETIME,
- error TEXT
- );
-
- CREATE TABLE IF NOT EXISTS feeds (
- id TEXT PRIMARY KEY,
- subscription_id TEXT NOT NULL,
- title TEXT,
- link TEXT,
- description TEXT,
- author TEXT,
- published DATETIME,
- updated DATETIME,
- content TEXT,
- guid TEXT UNIQUE,
- created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (subscription_id) REFERENCES subscriptions(id)
- );
-
- CREATE INDEX IF NOT EXISTS idx_feeds_subscription ON feeds(subscription_id);
- CREATE INDEX IF NOT EXISTS idx_feeds_published ON feeds(published DESC);
- CREATE INDEX IF NOT EXISTS idx_subscriptions_next_fetch ON subscriptions(next_fetch_at);
- CREATE INDEX IF NOT EXISTS idx_feeds_author ON feeds(author);
- CREATE INDEX IF NOT EXISTS idx_feeds_link ON feeds(link);
-
- CREATE VIRTUAL TABLE IF NOT EXISTS feeds_fts USING fts5(
- title,
- description,
- content,
- content='feeds',
- content_rowid='rowid'
- );
-
- CREATE VIRTUAL TABLE IF NOT EXISTS subscriptions_fts USING fts5(
- title,
- url,
- content='subscriptions',
- content_rowid='rowid'
- );
-
- CREATE TRIGGER IF NOT EXISTS feeds_ai AFTER INSERT ON feeds BEGIN
- INSERT INTO feeds_fts(rowid, title, description, content)
- VALUES (new.rowid, new.title, new.description, new.content);
- END;
-
- CREATE TRIGGER IF NOT EXISTS feeds_ad AFTER DELETE ON feeds BEGIN
- INSERT INTO feeds_fts(feeds_fts, rowid, title, description, content)
- VALUES ('delete', old.rowid, old.title, old.description, old.content);
- END;
-
- CREATE TRIGGER IF NOT EXISTS feeds_au AFTER UPDATE ON feeds BEGIN
- INSERT INTO feeds_fts(feeds_fts, rowid, title, description, content)
- VALUES ('delete', old.rowid, old.title, old.description, old.content);
- INSERT INTO feeds_fts(rowid, title, description, content)
- VALUES (new.rowid, new.title, new.description, new.content);
- END;
-
- CREATE TRIGGER IF NOT EXISTS subscriptions_ai AFTER INSERT ON subscriptions BEGIN
- INSERT INTO subscriptions_fts(rowid, title, url)
- VALUES (new.rowid, new.title, new.url);
- END;
-
- CREATE TRIGGER IF NOT EXISTS subscriptions_ad AFTER DELETE ON subscriptions BEGIN
- INSERT INTO subscriptions_fts(subscriptions_fts, rowid, title, url)
- VALUES ('delete', old.rowid, old.title, old.url);
- END;
-
- CREATE TRIGGER IF NOT EXISTS subscriptions_au AFTER UPDATE ON subscriptions BEGIN
- INSERT INTO subscriptions_fts(subscriptions_fts, rowid, title, url)
- VALUES ('delete', old.rowid, old.title, old.url);
- INSERT INTO subscriptions_fts(rowid, title, url)
- VALUES (new.rowid, new.title, new.url);
- END;
-
- CREATE TABLE IF NOT EXISTS search_history (
- id TEXT PRIMARY KEY,
- query TEXT NOT NULL,
- timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
- );
-
- CREATE INDEX IF NOT EXISTS idx_search_history_timestamp ON search_history(timestamp DESC);
- `);
-
- console.log('Database initialized successfully');
- } catch (error) {
- console.error('Failed to initialize database:', error);
- throw error;
- }
-}
-
-// Helper to get database instance
-export async function getDb(): Promise {
- if (!db) await initDatabase();
- if (!db) throw new Error('Database not initialized');
- return db;
-}
-
-// Subscription CRUD
-
-export async function saveSubscription(sub: FeedSubscription): Promise {
- const database = await getDb();
-
- await database.runAsync(
- `INSERT OR REPLACE INTO subscriptions
- (id, url, title, category, enabled, fetch_interval,
- http_auth_username, http_auth_password, updated_at,
- last_fetched_at, next_fetch_at, error)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, ?, ?, ?)`,
- [
- sub.id,
- sub.url,
- sub.title,
- sub.category || null,
- sub.enabled ? 1 : 0,
- sub.fetchInterval,
- sub.httpAuth?.username || null,
- sub.httpAuth?.password || null,
- sub.lastFetchedAt?.toISOString() || null,
- sub.nextFetchAt?.toISOString() || null,
- sub.error || null,
- ]
- );
-}
-
-export async function getSubscription(id: string): Promise {
- const database = await getDb();
-
- const row = await database.getFirstAsync(
- 'SELECT * FROM subscriptions WHERE id = ?',
- [id]
- );
-
- if (!row) return null;
-
- return rowToSubscription(row);
-}
-
-export async function getAllSubscriptions(): Promise {
- const database = await getDb();
-
- const rows = await database.getAllAsync('SELECT * FROM subscriptions ORDER BY title');
- return rows.map(rowToSubscription);
-}
-
-export async function deleteSubscription(id: string): Promise {
- const database = await getDb();
-
- await database.runAsync('DELETE FROM subscriptions WHERE id = ?', [id]);
- await database.runAsync('DELETE FROM feeds WHERE subscription_id = ?', [id]);
-}
-
-// Feed Item CRUD
-
-export async function saveFeedItems(
- subscriptionId: string,
- items: FeedItem[]
-): Promise {
- const database = await getDb();
-
- const insertQuery = `
- INSERT OR REPLACE INTO feeds
- (id, subscription_id, title, link, description, author,
- published, updated, content, guid)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- `;
-
- for (const item of items) {
- await database.runAsync(insertQuery, [
- item.id,
- subscriptionId,
- item.title || null,
- item.link || null,
- item.description || null,
- item.author || null,
- item.published?.toISOString() || null,
- item.updated?.toISOString() || null,
- item.content || null,
- item.guid || null,
- ]);
- }
-}
-
-export async function getFeedItems(
- subscriptionId?: string,
- limit: number = 50,
- offset: number = 0
-): Promise {
- const database = await getDb();
-
- let query = 'SELECT f.*, s.title as subscription_title FROM feeds f '
- + 'LEFT JOIN subscriptions s ON f.subscription_id = s.id ';
-
- const params: any[] = [];
-
- if (subscriptionId) {
- query += 'WHERE f.subscription_id = ? ';
- params.push(subscriptionId);
- }
-
- query += 'ORDER BY f.published DESC LIMIT ? OFFSET ?';
- params.push(limit, offset);
-
- const rows = await database.getAllAsync(query, params);
- return rows.map(rowToFeedItem);
-}
-
-export async function getAllFeedItems(limit: number = 100, offset: number = 0): Promise {
- const database = await getDb();
-
- const rows = await database.getAllAsync(
- 'SELECT f.*, s.title as subscription_title FROM feeds f '
- + 'LEFT JOIN subscriptions s ON f.subscription_id = s.id '
- + 'ORDER BY f.published DESC LIMIT ? OFFSET ?',
- [limit, offset]
- );
- return rows.map(rowToFeedItem);
-}
-
-// Helper functions
-
-function rowToSubscription(row: any): FeedSubscription {
- return {
- id: row.id,
- url: row.url,
- title: row.title || 'Untitled',
- category: row.category,
- enabled: row.enabled === 1,
- fetchInterval: row.fetch_interval,
- httpAuth: row.http_auth_username && row.http_auth_password ? {
- username: row.http_auth_username,
- password: row.http_auth_password,
- } : undefined,
- createdAt: new Date(row.created_at),
- updatedAt: new Date(row.updated_at),
- lastFetchedAt: row.last_fetched_at ? new Date(row.last_fetched_at) : undefined,
- nextFetchAt: row.next_fetch_at ? new Date(row.next_fetch_at) : undefined,
- error: row.error,
- };
-}
-
-function rowToFeedItem(row: any): FeedItem {
- return {
- id: row.id,
- title: row.title || '',
- link: row.link,
- description: row.description,
- content: row.content,
- author: row.author,
- published: row.published ? new Date(row.published) : undefined,
- updated: row.updated ? new Date(row.updated) : undefined,
- guid: row.guid,
- subscriptionTitle: row.subscription_title,
- };
-}
-
-export async function closeDatabase(): Promise {
- if (db) {
- await db.closeAsync();
- db = null;
- }
-}
-
-// Search History Functions
-
-export async function addToSearchHistory(query: string): Promise {
- const database = await getDb();
- const id = `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
-
- await database.runAsync(
- 'INSERT OR REPLACE INTO search_history (id, query, timestamp) VALUES (?, ?, CURRENT_TIMESTAMP)',
- [id, query]
- );
-}
-
-export async function getSearchHistory(limit: number = 10): Promise<{ query: string; timestamp: string }[]> {
- const database = await getDb();
-
- const rows = await database.getAllAsync(
- 'SELECT query, timestamp FROM search_history ORDER BY timestamp DESC LIMIT ?',
- [limit]
- );
-
- return rows.map(row => ({ query: row.query, timestamp: row.timestamp }));
-}
-
-export async function clearSearchHistory(): Promise {
- const database = await getDb();
- await database.runAsync('DELETE FROM search_history');
-}
-
-export async function removeSearchHistoryItem(query: string): Promise {
- const database = await getDb();
- await database.runAsync('DELETE FROM search_history WHERE query = ?', [query]);
-}
diff --git a/src/services/feed-service.ts b/src/services/feed-service.ts
deleted file mode 100644
index beb29e5..0000000
--- a/src/services/feed-service.ts
+++ /dev/null
@@ -1,185 +0,0 @@
-import axios from 'axios';
-import { parseStringPromise } from 'xml2js';
-import { Feed, FeedItem, ParseResult, FeedSubscription } from '@/types/feed';
-
-const parseOptions = {
- explicitArray: false,
- mergeAttrs: true,
- trim: true,
-};
-
-// Feed detection
-function detectFeedType(data: string): 'rss' | 'atom' | 'unknown' {
- if (data.includes(' {
- const rss = xml.rss;
- const channel = rss?.channel;
-
- if (!channel) {
- throw new Error('Invalid RSS: No channel found');
- }
-
- // Extract iTunes namespace fields
- const itunes = channel['itunes:navigation'] || {};
- const itunesImage = itunes.image || channel['itunes:image'];
-
- const items: FeedItem[] = (channel.item || []).map((item: any) => {
- const itunesItem = item['itunes:navigation'] || {};
- const enclosure = item.enclosure?.['$'] || item.enclosure;
-
- return {
- id: item.guid?.['$']?.value || item.link || crypto.randomUUID(),
- title: item.title,
- link: item.link,
- description: item.description || itunesItem.summary,
- content: item['content:encoded'] || item.description,
- author: item.author || itunesItem.author,
- published: item.pubDate ? new Date(item.pubDate) : undefined,
- categories: item.category?.map((c: any) => c) || [],
- enclosure: enclosure ? {
- url: enclosure.url,
- type: enclosure.type,
- length: enclosure.length ? parseInt(enclosure.length) : undefined,
- } : undefined,
- guid: item.guid?.['$']?.value,
- };
- });
-
- return {
- id: crypto.randomUUID(),
- title: channel.title || 'Untitled Feed',
- link: channel.link,
- description: channel.description,
- subtitle: itunes.summary,
- language: channel.language,
- lastBuildDate: channel.lastBuildDate ? new Date(channel.lastBuildDate) : undefined,
- generator: channel.generator,
- ttl: channel.ttl ? parseInt(channel.ttl) : undefined,
- items,
- rawUrl: '',
- };
-}
-
-// Atom 1.0 Parser
-async function parseAtom(xml: any): Promise {
- const feed = xml.feed;
-
- if (!feed) {
- throw new Error('Invalid Atom: No feed found');
- }
-
- const entries: FeedItem[] = (feed.entry || []).map((entry: any) => ({
- id: entry.id?.$?.value || entry.link?.href || crypto.randomUUID(),
- title: entry.title,
- link: Array.isArray(entry.link)
- ? entry.link.find((l: any) => !l.rel)?.href
- : entry.link?.href,
- summary: entry.summary,
- content: entry.content,
- author: Array.isArray(entry.author)
- ? entry.author[0]?.name
- : entry.author?.name,
- published: entry.published ? new Date(entry.published) : undefined,
- updated: entry.updated ? new Date(entry.updated) : undefined,
- categories: (feed.category || []).map((c: any) => c.term || c),
- guid: entry.id?.$?.value,
- }));
-
- return {
- id: crypto.randomUUID(),
- title: feed.title || 'Untitled Feed',
- link: feed.link?.href,
- subtitle: feed.subtitle,
- updated: feed.updated ? new Date(feed.updated) : undefined,
- generator: feed.generator,
- items: entries,
- rawUrl: '',
- };
-}
-
-// Main parse function
-export async function parseFeed(url: string, data: string): Promise {
- try {
- const feedType = detectFeedType(data);
-
- if (feedType === 'unknown') {
- return {
- success: false,
- error: 'Could not detect feed type',
- feedType,
- };
- }
-
- const xml = await parseStringPromise(data, parseOptions);
- let feed: Feed;
-
- if (feedType === 'rss') {
- feed = await parseRSS(xml);
- } else {
- feed = await parseAtom(xml);
- }
-
- feed.rawUrl = url;
- feed.lastFetchedAt = new Date();
-
- return {
- success: true,
- feed,
- feedType,
- };
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Unknown error occurred',
- feedType: detectFeedType(data),
- };
- }
-}
-
-// Fetch feed from URL
-export async function fetchFeed(
- url: string,
- auth?: { username: string; password: string }
-): Promise {
- try {
- const config: any = {
- timeout: 15000,
- validateStatus: (status: number) => status >= 200 && status < 400,
- };
-
- if (auth) {
- config.auth = {
- username: auth.username,
- password: auth.password,
- };
- }
-
- const response = await axios.get(url, config);
- return await parseFeed(url, response.data);
- } catch (error) {
- return {
- success: false,
- error: error instanceof Error ? error.message : 'Failed to fetch feed',
- };
- }
-}
-
-// Batch fetch multiple feeds
-export async function fetchFeeds(
- subscriptions: FeedSubscription[]
-): Promise