From f7a932f8535e20df9721d45004e59c7f897e3376 Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Tue, 30 Dec 2025 22:31:58 +0100 Subject: [PATCH 01/15] Frontend-backend integration --- .../wiarygodnik/cas/model/AnalysisEntity.kt | 1 + .../cas/model/dto/AnalysisResult.kt | 1 + .../wiarygodnik/cas/security/CorsConfig.kt | 27 ++ .../cas/security/PrincipalProvider.kt | 25 ++ .../cas/service/AnalysisProcessor.kt | 10 +- .../cas/service/agent/ContentCleanerAgent.kt | 47 ++-- .../service/agent/ContentComparisonAgent.kt | 12 - .../service/agent/ContentSentimentAgent.kt | 16 -- .../agent/ContentSummarizationAgent.kt | 14 -- .../src/main/resources/application.yml | 6 + report-generation-service/build.gradle.kts | 6 +- .../rgs/controller/ReportController.kt | 16 +- .../controller/dto/ReportContentResponse.kt | 26 ++ .../controller/dto/ReportListItemResponse.kt | 3 + .../rgs/controller/dto/ReportResponse.kt | 7 - .../p/lodz/wiarygodnik/rgs/model/Report.kt | 45 +++- .../wiarygodnik/rgs/model/SimilarSource.kt | 14 ++ .../rgs/model/dto/AnalysisResult.kt | 3 +- .../rgs/model/dto/ReportGenerationResult.kt | 3 + .../wiarygodnik/rgs/repo/ReportRepository.kt | 4 +- .../wiarygodnik/rgs/security/CorsConfig.kt | 27 ++ .../KeycloakJwtAuthenticationConverter.kt | 26 ++ .../rgs/security/PrincipalProvider.kt | 25 ++ .../rgs/security/SecurityConfig.kt | 35 +++ .../rgs/service/AiAnalysisReportGenerator.kt | 8 +- .../wiarygodnik/rgs/service/ReportService.kt | 42 ++-- .../src/main/resources/application.yml | 8 +- .../analysis_report_generation_system.txt | 30 +-- wiarygodnik_frontend/.env | 6 +- .../.vite/deps/_metadata.json | 8 + wiarygodnik_frontend/.vite/deps/package.json | 3 + wiarygodnik_frontend/package.json | 2 + wiarygodnik_frontend/pnpm-lock.yaml | 211 ++++++++++++++++ wiarygodnik_frontend/src/App.tsx | 11 +- .../components/reports/NewReportButton.tsx | 21 ++ .../src/components/reports/ReportContent.tsx | 76 ++++++ .../components/reports/ReportCredability.tsx | 42 ++++ .../src/components/reports/ReportList.tsx | 63 +++++ .../components/reports/ReportListButton.tsx | 26 ++ .../src/components/reports/ReportLoading.tsx | 21 ++ .../src/components/reports/ReportSearch.tsx | 39 +++ .../reports/domain/AnalysisStatus.ts | 8 + .../src/components/toast/ToastProvider.tsx | 23 ++ .../src/hooks/useAnalyseSource.ts | 13 + .../src/hooks/useAnalysisStatus.ts | 57 +++++ wiarygodnik_frontend/src/hooks/useReport.ts | 20 ++ .../src/hooks/useReportList.ts | 18 ++ wiarygodnik_frontend/src/http/analysis.api.ts | 31 +++ wiarygodnik_frontend/src/http/report.api.ts | 48 ++++ wiarygodnik_frontend/src/navbar/NavBar.tsx | 7 +- wiarygodnik_frontend/src/pages/Home.tsx | 2 +- wiarygodnik_frontend/src/pages/Raports.tsx | 231 ------------------ wiarygodnik_frontend/src/pages/Reports.tsx | 45 ++++ wiarygodnik_frontend/src/pages/User.tsx | 2 +- .../src/routing/AppRouter.tsx | 6 +- .../src/routing/ProtectedRoutes.tsx | 2 +- .../{ => shared}/context/KeycloakContext.tsx | 5 +- .../src/shared/hooks/useHttpClient.ts | 45 ++++ .../hooks/useKeycloak.ts} | 0 59 files changed, 1219 insertions(+), 360 deletions(-) create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/PrincipalProvider.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportListItemResponse.kt delete mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportResponse.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/KeycloakJwtAuthenticationConverter.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/PrincipalProvider.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt create mode 100644 wiarygodnik_frontend/.vite/deps/_metadata.json create mode 100644 wiarygodnik_frontend/.vite/deps/package.json create mode 100644 wiarygodnik_frontend/src/components/reports/NewReportButton.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/ReportContent.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/ReportCredability.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/ReportList.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/ReportListButton.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/ReportLoading.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/ReportSearch.tsx create mode 100644 wiarygodnik_frontend/src/components/reports/domain/AnalysisStatus.ts create mode 100644 wiarygodnik_frontend/src/components/toast/ToastProvider.tsx create mode 100644 wiarygodnik_frontend/src/hooks/useAnalyseSource.ts create mode 100644 wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts create mode 100644 wiarygodnik_frontend/src/hooks/useReport.ts create mode 100644 wiarygodnik_frontend/src/hooks/useReportList.ts create mode 100644 wiarygodnik_frontend/src/http/analysis.api.ts create mode 100644 wiarygodnik_frontend/src/http/report.api.ts delete mode 100644 wiarygodnik_frontend/src/pages/Raports.tsx create mode 100644 wiarygodnik_frontend/src/pages/Reports.tsx rename wiarygodnik_frontend/src/{ => shared}/context/KeycloakContext.tsx (89%) create mode 100644 wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts rename wiarygodnik_frontend/src/{hooks/useKeycloak.tsx => shared/hooks/useKeycloak.ts} (100%) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt index b0a1c19..ab11d5a 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt @@ -12,6 +12,7 @@ enum class AnalysisStatus { class AnalysisEntity( @Id @GeneratedValue(strategy = IDENTITY) var id: Long = 0, val requestId: String = "", + val userId: String = "", var sourceUrl: String = "", @Enumerated(EnumType.STRING) var status: AnalysisStatus = ANALYSING_CONTENT, ) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt index 100f286..8b88747 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt @@ -2,6 +2,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.model.dto data class AnalysisResult( val requestId: String, + val userId: String, val sourceUrl: String, val contentAnalysis: ContentAnalysis, val contentComparison: ContentComparison diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt new file mode 100644 index 0000000..cbeecd8 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt @@ -0,0 +1,27 @@ +package pl.edu.p.lodz.wiarygodnik.cas.security + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.CorsConfigurationSource +import org.springframework.web.cors.UrlBasedCorsConfigurationSource + +@Configuration +class CorsConfig { + + @Bean + fun corsConfigurationSource(): CorsConfigurationSource { + val configuration = CorsConfiguration() + configuration.allowedOrigins = listOf("http://localhost:5173") + configuration.allowedMethods = listOf("*") + configuration.allowedHeaders = listOf("*") + configuration.exposedHeaders = listOf("*") + configuration.allowCredentials = true + configuration.maxAge = 3600L + + val source = UrlBasedCorsConfigurationSource() + source.registerCorsConfiguration("/**", configuration) + return source + } + +} \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/PrincipalProvider.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/PrincipalProvider.kt new file mode 100644 index 0000000..323ad81 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/PrincipalProvider.kt @@ -0,0 +1,25 @@ +package pl.edu.p.lodz.wiarygodnik.cas.security + +import org.springframework.security.core.Authentication +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.oauth2.jwt.Jwt + +object PrincipalProvider { + + fun getCurrentUserId(): String { + val authentication: Authentication = SecurityContextHolder.getContext().authentication + ?: throw IllegalStateException("User not authenticated") + + if (!authentication.isAuthenticated) { + throw IllegalStateException("User not authenticated") + } + + val principal = authentication.principal + if (principal !is Jwt) { + throw IllegalStateException("Authentication principal is not Jwt: ${principal::class.qualifiedName}") + } + + return principal.subject + } + +} \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt index 5598cd1..9b96084 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt @@ -15,6 +15,7 @@ import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentComparison import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ScrapedWebContent import pl.edu.p.lodz.wiarygodnik.cas.repository.AnalysisRepository +import pl.edu.p.lodz.wiarygodnik.cas.security.PrincipalProvider import pl.edu.p.lodz.wiarygodnik.cas.service.analyser.ContentAnalyser import pl.edu.p.lodz.wiarygodnik.cas.service.comparator.ContentComparator import pl.edu.p.lodz.wiarygodnik.cas.service.scraper.WebScraper @@ -48,6 +49,7 @@ class AnalysisProcessor( private fun prepareNewAnalysis(url: String) = AnalysisEntity( requestId = UUID.randomUUID().toString(), + userId = PrincipalProvider.getCurrentUserId(), sourceUrl = url, status = ANALYSING_CONTENT ) @@ -69,7 +71,13 @@ class AnalysisProcessor( ) switchAnalysisStatus(analysisEntity, COMPLETED) - val result = AnalysisResult(analysisEntity.requestId, analysisEntity.sourceUrl, analysis, comparison) + val result = AnalysisResult( + analysisEntity.requestId, + analysisEntity.userId, + analysisEntity.sourceUrl, + analysis, + comparison + ) log.info { "Analysis process finished. Sending result for report generation. [analysisId: ${analysisEntity.id}, requestId: ${analysisEntity.requestId}]" } producer.sendAnalysis(result) } catch (e: Exception) { diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentCleanerAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentCleanerAgent.kt index bcf67b9..d2b71bc 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentCleanerAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentCleanerAgent.kt @@ -7,31 +7,42 @@ import pl.edu.p.lodz.wiarygodnik.cas.model.dto.CleanedContent @Component class ContentCleanerAgent(chatModel: ChatModel) : AbstractAgent(chatModel, CleanedContent::class.java) { override fun systemPrompt(): String = """ - Jesteś systemem czyszczącym treści wyciągnięte ze stron internetowych. Otrzymasz surowy tekst z kodem HTML oraz elementami niezwiązanymi z główną treścią (np. menu, stopki, reklamy, komentarze, polecane treści, komunikaty systemowe itp.). - + Jesteś systemem czyszczącym treści wyciągnięte ze stron internetowych. Otrzymasz surowy tekst wyciągnięty ze strony internetowej (bez tagów HTML, jako innerText/innerHTML) zawierający również elementy niezwiązane z główną treścią (np. menu, stopki, reklamy, komunikaty systemowe itp.). + Twoim zadaniem jest wyodrębnienie wyłącznie właściwej treści merytorycznej artykułu/tekstu oraz wykonanie następujących kroków **bez zmiany języka i treści zdań**: - - 1. **Czyszczenie i filtracja treści** - - Usuń wszystkie tagi HTML, znaczniki formatowania, fragmenty skryptów, style oraz inne techniczne elementy kodu. - - Usuń elementy funkcjonalne strony: menu nawigacyjne, stopki, boczne panele, przyciski, bannery, komunikaty o cookies, formularze, przyciski „zaloguj”, „zapisz się do newslettera”, „zaakceptuj”, „wybierz język” itp. + + 1. **Czyszczenie, filtracja i heurystyczne przycięcie treści** + - Usuń wszystkie pozostałe znaczniki techniczne, artefakty renderowania, fragmenty skryptów, style oraz elementy niefunkcjonalne. + - Usuń elementy funkcjonalne strony: menu nawigacyjne, stopki, boczne panele, przyciski, bannery, komunikaty systemowe, formularze, CTA. + - Usuń WSZELKIE treści związane z wyrażaniem zgody lub brakiem zgody na przetwarzanie danych, w tym w szczególności: + komunikaty o cookies, RODO, prywatności, zgodach marketingowych, śledzeniu użytkownika, personalizacji treści, + prośby typu „zaakceptuj”, „odrzuć”, „zarządzaj zgodami”, „ustawienia prywatności”, „kontynuując akceptujesz”, + nawet jeśli są zapisane jako pełne zdania lub część akapitu. - Usuń treści typu: regulaminy, polityka prywatności, prawa autorskie, informacje kontaktowe, sekcje „zobacz także”, „polecane artykuły”, komentarze użytkowników. - - Usuń listy linków, bloki z odnośnikami, podpisy techniczne, elementy nawigacyjne („następna strona”, „poprzednia strona” itp.). + - Usuń listy linków, bloki z odnośnikami, podpisy techniczne oraz elementy nawigacyjne („następna strona”, „poprzednia strona” itp.). + - **Heurystyczne przycięcie treści:** + - Jeśli początek tekstu zawiera ogólne elementy strony (nazwa serwisu, slogany, menu, logowanie, wybór języka, informacje o cookies), + usuń CAŁY tekst aż do pierwszego fragmentu, który wyraźnie rozpoczyna treść artykułu (np. tytuł, lead, pierwszy akapit merytoryczny). + - Jeśli koniec tekstu zawiera sekcje niemerytoryczne, usuń CAŁY tekst od pierwszego wystąpienia takich markerów jak: + „Related”, „Recommended”, „See also”, „Zobacz także”, „Polecane”, „Czytaj także”, „More articles”, + „Share”, „Udostępnij”, „Comments”, „Komentarze”, „Subscribe”, „Newsletter”, „Sign up”, „Follow us”. + - Nie próbuj rekonstruować, zgadywać ani dopisywać brakującej treści – wolno jedynie usuwać całe fragmenty. + 2. **Zachowanie oryginalnych zdań** - - Pozostaw wyłącznie zdania, które odnoszą się bezpośrednio do głównej treści/motywacji tekstu (np. artykułu, opisu, wpisu). + - Pozostaw wyłącznie zdania, które odnoszą się bezpośrednio do głównej treści/motywu tekstu. - **Nie zmieniaj języka tekstu** – jeśli tekst jest po angielsku, pozostaje po angielsku; jeśli po polsku, pozostaje po polsku itd. - - **Nie modyfikuj zdań w żaden sposób**: nie skracaj, nie parafrazuj, nie poprawiaj stylu, nie poprawiaj błędów językowych, nie zmieniaj interpunkcji ani szyku. Zdania mają być **identyczne jak w oryginalnym tekście**, jedynie odfiltrowane z otoczenia. + - **Nie modyfikuj zdań w żaden sposób**: nie skracaj, nie parafrazuj, nie poprawiaj stylu, nie poprawiaj błędów językowych, nie zmieniaj interpunkcji ani szyku. - Możesz jedynie usuwać całe, niepotrzebne fragmenty; nie wolno ingerować wewnątrz pojedynczego zdania. - 3. **Struktura wynikowego tekstu** - - Zadbaj, aby wynik zawierał tylko spójne, pełne zdania dotyczące głównej treści. - - Usuń nadmiarowe puste linie i zbędne białe znaki, ale nie łącz kilku oryginalnych zdań w jedno. - - Nie dodawaj żadnych komentarzy, podsumowań ani metadanych – zwróć wyłącznie oczyszczony tekst. - - Wynik ma być tylko samymi zdaniami, nie dodawaj żadnych nawiasów pod JSON, ani nic podobnego. - - ### Format odpowiedzi - Zwróć wynik dokładnie w następującym formacie: + 3. **Format wyjścia – krytyczne** + - Wynik MUSI być JEDNĄ linią tekstu. + - **NIE używaj znaków nowej linii (`\n`, `\r`) ani tabulatorów (`\t`)**. + - Oryginalne zdania oddzielaj **pojedynczą spacją**. + - Usuń nadmiarowe białe znaki, pozostawiając dokładnie jedną spację między zdaniami. + - **Nie dodawaj żadnych komentarzy, nagłówków, podsumowań ani metadanych**. + - Zwróć wyłącznie oczyszczony tekst, bez JSON-a, bez markdowna, bez dodatkowego formatowania. - [tu wklej oczyszczony tekst, składający się wyłącznie z oryginalnych zdań związanych z główną treścią] + Treści dotyczące zgód, cookies, RODO, prywatności i przetwarzania danych osobowych NIGDY nie są uznawane za część treści merytorycznej i MUSZĄ zostać usunięte w całości. """.trimIndent() } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentComparisonAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentComparisonAgent.kt index 64a07b2..9142cd1 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentComparisonAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentComparisonAgent.kt @@ -46,17 +46,5 @@ class ContentComparisonAgent(chatModel: ChatModel) : - Nie wypisuj żadnych URL‑i ani informacji, które nie mają wyraźnego powiązania z treścią GŁÓWNEGO ŹRÓDŁA. - Nie oceniaj wiarygodności źródeł – opisuj wyłącznie to, czy i jak ich treść **potwierdza, uzupełnia lub neguje** informacje z GŁÓWNEGO ŹRÓDŁA. - Nie dodawaj treści ani faktów spoza otrzymanych podsumowań. - - ### FORMAT ODPOWIEDZI: - - OPIS OGÓLNY: - [krótkie podsumowanie zgodności/rozbieżności między źródłami względem GŁÓWNEGO ŹRÓDŁA] - - PORÓWNANIE ŹRÓDEŁ: - - url1 – [które informacje z GŁÓWNEGO ŹRÓDŁA potwierdza / częściowo potwierdza / uzupełnia / neguje i w jaki sposób] - - url2 – [które informacje z GŁÓWNEGO ŹRÓDŁA potwierdza / częściowo potwierdza / uzupełnia / neguje i w jaki sposób] - - url3 – [...] - - Nie dodawaj nic ponad ten format i nie używaj innych języków niż polski. """.trimIndent() } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt index 01a483b..9f86762 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt @@ -38,21 +38,5 @@ class ContentSentimentAgent(chatModel: ChatModel) : - perswazyjny - PERSUASIVE, - agresywny - AGGRESSIVE, - formalny - FORMAL. - - ### FORMAT ODPOWIEDZI: - - NACECHOWANIE GŁÓWNE: - [krótki opis ogólnego tonu tekstu] - - LISTA NACECHOWAŃ Z PRZYKŁADAMI: - - [rodzaj nacechowania 1] - - "[cytat 1]" – [krótki komentarz] - - "[cytat 2]" – [krótki komentarz] - - [rodzaj nacechowania 2] - - "[cytat 1]" – [krótki komentarz] - - "[cytat 2]" – [krótki komentarz] - - [...] - - Nie dodawaj nic ponad ten format i nie używaj innych języków niż polski. """.trimIndent() } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt index ca6c3d8..0b70e64 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt @@ -27,19 +27,5 @@ class ContentSummarizationAgent(chatModel: ChatModel) : - Bierz pod uwagę tylko właściwą treść artykułu. - Ignoruj wszelkie fragmenty niezwiązane z artykułem. - Wszystkie odpowiedzi muszą być **w języku polskim**. - - ### Format odpowiedzi - Zwróć wynik w następującym formacie: - - PODSUMOWANIE: - [tu podsumowanie] - - SŁOWA KLUCZOWE: - - słowo1 - - słowo2 - - słowo3 - [...] - - Nie dodawaj nic ponad ten format i nie używaj innych języków. """.trimIndent() } \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/application.yml b/content-analysis-service/src/main/resources/application.yml index 7684957..9067817 100644 --- a/content-analysis-service/src/main/resources/application.yml +++ b/content-analysis-service/src/main/resources/application.yml @@ -2,6 +2,12 @@ spring: application: name: content-analysis-service + security: + oauth2: + resource-server: + jwt: + issuer-uri: http://localhost:8888/realms/wiarygodnik + rabbitmq: host: localhost port: 5672 diff --git a/report-generation-service/build.gradle.kts b/report-generation-service/build.gradle.kts index 95bf6af..f037099 100644 --- a/report-generation-service/build.gradle.kts +++ b/report-generation-service/build.gradle.kts @@ -26,13 +26,15 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-amqp") implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-security") + implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") + implementation("org.springframework.boot:spring-boot-starter-actuator") + implementation("org.springframework.boot:spring-boot-starter-logging") implementation("org.springframework.ai:spring-ai-starter-model-ollama") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("io.github.oshai:kotlin-logging-jvm:5.1.0") implementation("net.logstash.logback:logstash-logback-encoder:7.4") - implementation("org.springframework.boot:spring-boot-starter-actuator") - implementation("org.springframework.boot:spring-boot-starter-logging") runtimeOnly("org.postgresql:postgresql") diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt index ec1f623..b69b8e8 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt @@ -4,7 +4,8 @@ import org.springframework.http.HttpStatus import org.springframework.http.ProblemDetail import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* -import pl.edu.p.lodz.wiarygodnik.rgs.controller.dto.ReportResponse +import pl.edu.p.lodz.wiarygodnik.rgs.controller.dto.ReportContentResponse +import pl.edu.p.lodz.wiarygodnik.rgs.controller.dto.ReportListItemResponse import pl.edu.p.lodz.wiarygodnik.rgs.controller.dto.ReportStatusResponse import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus @@ -15,10 +16,17 @@ import pl.edu.p.lodz.wiarygodnik.rgs.service.ReportService @RequestMapping("/api/report") class ReportController(val reportService: ReportService) { + @GetMapping + fun getMyAllReports(): ResponseEntity> { + val reports: List = reportService.findAllReportsForCurrentUser() + val response = reports.map { ReportListItemResponse(it.requestId, it.title) } + return ResponseEntity.ok(response) + } + @GetMapping("/{requestId}") - fun getReport(@PathVariable requestId: String): ResponseEntity { - val report: Report = reportService.getReportContent(requestId) - val response = ReportResponse(requestId, report.sourceUrl, report.content) + fun getMyReport(@PathVariable requestId: String): ResponseEntity { + val report: Report = reportService.findReportByRequestId(requestId) + val response = ReportContentResponse.from(report) return ResponseEntity.ok(response) } diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt new file mode 100644 index 0000000..2594c3d --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt @@ -0,0 +1,26 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.controller.dto + +import pl.edu.p.lodz.wiarygodnik.rgs.model.CredibilityLevel +import pl.edu.p.lodz.wiarygodnik.rgs.model.Report + +data class ReportContentResponse( + val requestId: String, + val sourceUrl: String, + val title: String, + val credibilityLevel: CredibilityLevel, + val content: String, + val similarSourceUrls: List +) { + companion object { + fun from(report: Report): ReportContentResponse { + return ReportContentResponse( + requestId = report.requestId, + sourceUrl = report.sourceUrl, + title = report.title, + credibilityLevel = report.credibilityLevel, + content = report.content, + similarSourceUrls = report.similarSources.map { it.sourceUrl } + ) + } + } +} \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportListItemResponse.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportListItemResponse.kt new file mode 100644 index 0000000..8f4b7fb --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportListItemResponse.kt @@ -0,0 +1,3 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.controller.dto + +data class ReportListItemResponse(val requestId: String, val title: String) diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportResponse.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportResponse.kt deleted file mode 100644 index 8c0310c..0000000 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportResponse.kt +++ /dev/null @@ -1,7 +0,0 @@ -package pl.edu.p.lodz.wiarygodnik.rgs.controller.dto - -data class ReportResponse( - val requestId: String, - val sourceUrl: String, - val content: String -) \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt index 6d01963..8368268 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt @@ -2,21 +2,54 @@ package pl.edu.p.lodz.wiarygodnik.rgs.model import jakarta.persistence.* import jakarta.persistence.GenerationType.IDENTITY +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult enum class ReportStatus { - GENERATING, GENERATED + GENERATING, GENERATED, FAILED +} + +enum class CredibilityLevel { + HIGH, MEDIUM, LOW } @Entity class Report( @Id @GeneratedValue(strategy = IDENTITY) var id: Long = 0, - var requestId: String = "", - var sourceUrl: String = "", - @Enumerated(EnumType.STRING) var status: ReportStatus = ReportStatus.GENERATING, + @Version var version: Long = 0, + var requestId: String, + var userId: String, + var sourceUrl: String, + @Enumerated(EnumType.STRING) var status: ReportStatus, + var title: String = "Not generated yet", + @Enumerated(EnumType.STRING) var credibilityLevel: CredibilityLevel, @Lob @Column(columnDefinition = "TEXT") var content: String = "Not generated yet", + @OneToMany( + cascade = [CascadeType.ALL], + mappedBy = "report" + ) var similarSources: MutableList = ArrayList() ) { - fun fillWithGeneratedContent(generatedContent: String) { - this.content = generatedContent + + companion object { + fun fromAnalysisResult(analysisResult: AnalysisResult): Report { + val initialReport = Report( + requestId = analysisResult.requestId, + userId = analysisResult.userId, + sourceUrl = analysisResult.sourceUrl, + credibilityLevel = CredibilityLevel.MEDIUM, + status = ReportStatus.GENERATING + ) + initialReport.similarSources = analysisResult.contentComparison.sourcesFacts + .map { SimilarSource(sourceUrl = it.url, report = initialReport) } + .toMutableList() + return initialReport + } + } + + fun fillWithGeneratedContent(reportGenerationResult: ReportGenerationResult) { + this.title = reportGenerationResult.title + this.content = reportGenerationResult.content this.status = ReportStatus.GENERATED } + } \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt new file mode 100644 index 0000000..0589f4e --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt @@ -0,0 +1,14 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.model + +import jakarta.persistence.* +import jakarta.persistence.GenerationType.IDENTITY + +@Entity +class SimilarSource( + @Id @GeneratedValue(strategy = IDENTITY) var id: Long = 0, + @Version var version: Long = 0, + var sourceUrl: String = "", + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "report_id") + var report: Report? = null, +) \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt index 506ca7e..739bf27 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt @@ -6,9 +6,10 @@ enum class Sentiment { data class AnalysisResult( val requestId: String, + val userId: String, val sourceUrl: String, val contentAnalysis: ContentAnalysis, - val contentComparison: ContentComparison + val contentComparison: ContentComparison, ) data class ContentAnalysis(val summarization: ContentSummarization, val sentiment: ContentSentiment) diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt new file mode 100644 index 0000000..7e31080 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt @@ -0,0 +1,3 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.model.dto + +data class ReportGenerationResult(val title: String, val content: String) diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt index d28bac7..1ae30ba 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt @@ -3,8 +3,10 @@ package pl.edu.p.lodz.wiarygodnik.rgs.repo import org.springframework.data.jpa.repository.JpaRepository import org.springframework.transaction.annotation.Transactional import pl.edu.p.lodz.wiarygodnik.rgs.model.Report +import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus @Transactional interface ReportRepository : JpaRepository { - fun findReportByRequestId(requestId: String): Report? + fun findReportByRequestIdAndUserIdAndStatus(requestId: String, userId: String, status: ReportStatus): Report? + fun findAllByUserIdAndStatus(userId: String, status: ReportStatus): List } \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt new file mode 100644 index 0000000..230ad6c --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt @@ -0,0 +1,27 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.security + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.cors.CorsConfiguration +import org.springframework.web.cors.CorsConfigurationSource +import org.springframework.web.cors.UrlBasedCorsConfigurationSource + +@Configuration +class CorsConfig { + + @Bean + fun corsConfigurationSource(): CorsConfigurationSource { + val configuration = CorsConfiguration() + configuration.allowedOrigins = listOf("http://localhost:5173") + configuration.allowedMethods = listOf("*") + configuration.allowedHeaders = listOf("*") + configuration.exposedHeaders = listOf("*") + configuration.allowCredentials = true + configuration.maxAge = 3600L + + val source = UrlBasedCorsConfigurationSource() + source.registerCorsConfiguration("/**", configuration) + return source + } + +} \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/KeycloakJwtAuthenticationConverter.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/KeycloakJwtAuthenticationConverter.kt new file mode 100644 index 0000000..2888134 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/KeycloakJwtAuthenticationConverter.kt @@ -0,0 +1,26 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.security + +import org.springframework.core.convert.converter.Converter +import org.springframework.security.authentication.AbstractAuthenticationToken +import org.springframework.security.core.GrantedAuthority +import org.springframework.security.core.authority.SimpleGrantedAuthority +import org.springframework.security.oauth2.jwt.Jwt +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken + +class KeycloakJwtAuthenticationConverter : Converter { + + override fun convert(source: Jwt): AbstractAuthenticationToken { + val authorities = (extractRealmRoles(source)).toSet() + return JwtAuthenticationToken(source, authorities) + } + + private fun extractRealmRoles(jwt: Jwt): Collection { + val realmAccess = jwt.claims["realm_access"] as? Map<*, *> ?: return emptyList() + val roles = realmAccess["roles"] as? Collection<*> ?: return emptyList() + + return roles + .filterIsInstance() + .map { SimpleGrantedAuthority("ROLE_${it.replace("-", "_").uppercase()}") } + } + +} diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/PrincipalProvider.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/PrincipalProvider.kt new file mode 100644 index 0000000..5528193 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/PrincipalProvider.kt @@ -0,0 +1,25 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.security + +import org.springframework.security.core.Authentication +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.oauth2.jwt.Jwt + +object PrincipalProvider { + + fun getCurrentUserId(): String { + val authentication: Authentication = SecurityContextHolder.getContext().authentication + ?: throw IllegalStateException("User not authenticated") + + if (!authentication.isAuthenticated) { + throw IllegalStateException("User not authenticated") + } + + val principal = authentication.principal + if (principal !is Jwt) { + throw IllegalStateException("Authentication principal is not Jwt: ${principal::class.qualifiedName}") + } + + return principal.subject + } + +} \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt new file mode 100644 index 0000000..f77b318 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt @@ -0,0 +1,35 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.security + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.security.config.annotation.web.builders.HttpSecurity +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity +import org.springframework.security.config.annotation.web.invoke +import org.springframework.security.config.http.SessionCreationPolicy.STATELESS +import org.springframework.security.web.SecurityFilterChain + +@Configuration +@EnableWebSecurity +class SecurityConfig { + + @Bean + fun securityFilterChain(http: HttpSecurity): SecurityFilterChain { + http { + cors { } + csrf { disable() } + authorizeHttpRequests { + authorize("/api/report/**", hasRole("USER")) + } + oauth2ResourceServer { + jwt { + jwtAuthenticationConverter = KeycloakJwtAuthenticationConverter() + } + } + sessionManagement { + sessionCreationPolicy = STATELESS + } + } + return http.build() + } + +} \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt index aa40ee3..0219be6 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt @@ -4,23 +4,25 @@ import org.springframework.ai.chat.client.ChatClient import org.springframework.ai.chat.model.ChatModel import org.springframework.core.io.ResourceLoader import org.springframework.stereotype.Component +import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult @Component class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader: ResourceLoader) { private val chatClient = ChatClient.create(chatModel) - fun generate(input: AnalysisResult): String { + fun generate(input: AnalysisResult): ReportGenerationResult { val analysisReportGenerationPrompt: String = prepareAnalysisReportGenerationPrompt(input) return callChatGeneration(analysisReportGenerationPrompt) } - private fun callChatGeneration(input: String): String = chatClient.prompt() + private fun callChatGeneration(input: String): ReportGenerationResult = chatClient.prompt() .system { system -> system.text(readSystemPrompt()) } .user { user -> user.text(input) } .call() - .content() + .entity(ReportGenerationResult::class.java) ?: throw RuntimeException("LLM returned a null object while generating a report.") private fun readSystemPrompt(): String = diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt index 3b85e0f..8fd8d6e 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt @@ -4,8 +4,12 @@ import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Service import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus +import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.FAILED +import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.GENERATED import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult import pl.edu.p.lodz.wiarygodnik.rgs.repo.ReportRepository +import pl.edu.p.lodz.wiarygodnik.rgs.security.PrincipalProvider @Service class ReportService( @@ -16,28 +20,36 @@ class ReportService( private val log = KotlinLogging.logger {} fun createReport(analysisResult: AnalysisResult) { - val newReport = prepareInitialReport(analysisResult) + val newReport = Report.fromAnalysisResult(analysisResult) val persistedReport = reportRepository.save(newReport) log.info { "Initial report persisted to database [reportId: ${persistedReport.id}, requestId: ${analysisResult.requestId}]" } - log.info { "Generating report... [reportId: ${persistedReport.id}, requestId: ${analysisResult.requestId}]" } - val generatedReport = analysisReportGenerator.generate(analysisResult) - persistedReport.fillWithGeneratedContent(generatedReport) - reportRepository.save(persistedReport) - log.info { "Report generated successfully and persisted to databse [reportId: ${persistedReport.id}], requestId: ${analysisResult.requestId}" } + try { + log.info { "Generating report... [reportId: ${persistedReport.id}, requestId: ${analysisResult.requestId}]" } + val reportGenerationResult: ReportGenerationResult = analysisReportGenerator.generate(analysisResult) + persistedReport.fillWithGeneratedContent(reportGenerationResult) + reportRepository.save(persistedReport) + log.info { "Report generated successfully and persisted to database [reportId: ${persistedReport.id}], requestId: ${analysisResult.requestId}" } + } catch (e: Exception) { + log.error(e) { "Generating report failed" } + persistedReport.status = FAILED + reportRepository.save(persistedReport) + } } - private fun prepareInitialReport(analysisResult: AnalysisResult): Report = - Report( - requestId = analysisResult.requestId, - sourceUrl = analysisResult.sourceUrl - ) + fun getReportStatus(requestId: String): ReportStatus { + return findReportByRequestId(requestId).status + } - fun getReportContent(requestId: String): Report = - reportRepository.findReportByRequestId(requestId) ?: throw NoSuchElementException("Report not found") + fun findReportByRequestId(requestId: String): Report { + val currentUserId = PrincipalProvider.getCurrentUserId() + return reportRepository.findReportByRequestIdAndUserIdAndStatus(requestId, currentUserId, GENERATED) + ?: throw NoSuchElementException("Report not found") + } - fun getReportStatus(requestId: String): ReportStatus { - return getReportContent(requestId).status + fun findAllReportsForCurrentUser(): List { + val currentUserId = PrincipalProvider.getCurrentUserId() + return reportRepository.findAllByUserIdAndStatus(currentUserId, GENERATED) } } \ No newline at end of file diff --git a/report-generation-service/src/main/resources/application.yml b/report-generation-service/src/main/resources/application.yml index d6b3489..b0d620d 100644 --- a/report-generation-service/src/main/resources/application.yml +++ b/report-generation-service/src/main/resources/application.yml @@ -2,6 +2,12 @@ spring: application: name: report-generation-service + security: + oauth2: + resource-server: + jwt: + issuer-uri: http://localhost:8888/realms/wiarygodnik + rabbitmq: host: localhost port: 5672 @@ -23,7 +29,7 @@ spring: model: "gpt-oss" server: - port: 8081 + port: 8082 logging: logstash: diff --git a/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt b/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt index dc6e1f9..bd0798a 100644 --- a/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt +++ b/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt @@ -1,23 +1,25 @@ -Jesteś systemem generującym zwięzłe, informacyjne podsumowania na podstawie analizy nacechowania tekstu (z przykładami) oraz porównania innych źródeł z oryginalnym. +Jesteś systemem generującym zwięzłe, informacyjne raporty na podstawie analizy nacechowania tekstu (z przykładami) oraz porównania innych źródeł z oryginalnym tekstem. Otrzymasz: - szczegółową analizę nacechowania tekstu (z opisem ogólnego tonu oraz przykładami cytatów wraz z komentarzami), -- wynik porównania kilku źródeł (opis zgodności/rozbieżności pomiędzy źródłami oraz wskazania, które informacje zostały potwierdzone, uzupełnione lub zanegowane przez konkretne źródła). +- wynik porównania kilku źródeł (opis zgodności i rozbieżności pomiędzy źródłami oraz wskazania, które informacje zostały potwierdzone, uzupełnione lub zanegowane przez konkretne źródła). Twoje zadanie: -1. **Wygeneruj krótkie podsumowanie** (3-6 zdań), które: - - jasno i treściwie opisuje ogólne nacechowanie tekstu oraz jego wpływ na odbiór i wiarygodność treści, - - wskazuje, czy oraz które cechy nacechowania mają odzwierciedlenie w analizie porównawczej z innymi źródłami, - - informuje, czy informacje przedstawione w tekście są potwierdzane, uzupełniane, czy kwestionowane przez źródła porównawcze, - - zawiera rzeczowe wnioski dotyczące spójności przekazu i możliwej wiarygodności treści. - -2. **Nie kopiuj pełnych cytatów ani fragmentów z analizy** – prezentuj wnioski własnymi słowami na bazie dostarczonych analiz. -3. **Nie oceniaj wiarygodności na podstawie osobistych sądów** – odnoś się wyłącznie do konkluzji z analizy nacechowania i relacji z porównania źródeł. +1. **Wygeneruj tytuł raportu**, który: + - składa się z **maksymalnie 5 słów**, + - opisuje **wyłącznie temat oryginalnego źródła**, bez odniesień do analizy, tonu, wiarygodności ani porównań, + - jest neutralny, rzeczowy i informacyjny, + - nie zawiera ocen, emocji, sensacji ani sugestii wniosków, + - nie używa pytań ani trybu rozkazującego, + - użyj tylko języka polskiego. -### Format odpowiedzi +2. **Wygeneruj krótkie podsumowanie** (3–6 zdań), które: + - jasno i treściwie opisuje ogólne nacechowanie tekstu oraz jego wpływ na odbiór i potencjalną wiarygodność treści, + - wskazuje, czy oraz które cechy nacechowania mają odzwierciedlenie w analizie porównawczej z innymi źródłami, + - informuje, czy informacje przedstawione w tekście są potwierdzane, uzupełniane czy kwestionowane przez źródła porównawcze, + - zawiera rzeczowe wnioski dotyczące spójności przekazu i możliwej wiarygodności treści, wyłącznie w oparciu o dostarczone analizy. -RAPORT Z ANALIZY: -[tu spójne, konkretne i zwięzłe streszczenie wniosków] +3. **Nie kopiuj pełnych cytatów ani fragmentów z analizy** – prezentuj wnioski własnymi słowami na podstawie dostarczonych danych. -Nie dodawaj nic ponad ten format i nie używaj innych języków niż polski. \ No newline at end of file +4. **Nie oceniaj wiarygodności na podstawie osobistych sądów** – odnoś się wyłącznie do konkluzji wynikających z analizy nacechowania oraz porównania źródeł. diff --git a/wiarygodnik_frontend/.env b/wiarygodnik_frontend/.env index 931a29c..f41fbd1 100644 --- a/wiarygodnik_frontend/.env +++ b/wiarygodnik_frontend/.env @@ -1,3 +1,7 @@ VITE_KEYCLOAK_URL=http://localhost:8888/ VITE_KEYCLOAK_REALM=wiarygodnik -VITE_KEYCLOAK_CLIENT=wiarygodnik-ui \ No newline at end of file +VITE_KEYCLOAK_CLIENT=wiarygodnik-ui + +VITE_CONTENT_ANALYSIS_SERVICE_API_URL=http://localhost:8080/ +VITE_CREADABILITY_SCORING_SERVICE_API_URL=http://localhost:8081/ +VITE_REPORT_GENERATION_SERVICE_API_URL=http://localhost:8082/ \ No newline at end of file diff --git a/wiarygodnik_frontend/.vite/deps/_metadata.json b/wiarygodnik_frontend/.vite/deps/_metadata.json new file mode 100644 index 0000000..64b6049 --- /dev/null +++ b/wiarygodnik_frontend/.vite/deps/_metadata.json @@ -0,0 +1,8 @@ +{ + "hash": "b43932ff", + "configHash": "6b0e13ae", + "lockfileHash": "6722e362", + "browserHash": "c97e7a96", + "optimized": {}, + "chunks": {} +} \ No newline at end of file diff --git a/wiarygodnik_frontend/.vite/deps/package.json b/wiarygodnik_frontend/.vite/deps/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/wiarygodnik_frontend/.vite/deps/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/wiarygodnik_frontend/package.json b/wiarygodnik_frontend/package.json index 4fe6e75..b8e074d 100644 --- a/wiarygodnik_frontend/package.json +++ b/wiarygodnik_frontend/package.json @@ -10,7 +10,9 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.13.2", "keycloak-js": "^26.2.1", + "notistack": "^3.0.2", "react": "^19.2.0", "react-dom": "^19.2.0" }, diff --git a/wiarygodnik_frontend/pnpm-lock.yaml b/wiarygodnik_frontend/pnpm-lock.yaml index e62b30f..6f74b42 100644 --- a/wiarygodnik_frontend/pnpm-lock.yaml +++ b/wiarygodnik_frontend/pnpm-lock.yaml @@ -8,9 +8,15 @@ importers: .: dependencies: + axios: + specifier: ^1.13.2 + version: 1.13.2 keycloak-js: specifier: ^26.2.1 version: 26.2.1 + notistack: + specifier: ^3.0.2 + version: 3.0.2(csstype@3.2.3)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react: specifier: ^19.2.0 version: 19.2.1 @@ -775,6 +781,12 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -797,6 +809,10 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -808,6 +824,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -819,6 +839,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -851,15 +875,39 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + electron-to-chromium@1.5.266: resolution: {integrity: sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==} error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -962,6 +1010,19 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -974,6 +1035,14 @@ packages: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -986,6 +1055,15 @@ packages: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} + goober@2.1.18: + resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} + peerDependencies: + csstype: ^3.0.10 + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -993,6 +1071,14 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -1096,6 +1182,18 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -1117,6 +1215,13 @@ packages: node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + notistack@3.0.2: + resolution: {integrity: sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==} + engines: {node: '>=12.0.0', npm: '>=6.0.0'} + peerDependencies: + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -1174,6 +1279,9 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -2060,6 +2168,16 @@ snapshots: argparse@2.0.1: {} + asynckit@0.4.0: {} + + axios@1.13.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.28.4 @@ -2087,6 +2205,11 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.2(browserslist@4.28.1) + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + callsites@3.1.0: {} caniuse-lite@1.0.30001759: {} @@ -2096,6 +2219,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + clsx@1.2.1: {} + clsx@2.1.1: {} color-convert@2.0.1: @@ -2104,6 +2229,10 @@ snapshots: color-name@1.1.4: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + concat-map@0.0.1: {} convert-source-map@1.9.0: {} @@ -2132,17 +2261,40 @@ snapshots: deep-is@0.1.4: {} + delayed-stream@1.0.0: {} + dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.28.4 csstype: 3.2.3 + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + electron-to-chromium@1.5.266: {} error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -2285,6 +2437,16 @@ snapshots: flatted@3.3.3: {} + follow-redirects@1.15.11: {} + + 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.35 + fsevents@2.3.3: optional: true @@ -2292,6 +2454,24 @@ snapshots: gensync@1.0.0-beta.2: {} + 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 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -2300,10 +2480,22 @@ snapshots: globals@16.5.0: {} + goober@2.1.18(csstype@3.2.3): + dependencies: + csstype: 3.2.3 + + gopd@1.2.0: {} + graphemer@1.4.0: {} has-flag@4.0.0: {} + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -2388,6 +2580,14 @@ snapshots: dependencies: yallist: 3.1.1 + math-intrinsics@1.1.0: {} + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -2404,6 +2604,15 @@ snapshots: node-releases@2.0.27: {} + notistack@3.0.2(csstype@3.2.3)(react-dom@19.2.1(react@19.2.1))(react@19.2.1): + dependencies: + clsx: 1.2.1 + goober: 2.1.18(csstype@3.2.3) + react: 19.2.1 + react-dom: 19.2.1(react@19.2.1) + transitivePeerDependencies: + - csstype + object-assign@4.1.1: {} optionator@0.9.4: @@ -2460,6 +2669,8 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + proxy-from-env@1.1.0: {} + punycode@2.3.1: {} react-dom@19.2.1(react@19.2.1): diff --git a/wiarygodnik_frontend/src/App.tsx b/wiarygodnik_frontend/src/App.tsx index 1312460..cb347f2 100644 --- a/wiarygodnik_frontend/src/App.tsx +++ b/wiarygodnik_frontend/src/App.tsx @@ -1,11 +1,14 @@ -import { KeycloakProvider } from './context/KeycloakContext.tsx'; +import { ToastProvider } from './components/toast/ToastProvider.tsx'; +import { KeycloakProvider } from './shared/context/KeycloakContext.tsx'; import AppRouter from './routing/AppRouter.tsx'; function App() { return ( - - - + + + + + ); } diff --git a/wiarygodnik_frontend/src/components/reports/NewReportButton.tsx b/wiarygodnik_frontend/src/components/reports/NewReportButton.tsx new file mode 100644 index 0000000..c8107c6 --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/NewReportButton.tsx @@ -0,0 +1,21 @@ +import Button from "@mui/material/Button"; +import { sideMenuButton } from "../../Style.tsx"; +import { useNavigate } from "react-router-dom"; + +export const NewReportButton = () => { + const navigate = useNavigate(); + + const handleClick = () => { + navigate(`/reports`); + } + + return ( + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/ReportContent.tsx b/wiarygodnik_frontend/src/components/reports/ReportContent.tsx new file mode 100644 index 0000000..1d94969 --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/ReportContent.tsx @@ -0,0 +1,76 @@ +import { Box, Link, Typography } from "@mui/material"; +import { useTheme } from "@mui/material/styles"; +import useMediaQuery from "@mui/material/useMediaQuery"; +import LightbulbIcon from '@mui/icons-material/Lightbulb'; +import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; +import CircleIcon from '@mui/icons-material/Circle'; +import { getDomain } from "../../common/Scripts.tsx"; +import { sourceDot, sourceLink } from "../../Style.tsx"; +import type { ReportContentResponse } from "../../http/report.api.ts"; +import { ReportCredability } from "./ReportCredability.tsx"; + +interface ReportContentProps { + report?: ReportContentResponse; +} + +export const ReportContent = ({ report }: ReportContentProps) => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + + if (!report) { + return <>; + } + + const analyzedSource = report.sourceUrl; + const similarSourceUrls = report.similarSourceUrls; + const reportTitle = report.title; + const reportContent = report.content; + const reportCreadabilityLevel = report.credibilityLevel; + + return ( + + + + + + + {reportTitle} + + + + + Analizowane źródło + + + + + {getDomain(analyzedSource)} + + + + + + + Znalezione źródła + + { + similarSourceUrls.map((source, index) => ( + + + + {getDomain(source)} + + + )) + } + + + + Raport + + {reportContent} + + + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/ReportCredability.tsx b/wiarygodnik_frontend/src/components/reports/ReportCredability.tsx new file mode 100644 index 0000000..9916ad7 --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/ReportCredability.tsx @@ -0,0 +1,42 @@ +import type { ReportCreadabilityLevel } from "../../http/report.api"; +import ErrorIcon from '@mui/icons-material/Error'; +import CancelIcon from '@mui/icons-material/Cancel'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import { Typography } from "@mui/material"; + +interface ReportCredabilityProps { + creadability: ReportCreadabilityLevel; +} + +export const ReportCredability = ({ creadability }: ReportCredabilityProps) => { + let color = ""; + let content: React.ReactNode; + + const iconStyle = { alignSelf: "center", fontSize: "2rem", marginRight: "5px" }; + + switch (creadability) { + case "HIGH": + color = "#8dff5d"; + content = <> Źródło wiarygodne; + break; + case "MEDIUM": + color = "#faff5d"; + content = <> Źródło częściowo wiarygodne; + break; + case "LOW": + color = "#ff5d5d"; + content = <> Źródło niewiarygodne; + break; + default: + color = "gray"; + content = <>Unknown; + } + + const typographyStyle = { display: "flex", fontWeight: "bold", fontSize: "1.6rem", color: color }; + + return ( + + {content} + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/ReportList.tsx b/wiarygodnik_frontend/src/components/reports/ReportList.tsx new file mode 100644 index 0000000..096df83 --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/ReportList.tsx @@ -0,0 +1,63 @@ +import { Box, CircularProgress, Typography } from "@mui/material"; +import ArticleIcon from '@mui/icons-material/Article'; +import Divider from "@mui/material/Divider"; +import { useTheme } from "@mui/material/styles"; +import useMediaQuery from "@mui/material/useMediaQuery"; +import { ReportListButton } from "./ReportListButton.tsx"; +import { useReportsList } from "../../hooks/useReportList.ts"; +import { NewReportButton } from "./NewReportButton.tsx"; + + +export const ReportList = () => { + const theme = useTheme(); + const isMobile = useMediaQuery(theme.breakpoints.down("sm")); + + const { reports, loading } = useReportsList(); + + return ( + + + {loading ? + + : + <> + + + Raporty + + + + + {reports.map((report, index) => )} + + + } + + + ); +}; \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/ReportListButton.tsx b/wiarygodnik_frontend/src/components/reports/ReportListButton.tsx new file mode 100644 index 0000000..7cc31f7 --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/ReportListButton.tsx @@ -0,0 +1,26 @@ +import Button from "@mui/material/Button"; +import { sideMenuButton } from "../../Style.tsx"; +import { useNavigate } from "react-router-dom"; + +interface ReportListButtonProps { + reportTitle: string; + requestId: string; +} + +export const ReportListButton = ({ reportTitle, requestId }: ReportListButtonProps) => { + const navigate = useNavigate(); + + const handleClick = () => { + navigate(`/reports/${requestId}`); + } + + return ( + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/ReportLoading.tsx b/wiarygodnik_frontend/src/components/reports/ReportLoading.tsx new file mode 100644 index 0000000..fe8d3d6 --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/ReportLoading.tsx @@ -0,0 +1,21 @@ +import { Box, CircularProgress, Typography } from "@mui/material"; +import theme from "../../theme"; + +interface ReportLoadingProps { + loadingStatus?: string; +} + +export const ReportLoading = ({ loadingStatus }: ReportLoadingProps) => { + return ( + + + + {loadingStatus} + + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/ReportSearch.tsx b/wiarygodnik_frontend/src/components/reports/ReportSearch.tsx new file mode 100644 index 0000000..8ae64dd --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/ReportSearch.tsx @@ -0,0 +1,39 @@ +import { Box, Button, Input, Typography } from "@mui/material"; +import theme from "../../theme.ts"; +import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined'; +import { useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { useAnalyseSource } from "../../hooks/useAnalyseSource.ts"; + +export const ReportSearch = () => { + const navigate = useNavigate(); + + const { startAnalysis } = useAnalyseSource(); + + const [sourceUrl, setSourceUrl] = useState(""); + + const handleSearch = async () => { + navigator.vibrate?.(200); + const requestId = await startAnalysis(sourceUrl); + navigate(`/reports/${requestId}`); + }; + + return ( + <> + + + + Podaj źródło, żeby sprawdzić jego wiarygodność + + + + setSourceUrl(e.target.value)} + placeholder="Podaj źródło" disableUnderline={true} + sx={{ fontWeight: "light", fontSize: "1.2rem", padding: "10px", width: "100%" }} /> + + + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/reports/domain/AnalysisStatus.ts b/wiarygodnik_frontend/src/components/reports/domain/AnalysisStatus.ts new file mode 100644 index 0000000..2400b9c --- /dev/null +++ b/wiarygodnik_frontend/src/components/reports/domain/AnalysisStatus.ts @@ -0,0 +1,8 @@ +export const AnalysisStatus = { + ANALYSISNG_CONTENT: 'ANALYSING_CONTENT', + COMPARING_SIMILAR_SOURCES: 'COMPARING_SIMILAR_SOURCES', + COMPLETED: 'COMPLETED', + GENERATING: 'GENERATING', + GENERATED: 'GENERATED', + FAILED: 'FAILED' +}; \ No newline at end of file diff --git a/wiarygodnik_frontend/src/components/toast/ToastProvider.tsx b/wiarygodnik_frontend/src/components/toast/ToastProvider.tsx new file mode 100644 index 0000000..6478ae1 --- /dev/null +++ b/wiarygodnik_frontend/src/components/toast/ToastProvider.tsx @@ -0,0 +1,23 @@ +import { Button } from '@mui/material'; +import ClearIcon from '@mui/icons-material/Clear'; +import { closeSnackbar, SnackbarProvider } from 'notistack'; + +interface ToastProviderProps { + children: React.ReactNode; +} + +export const ToastProvider = ({ children }: ToastProviderProps) => ( + ( + + )} + > + {children} + +); diff --git a/wiarygodnik_frontend/src/hooks/useAnalyseSource.ts b/wiarygodnik_frontend/src/hooks/useAnalyseSource.ts new file mode 100644 index 0000000..006bfc2 --- /dev/null +++ b/wiarygodnik_frontend/src/hooks/useAnalyseSource.ts @@ -0,0 +1,13 @@ +import { useAnalysisApi, type AnalyseResponse } from "../http/analysis.api"; + +export const useAnalyseSource = () => { + const { analyseSource } = useAnalysisApi(); + + const startAnalysis = async (url: string) => { + const response: AnalyseResponse = await analyseSource({ url }); + return response.requestId; + }; + + return { startAnalysis }; +}; + diff --git a/wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts b/wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts new file mode 100644 index 0000000..4085a8c --- /dev/null +++ b/wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts @@ -0,0 +1,57 @@ +import { useEffect, useState } from 'react'; +import { useAnalysisApi, type AnalysisStatusResponse } from '../http/analysis.api'; +import { useReportApi, type ReportStatusResponse } from '../http/report.api'; +import { AnalysisStatus } from "../components/reports/domain/AnalysisStatus.ts"; + +export const useAnalysisStatus = (requestId: string | undefined) => { + const { getAnalysisStatus } = useAnalysisApi(); + const { getMyReportStatus } = useReportApi(); + + const [status, setStatus] = useState(undefined); + + useEffect(() => { + if (!requestId) { + setStatus(undefined); + return; + }; + + let active = true; + + const poll = async () => { + let firstCheck = true; + let analysisCompleted: boolean = false; + while (active) { + if (!analysisCompleted) { + const res: AnalysisStatusResponse = await getAnalysisStatus(requestId); + setStatus(res.status); + if (res.status === AnalysisStatus.COMPLETED) { + analysisCompleted = true; + } else if (res.status === AnalysisStatus.FAILED) { + break; + } + } else { + const reportRes: ReportStatusResponse = await getMyReportStatus(requestId); + setStatus(reportRes.status); + if (reportRes.status === AnalysisStatus.GENERATED) { + break; + } else if (reportRes.status === AnalysisStatus.FAILED) { + break; + } + } + + if (firstCheck) { + firstCheck = false; + } else { + await new Promise(resolve => setTimeout(resolve, 2000)); + } + } + }; + + poll(); + return () => { + active = false; + }; + }, [requestId]); + + return status; +}; diff --git a/wiarygodnik_frontend/src/hooks/useReport.ts b/wiarygodnik_frontend/src/hooks/useReport.ts new file mode 100644 index 0000000..b3d3b70 --- /dev/null +++ b/wiarygodnik_frontend/src/hooks/useReport.ts @@ -0,0 +1,20 @@ +import { useEffect, useState } from 'react'; +import { useReportApi, type ReportContentResponse } from '../http/report.api'; +import { AnalysisStatus } from "../components/reports/domain/AnalysisStatus.ts"; + +export const useReport = (requestId: string | undefined, status: string | undefined) => { + const { getMyReport } = useReportApi(); + + const [report, setReport] = useState(undefined); + + useEffect(() => { + if (!requestId || (status !== AnalysisStatus.GENERATED)) { + setReport(undefined); + return; + } + + getMyReport(requestId).then(setReport); + }, [requestId, status]); + + return report; +}; diff --git a/wiarygodnik_frontend/src/hooks/useReportList.ts b/wiarygodnik_frontend/src/hooks/useReportList.ts new file mode 100644 index 0000000..f2859e7 --- /dev/null +++ b/wiarygodnik_frontend/src/hooks/useReportList.ts @@ -0,0 +1,18 @@ +import { useEffect, useState } from 'react'; +import { useReportApi, type ReportListItemResponse } from '../http/report.api'; + +export const useReportsList = () => { + const { getAllMyReports } = useReportApi(); + + const [reports, setReports] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + getAllMyReports() + .then(setReports) + .finally(() => setLoading(false)); + }, []); + + return { reports, loading }; +}; + diff --git a/wiarygodnik_frontend/src/http/analysis.api.ts b/wiarygodnik_frontend/src/http/analysis.api.ts new file mode 100644 index 0000000..f732a1c --- /dev/null +++ b/wiarygodnik_frontend/src/http/analysis.api.ts @@ -0,0 +1,31 @@ +import { useHttpClient } from '../shared/hooks/useHttpClient'; + +export interface AnalyseRequest { + url: string; +} + +export interface AnalyseResponse { + requestId: string; +} + +export interface AnalysisStatusResponse { + status: string; +} + +const API_ANALYSIS_PATH = '/api/analysis'; + +export const useAnalysisApi = () => { + const http = useHttpClient(import.meta.env.VITE_CONTENT_ANALYSIS_SERVICE_API_URL); + + const analyseSource = async (payload: AnalyseRequest): Promise => { + const response = await http.post(`${API_ANALYSIS_PATH}/process`, payload); + return response.data; + }; + + const getAnalysisStatus = async (requestId: string): Promise => { + const response = await http.get(`${API_ANALYSIS_PATH}/status/${requestId}`); + return response.data; + }; + + return { analyseSource, getAnalysisStatus }; +}; diff --git a/wiarygodnik_frontend/src/http/report.api.ts b/wiarygodnik_frontend/src/http/report.api.ts new file mode 100644 index 0000000..a46421a --- /dev/null +++ b/wiarygodnik_frontend/src/http/report.api.ts @@ -0,0 +1,48 @@ +import { useHttpClient } from "../shared/hooks/useHttpClient"; + +export type ReportCreadabilityLevel = "HIGH" | "MEDIUM" | "LOW"; + +export interface ReportListItemResponse { + requestId: string; + title: string; +} + +export interface ReportContentResponse { + requestId: string; + title: string; + sourceUrl: string; + credibilityLevel: ReportCreadabilityLevel; + content: string; + similarSourceUrls: string[]; +} + +export interface ReportStatusResponse { + status: string; +} + +export interface ReportStatusResponse { + status: string; +} + +const API_REPORT_PATH = '/api/report'; + +export const useReportApi = () => { + const http = useHttpClient(import.meta.env.VITE_REPORT_GENERATION_SERVICE_API_URL); + + const getAllMyReports = async (): Promise => { + const response = await http.get(`${API_REPORT_PATH}`); + return response.data; + }; + + const getMyReport = async (requestId: string): Promise => { + const response = await http.get(`${API_REPORT_PATH}/${requestId}`); + return response.data; + }; + + const getMyReportStatus = async (requestId: string): Promise => { + const response = await http.get(`${API_REPORT_PATH}/status/${requestId}`); + return response.data; + }; + + return { getAllMyReports, getMyReport, getMyReportStatus }; +}; \ No newline at end of file diff --git a/wiarygodnik_frontend/src/navbar/NavBar.tsx b/wiarygodnik_frontend/src/navbar/NavBar.tsx index 21b57b4..6094bc4 100644 --- a/wiarygodnik_frontend/src/navbar/NavBar.tsx +++ b/wiarygodnik_frontend/src/navbar/NavBar.tsx @@ -1,11 +1,11 @@ import { useIsMobile } from "../common/UseIsMobile.tsx"; -import { Box, Button, Typography, AppBar, Toolbar } from "@mui/material"; +import { Box, Button, AppBar, Toolbar } from "@mui/material"; import logo from "/logo_full_350_80.png"; import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined'; import MenuOutlinedIcon from '@mui/icons-material/MenuOutlined'; import theme from "../theme.ts"; import { useLocation, useNavigate } from "react-router-dom"; -import useKeycloak from "../hooks/useKeycloak.tsx"; +import useKeycloak from "../shared/hooks/useKeycloak.ts"; type NavBarProps = { menuActive: boolean | undefined; @@ -41,10 +41,11 @@ function NavBar(props: NavBarProps) { px: isMobile ? 0 : 4 }}> - {!authenticated || location.pathname !== "/raports" ? null : + {authenticated && location.pathname.startsWith("/reports") ? ( + ) : null } diff --git a/wiarygodnik_frontend/src/pages/Home.tsx b/wiarygodnik_frontend/src/pages/Home.tsx index c76fe05..5ee2711 100644 --- a/wiarygodnik_frontend/src/pages/Home.tsx +++ b/wiarygodnik_frontend/src/pages/Home.tsx @@ -20,7 +20,7 @@ export const Home = () => { - ))} - - - - ); - } - - function content() { - return ( - - - - {mapResult()} - - - {titleOfReport} - - - - - Analizowane źródło - - - - - {getDomain(analyzedSource)} - - - - - - - Znalezione źródła - - { - foundSource.map((source, index) => ( - - - - {getDomain(source)} - - - )) - } - - - - Raport - - Zawartość raportu. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. . Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. - - - - ) - } - - return ( - <> - - - - {isMobile ? - <> - {menuActive && sideMenu()} - - : - <> - {menuActive && sideMenu()} - - } - - - {isContentLoaded ? - content() - : - isContentLoading ? - - - - {loadingStatus} - - - : - - - - Podaj źródło, żeby sprawdzić jego wiarygodność - - - } - - setValue(e.target.value)} - placeholder="Podaj źródło" disableUnderline={true} - sx={{fontWeight: "light", fontSize: "1.2rem", padding: "10px", width: "100%"}} /> - - - - - - - ) -} - -export default Raports; diff --git a/wiarygodnik_frontend/src/pages/Reports.tsx b/wiarygodnik_frontend/src/pages/Reports.tsx new file mode 100644 index 0000000..5f10b15 --- /dev/null +++ b/wiarygodnik_frontend/src/pages/Reports.tsx @@ -0,0 +1,45 @@ +import NavBar from "../navbar/NavBar.tsx"; +import { Box } from "@mui/material"; +import { useEffect, useState } from "react"; +import { useIsMobile } from "../common/UseIsMobile.tsx"; +import { useNavigate, useParams } from "react-router-dom"; +import { useAnalysisStatus } from "../hooks/useAnalysisStatus.ts"; +import { useReport } from "../hooks/useReport.ts"; +import { ReportList } from "../components/reports/ReportList.tsx"; +import { ReportSearch } from "../components/reports/ReportSearch.tsx"; +import { ReportContent } from "../components/reports/ReportContent.tsx"; +import { ReportLoading } from "../components/reports/ReportLoading.tsx"; +import { enqueueSnackbar } from "notistack"; +import { AnalysisStatus } from "../components/reports/domain/AnalysisStatus.ts"; + +function Reports() { + const isMobile = useIsMobile(); + const navigate = useNavigate(); + + const { requestId } = useParams(); + const status = useAnalysisStatus(requestId); + const report = useReport(requestId, status); + + const [menuActive, setMenuActive] = useState(!isMobile); + + useEffect(() => { + if (status === AnalysisStatus.FAILED) { + enqueueSnackbar('Analiza nie powiodła się. Spróbuj ponownie.', { variant: 'error' }); + navigate('/reports'); + } + }, [status]); + + return ( + <> + + + {menuActive && } + + {report ? : status ? : } + + + + ) +} + +export default Reports; diff --git a/wiarygodnik_frontend/src/pages/User.tsx b/wiarygodnik_frontend/src/pages/User.tsx index 523e582..bd88dc3 100644 --- a/wiarygodnik_frontend/src/pages/User.tsx +++ b/wiarygodnik_frontend/src/pages/User.tsx @@ -6,7 +6,7 @@ import LogoutIcon from '@mui/icons-material/Logout'; import { userPageButton, userPageButtonIcon, userPageButtonText, userPageDivider } from "../Style.tsx"; import InfoIcon from '@mui/icons-material/Info'; import SettingsIcon from '@mui/icons-material/Settings'; -import useKeycloak from "../hooks/useKeycloak.tsx"; +import useKeycloak from "../shared/hooks/useKeycloak.ts"; function User() { const { keycloak } = useKeycloak(); diff --git a/wiarygodnik_frontend/src/routing/AppRouter.tsx b/wiarygodnik_frontend/src/routing/AppRouter.tsx index 40fc3f2..dc0207d 100644 --- a/wiarygodnik_frontend/src/routing/AppRouter.tsx +++ b/wiarygodnik_frontend/src/routing/AppRouter.tsx @@ -1,5 +1,5 @@ import { Routes, Route, BrowserRouter } from "react-router-dom"; -import Raports from "../pages/Raports"; +import Reports from "../pages/Reports"; import ProtectedRoutes from "./ProtectedRoutes"; import NotFound from "../pages/NotFound"; import User from "../pages/User"; @@ -11,7 +11,9 @@ export default function AppRouter() { } /> }> - } /> + }> + } /> + } /> } /> diff --git a/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx b/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx index 9426e4b..a87ec5d 100644 --- a/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx +++ b/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Outlet } from "react-router-dom"; -import useKeycloak from "../hooks/useKeycloak"; +import useKeycloak from "../shared/hooks/useKeycloak"; import AccessDenied from "../pages/AccessDenied"; import Loading from "../pages/Loading"; diff --git a/wiarygodnik_frontend/src/context/KeycloakContext.tsx b/wiarygodnik_frontend/src/shared/context/KeycloakContext.tsx similarity index 89% rename from wiarygodnik_frontend/src/context/KeycloakContext.tsx rename to wiarygodnik_frontend/src/shared/context/KeycloakContext.tsx index fa30b3f..d53b6df 100644 --- a/wiarygodnik_frontend/src/context/KeycloakContext.tsx +++ b/wiarygodnik_frontend/src/shared/context/KeycloakContext.tsx @@ -31,7 +31,10 @@ const KeycloakProvider: React.FC = ({ children }) => { keycloakInstance .init({ onLoad: 'check-sso' }) - .then((authenticated: boolean) => setAuthenticated(authenticated)) + .then((authenticated: boolean) => { + setAuthenticated(authenticated); + localStorage.setItem('token', keycloakInstance.token || ''); + }) .catch((error) => { console.error('Keycloak initialization failed:', error); setAuthenticated(false); diff --git a/wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts b/wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts new file mode 100644 index 0000000..63cea13 --- /dev/null +++ b/wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts @@ -0,0 +1,45 @@ +import { useMemo } from 'react'; +import axios, { HttpStatusCode, type AxiosInstance } from 'axios'; +import { enqueueSnackbar } from 'notistack'; +import useKeycloak from './useKeycloak'; + +export const useHttpClient = (baseURL: string): AxiosInstance => { + const { keycloak, authenticated } = useKeycloak(); + + return useMemo(() => { + const instance = axios.create({ + baseURL, + withCredentials: true, + }); + + instance.interceptors.request.use((config) => { + const token = keycloak?.token; + if (token) config.headers.Authorization = `Bearer ${token}`; + return config; + }); + + instance.interceptors.response.use( + (res) => res, + async (err) => { + const status = err.response?.status; + + if (status === HttpStatusCode.Unauthorized) { + try { + if (keycloak && await keycloak.updateToken()) { + return instance(err.config); // retry request + } + } catch { + keycloak?.login(); + } + + return Promise.reject(err); + } + + enqueueSnackbar(err.message || 'Wystąpił błąd', { variant: 'error' }); + return Promise.reject(err); + } + ); + + return instance; + }, [keycloak, authenticated, baseURL]); +}; diff --git a/wiarygodnik_frontend/src/hooks/useKeycloak.tsx b/wiarygodnik_frontend/src/shared/hooks/useKeycloak.ts similarity index 100% rename from wiarygodnik_frontend/src/hooks/useKeycloak.tsx rename to wiarygodnik_frontend/src/shared/hooks/useKeycloak.ts From 821f703a3587bc02c16c80b9351fdbf7c0ff1f9f Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Tue, 30 Dec 2025 23:54:49 +0100 Subject: [PATCH 02/15] Change files structure for frontend project --- wiarygodnik_frontend/src/App.tsx | 4 ++-- .../auth}/context/KeycloakContext.tsx | 0 .../auth}/hooks/useKeycloak.ts | 0 .../report/api}/analysis.api.ts | 2 +- .../report/api}/report.api.ts | 2 +- .../report/components}/NewReportButton.tsx | 2 +- .../report/components}/ReportContent.tsx | 6 +++--- .../report/components}/ReportCredability.tsx | 2 +- .../report/components}/ReportList.tsx | 2 +- .../report/components}/ReportListButton.tsx | 2 +- .../report/components}/ReportLoading.tsx | 2 +- .../report/components}/ReportSearch.tsx | 4 ++-- .../report}/domain/AnalysisStatus.ts | 0 .../report}/hooks/useAnalyseSource.ts | 2 +- .../report}/hooks/useAnalysisStatus.ts | 6 +++--- .../{ => features/report}/hooks/useReport.ts | 4 ++-- .../report}/hooks/useReportList.ts | 2 +- .../src/{shared => }/hooks/useHttpClient.ts | 2 +- .../UseIsMobile.tsx => hooks/useIsMobile.ts} | 0 .../src/{navbar => layout}/NavBar.tsx | 4 ++-- .../toast => layout}/ToastProvider.tsx | 0 .../Scripts.tsx => lib/domainExtractor.ts} | 0 .../src/pages/AccessDenied.tsx | 2 +- wiarygodnik_frontend/src/pages/Home.tsx | 4 ++-- wiarygodnik_frontend/src/pages/NotFound.tsx | 2 +- wiarygodnik_frontend/src/pages/Reports.tsx | 18 +++++++++--------- wiarygodnik_frontend/src/pages/User.tsx | 4 ++-- .../src/routing/ProtectedRoutes.tsx | 2 +- 28 files changed, 40 insertions(+), 40 deletions(-) rename wiarygodnik_frontend/src/{shared => features/auth}/context/KeycloakContext.tsx (100%) rename wiarygodnik_frontend/src/{shared => features/auth}/hooks/useKeycloak.ts (100%) rename wiarygodnik_frontend/src/{http => features/report/api}/analysis.api.ts (93%) rename wiarygodnik_frontend/src/{http => features/report/api}/report.api.ts (95%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/NewReportButton.tsx (89%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/ReportContent.tsx (95%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/ReportCredability.tsx (94%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/ReportList.tsx (97%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/ReportListButton.tsx (91%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/ReportLoading.tsx (95%) rename wiarygodnik_frontend/src/{components/reports => features/report/components}/ReportSearch.tsx (94%) rename wiarygodnik_frontend/src/{components/reports => features/report}/domain/AnalysisStatus.ts (100%) rename wiarygodnik_frontend/src/{ => features/report}/hooks/useAnalyseSource.ts (78%) rename wiarygodnik_frontend/src/{ => features/report}/hooks/useAnalysisStatus.ts (91%) rename wiarygodnik_frontend/src/{ => features/report}/hooks/useReport.ts (75%) rename wiarygodnik_frontend/src/{ => features/report}/hooks/useReportList.ts (83%) rename wiarygodnik_frontend/src/{shared => }/hooks/useHttpClient.ts (95%) rename wiarygodnik_frontend/src/{common/UseIsMobile.tsx => hooks/useIsMobile.ts} (100%) rename wiarygodnik_frontend/src/{navbar => layout}/NavBar.tsx (95%) rename wiarygodnik_frontend/src/{components/toast => layout}/ToastProvider.tsx (100%) rename wiarygodnik_frontend/src/{common/Scripts.tsx => lib/domainExtractor.ts} (100%) diff --git a/wiarygodnik_frontend/src/App.tsx b/wiarygodnik_frontend/src/App.tsx index cb347f2..a786f19 100644 --- a/wiarygodnik_frontend/src/App.tsx +++ b/wiarygodnik_frontend/src/App.tsx @@ -1,5 +1,5 @@ -import { ToastProvider } from './components/toast/ToastProvider.tsx'; -import { KeycloakProvider } from './shared/context/KeycloakContext.tsx'; +import { ToastProvider } from './layout/ToastProvider.tsx'; +import { KeycloakProvider } from './features/auth/context/KeycloakContext.tsx'; import AppRouter from './routing/AppRouter.tsx'; function App() { diff --git a/wiarygodnik_frontend/src/shared/context/KeycloakContext.tsx b/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx similarity index 100% rename from wiarygodnik_frontend/src/shared/context/KeycloakContext.tsx rename to wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx diff --git a/wiarygodnik_frontend/src/shared/hooks/useKeycloak.ts b/wiarygodnik_frontend/src/features/auth/hooks/useKeycloak.ts similarity index 100% rename from wiarygodnik_frontend/src/shared/hooks/useKeycloak.ts rename to wiarygodnik_frontend/src/features/auth/hooks/useKeycloak.ts diff --git a/wiarygodnik_frontend/src/http/analysis.api.ts b/wiarygodnik_frontend/src/features/report/api/analysis.api.ts similarity index 93% rename from wiarygodnik_frontend/src/http/analysis.api.ts rename to wiarygodnik_frontend/src/features/report/api/analysis.api.ts index f732a1c..75110dc 100644 --- a/wiarygodnik_frontend/src/http/analysis.api.ts +++ b/wiarygodnik_frontend/src/features/report/api/analysis.api.ts @@ -1,4 +1,4 @@ -import { useHttpClient } from '../shared/hooks/useHttpClient'; +import { useHttpClient } from '../../../hooks/useHttpClient'; export interface AnalyseRequest { url: string; diff --git a/wiarygodnik_frontend/src/http/report.api.ts b/wiarygodnik_frontend/src/features/report/api/report.api.ts similarity index 95% rename from wiarygodnik_frontend/src/http/report.api.ts rename to wiarygodnik_frontend/src/features/report/api/report.api.ts index a46421a..215e33e 100644 --- a/wiarygodnik_frontend/src/http/report.api.ts +++ b/wiarygodnik_frontend/src/features/report/api/report.api.ts @@ -1,4 +1,4 @@ -import { useHttpClient } from "../shared/hooks/useHttpClient"; +import { useHttpClient } from "../../../hooks/useHttpClient"; export type ReportCreadabilityLevel = "HIGH" | "MEDIUM" | "LOW"; diff --git a/wiarygodnik_frontend/src/components/reports/NewReportButton.tsx b/wiarygodnik_frontend/src/features/report/components/NewReportButton.tsx similarity index 89% rename from wiarygodnik_frontend/src/components/reports/NewReportButton.tsx rename to wiarygodnik_frontend/src/features/report/components/NewReportButton.tsx index c8107c6..70abcc1 100644 --- a/wiarygodnik_frontend/src/components/reports/NewReportButton.tsx +++ b/wiarygodnik_frontend/src/features/report/components/NewReportButton.tsx @@ -1,5 +1,5 @@ import Button from "@mui/material/Button"; -import { sideMenuButton } from "../../Style.tsx"; +import { sideMenuButton } from "../../../Style.tsx"; import { useNavigate } from "react-router-dom"; export const NewReportButton = () => { diff --git a/wiarygodnik_frontend/src/components/reports/ReportContent.tsx b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx similarity index 95% rename from wiarygodnik_frontend/src/components/reports/ReportContent.tsx rename to wiarygodnik_frontend/src/features/report/components/ReportContent.tsx index 1d94969..db630a7 100644 --- a/wiarygodnik_frontend/src/components/reports/ReportContent.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx @@ -4,9 +4,9 @@ import useMediaQuery from "@mui/material/useMediaQuery"; import LightbulbIcon from '@mui/icons-material/Lightbulb'; import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; import CircleIcon from '@mui/icons-material/Circle'; -import { getDomain } from "../../common/Scripts.tsx"; -import { sourceDot, sourceLink } from "../../Style.tsx"; -import type { ReportContentResponse } from "../../http/report.api.ts"; +import { getDomain } from "../../../lib/domainExtractor.ts"; +import { sourceDot, sourceLink } from "../../../Style.tsx"; +import type { ReportContentResponse } from "../api/report.api.ts"; import { ReportCredability } from "./ReportCredability.tsx"; interface ReportContentProps { diff --git a/wiarygodnik_frontend/src/components/reports/ReportCredability.tsx b/wiarygodnik_frontend/src/features/report/components/ReportCredability.tsx similarity index 94% rename from wiarygodnik_frontend/src/components/reports/ReportCredability.tsx rename to wiarygodnik_frontend/src/features/report/components/ReportCredability.tsx index 9916ad7..a404b51 100644 --- a/wiarygodnik_frontend/src/components/reports/ReportCredability.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportCredability.tsx @@ -1,4 +1,4 @@ -import type { ReportCreadabilityLevel } from "../../http/report.api"; +import type { ReportCreadabilityLevel } from "../api/report.api"; import ErrorIcon from '@mui/icons-material/Error'; import CancelIcon from '@mui/icons-material/Cancel'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; diff --git a/wiarygodnik_frontend/src/components/reports/ReportList.tsx b/wiarygodnik_frontend/src/features/report/components/ReportList.tsx similarity index 97% rename from wiarygodnik_frontend/src/components/reports/ReportList.tsx rename to wiarygodnik_frontend/src/features/report/components/ReportList.tsx index 096df83..b7082db 100644 --- a/wiarygodnik_frontend/src/components/reports/ReportList.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportList.tsx @@ -4,7 +4,7 @@ import Divider from "@mui/material/Divider"; import { useTheme } from "@mui/material/styles"; import useMediaQuery from "@mui/material/useMediaQuery"; import { ReportListButton } from "./ReportListButton.tsx"; -import { useReportsList } from "../../hooks/useReportList.ts"; +import { useReportsList } from "../hooks/useReportList.ts"; import { NewReportButton } from "./NewReportButton.tsx"; diff --git a/wiarygodnik_frontend/src/components/reports/ReportListButton.tsx b/wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx similarity index 91% rename from wiarygodnik_frontend/src/components/reports/ReportListButton.tsx rename to wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx index 7cc31f7..ad81bc5 100644 --- a/wiarygodnik_frontend/src/components/reports/ReportListButton.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx @@ -1,5 +1,5 @@ import Button from "@mui/material/Button"; -import { sideMenuButton } from "../../Style.tsx"; +import { sideMenuButton } from "../../../Style.tsx"; import { useNavigate } from "react-router-dom"; interface ReportListButtonProps { diff --git a/wiarygodnik_frontend/src/components/reports/ReportLoading.tsx b/wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx similarity index 95% rename from wiarygodnik_frontend/src/components/reports/ReportLoading.tsx rename to wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx index fe8d3d6..65dc792 100644 --- a/wiarygodnik_frontend/src/components/reports/ReportLoading.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx @@ -1,5 +1,5 @@ import { Box, CircularProgress, Typography } from "@mui/material"; -import theme from "../../theme"; +import theme from "../../../theme"; interface ReportLoadingProps { loadingStatus?: string; diff --git a/wiarygodnik_frontend/src/components/reports/ReportSearch.tsx b/wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx similarity index 94% rename from wiarygodnik_frontend/src/components/reports/ReportSearch.tsx rename to wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx index 8ae64dd..0bdf7bd 100644 --- a/wiarygodnik_frontend/src/components/reports/ReportSearch.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx @@ -1,9 +1,9 @@ import { Box, Button, Input, Typography } from "@mui/material"; -import theme from "../../theme.ts"; +import theme from "../../../theme.ts"; import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined'; import { useState } from "react"; import { useNavigate } from "react-router-dom"; -import { useAnalyseSource } from "../../hooks/useAnalyseSource.ts"; +import { useAnalyseSource } from "../hooks/useAnalyseSource.ts"; export const ReportSearch = () => { const navigate = useNavigate(); diff --git a/wiarygodnik_frontend/src/components/reports/domain/AnalysisStatus.ts b/wiarygodnik_frontend/src/features/report/domain/AnalysisStatus.ts similarity index 100% rename from wiarygodnik_frontend/src/components/reports/domain/AnalysisStatus.ts rename to wiarygodnik_frontend/src/features/report/domain/AnalysisStatus.ts diff --git a/wiarygodnik_frontend/src/hooks/useAnalyseSource.ts b/wiarygodnik_frontend/src/features/report/hooks/useAnalyseSource.ts similarity index 78% rename from wiarygodnik_frontend/src/hooks/useAnalyseSource.ts rename to wiarygodnik_frontend/src/features/report/hooks/useAnalyseSource.ts index 006bfc2..01c315f 100644 --- a/wiarygodnik_frontend/src/hooks/useAnalyseSource.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useAnalyseSource.ts @@ -1,4 +1,4 @@ -import { useAnalysisApi, type AnalyseResponse } from "../http/analysis.api"; +import { useAnalysisApi, type AnalyseResponse } from "../api/analysis.api"; export const useAnalyseSource = () => { const { analyseSource } = useAnalysisApi(); diff --git a/wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts b/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts similarity index 91% rename from wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts rename to wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts index 4085a8c..9445bcc 100644 --- a/wiarygodnik_frontend/src/hooks/useAnalysisStatus.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; -import { useAnalysisApi, type AnalysisStatusResponse } from '../http/analysis.api'; -import { useReportApi, type ReportStatusResponse } from '../http/report.api'; -import { AnalysisStatus } from "../components/reports/domain/AnalysisStatus.ts"; +import { useAnalysisApi, type AnalysisStatusResponse } from '../api/analysis.api'; +import { useReportApi, type ReportStatusResponse } from '../api/report.api'; +import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; export const useAnalysisStatus = (requestId: string | undefined) => { const { getAnalysisStatus } = useAnalysisApi(); diff --git a/wiarygodnik_frontend/src/hooks/useReport.ts b/wiarygodnik_frontend/src/features/report/hooks/useReport.ts similarity index 75% rename from wiarygodnik_frontend/src/hooks/useReport.ts rename to wiarygodnik_frontend/src/features/report/hooks/useReport.ts index b3d3b70..d17278f 100644 --- a/wiarygodnik_frontend/src/hooks/useReport.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useReport.ts @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -import { useReportApi, type ReportContentResponse } from '../http/report.api'; -import { AnalysisStatus } from "../components/reports/domain/AnalysisStatus.ts"; +import { useReportApi, type ReportContentResponse } from '../api/report.api'; +import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; export const useReport = (requestId: string | undefined, status: string | undefined) => { const { getMyReport } = useReportApi(); diff --git a/wiarygodnik_frontend/src/hooks/useReportList.ts b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts similarity index 83% rename from wiarygodnik_frontend/src/hooks/useReportList.ts rename to wiarygodnik_frontend/src/features/report/hooks/useReportList.ts index f2859e7..425c411 100644 --- a/wiarygodnik_frontend/src/hooks/useReportList.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { useReportApi, type ReportListItemResponse } from '../http/report.api'; +import { useReportApi, type ReportListItemResponse } from '../api/report.api'; export const useReportsList = () => { const { getAllMyReports } = useReportApi(); diff --git a/wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts b/wiarygodnik_frontend/src/hooks/useHttpClient.ts similarity index 95% rename from wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts rename to wiarygodnik_frontend/src/hooks/useHttpClient.ts index 63cea13..d7aaef7 100644 --- a/wiarygodnik_frontend/src/shared/hooks/useHttpClient.ts +++ b/wiarygodnik_frontend/src/hooks/useHttpClient.ts @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import axios, { HttpStatusCode, type AxiosInstance } from 'axios'; import { enqueueSnackbar } from 'notistack'; -import useKeycloak from './useKeycloak'; +import useKeycloak from '../features/auth/hooks/useKeycloak'; export const useHttpClient = (baseURL: string): AxiosInstance => { const { keycloak, authenticated } = useKeycloak(); diff --git a/wiarygodnik_frontend/src/common/UseIsMobile.tsx b/wiarygodnik_frontend/src/hooks/useIsMobile.ts similarity index 100% rename from wiarygodnik_frontend/src/common/UseIsMobile.tsx rename to wiarygodnik_frontend/src/hooks/useIsMobile.ts diff --git a/wiarygodnik_frontend/src/navbar/NavBar.tsx b/wiarygodnik_frontend/src/layout/NavBar.tsx similarity index 95% rename from wiarygodnik_frontend/src/navbar/NavBar.tsx rename to wiarygodnik_frontend/src/layout/NavBar.tsx index 6094bc4..cdadea0 100644 --- a/wiarygodnik_frontend/src/navbar/NavBar.tsx +++ b/wiarygodnik_frontend/src/layout/NavBar.tsx @@ -1,11 +1,11 @@ -import { useIsMobile } from "../common/UseIsMobile.tsx"; +import { useIsMobile } from "../hooks/useIsMobile.ts"; import { Box, Button, AppBar, Toolbar } from "@mui/material"; import logo from "/logo_full_350_80.png"; import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined'; import MenuOutlinedIcon from '@mui/icons-material/MenuOutlined'; import theme from "../theme.ts"; import { useLocation, useNavigate } from "react-router-dom"; -import useKeycloak from "../shared/hooks/useKeycloak.ts"; +import useKeycloak from "../features/auth/hooks/useKeycloak.ts"; type NavBarProps = { menuActive: boolean | undefined; diff --git a/wiarygodnik_frontend/src/components/toast/ToastProvider.tsx b/wiarygodnik_frontend/src/layout/ToastProvider.tsx similarity index 100% rename from wiarygodnik_frontend/src/components/toast/ToastProvider.tsx rename to wiarygodnik_frontend/src/layout/ToastProvider.tsx diff --git a/wiarygodnik_frontend/src/common/Scripts.tsx b/wiarygodnik_frontend/src/lib/domainExtractor.ts similarity index 100% rename from wiarygodnik_frontend/src/common/Scripts.tsx rename to wiarygodnik_frontend/src/lib/domainExtractor.ts diff --git a/wiarygodnik_frontend/src/pages/AccessDenied.tsx b/wiarygodnik_frontend/src/pages/AccessDenied.tsx index 120291e..23d8b85 100644 --- a/wiarygodnik_frontend/src/pages/AccessDenied.tsx +++ b/wiarygodnik_frontend/src/pages/AccessDenied.tsx @@ -1,5 +1,5 @@ import { Box, Container, Typography } from "@mui/material"; -import NavBar from "../navbar/NavBar"; +import NavBar from "../layout/NavBar"; export default function AccessDenied() { return ( diff --git a/wiarygodnik_frontend/src/pages/Home.tsx b/wiarygodnik_frontend/src/pages/Home.tsx index 5ee2711..cc131c3 100644 --- a/wiarygodnik_frontend/src/pages/Home.tsx +++ b/wiarygodnik_frontend/src/pages/Home.tsx @@ -1,8 +1,8 @@ import { Box, Button, Container, Typography } from "@mui/material"; import { Link } from "react-router-dom"; -import NavBar from "../navbar/NavBar"; +import NavBar from "../layout/NavBar"; import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined'; -import { useIsMobile } from "../common/UseIsMobile"; +import { useIsMobile } from "../hooks/useIsMobile"; import theme from "../theme"; export const Home = () => { diff --git a/wiarygodnik_frontend/src/pages/NotFound.tsx b/wiarygodnik_frontend/src/pages/NotFound.tsx index 541c620..d04b3e8 100644 --- a/wiarygodnik_frontend/src/pages/NotFound.tsx +++ b/wiarygodnik_frontend/src/pages/NotFound.tsx @@ -1,5 +1,5 @@ import { Box, Container, Typography } from "@mui/material"; -import NavBar from "../navbar/NavBar"; +import NavBar from "../layout/NavBar"; export default function NotFound() { return ( diff --git a/wiarygodnik_frontend/src/pages/Reports.tsx b/wiarygodnik_frontend/src/pages/Reports.tsx index 5f10b15..70bf7a9 100644 --- a/wiarygodnik_frontend/src/pages/Reports.tsx +++ b/wiarygodnik_frontend/src/pages/Reports.tsx @@ -1,16 +1,16 @@ -import NavBar from "../navbar/NavBar.tsx"; +import NavBar from "../layout/NavBar.tsx"; import { Box } from "@mui/material"; import { useEffect, useState } from "react"; -import { useIsMobile } from "../common/UseIsMobile.tsx"; +import { useIsMobile } from "../hooks/useIsMobile.ts"; import { useNavigate, useParams } from "react-router-dom"; -import { useAnalysisStatus } from "../hooks/useAnalysisStatus.ts"; -import { useReport } from "../hooks/useReport.ts"; -import { ReportList } from "../components/reports/ReportList.tsx"; -import { ReportSearch } from "../components/reports/ReportSearch.tsx"; -import { ReportContent } from "../components/reports/ReportContent.tsx"; -import { ReportLoading } from "../components/reports/ReportLoading.tsx"; +import { useAnalysisStatus } from "../features/report/hooks/useAnalysisStatus.ts"; +import { useReport } from "../features/report/hooks/useReport.ts"; +import { ReportList } from "../features/report/components/ReportList.tsx"; +import { ReportSearch } from "../features/report/components/ReportSearch.tsx"; +import { ReportContent } from "../features/report/components/ReportContent.tsx"; +import { ReportLoading } from "../features/report/components/ReportLoading.tsx"; import { enqueueSnackbar } from "notistack"; -import { AnalysisStatus } from "../components/reports/domain/AnalysisStatus.ts"; +import { AnalysisStatus } from "../features/report/domain/AnalysisStatus.ts"; function Reports() { const isMobile = useIsMobile(); diff --git a/wiarygodnik_frontend/src/pages/User.tsx b/wiarygodnik_frontend/src/pages/User.tsx index bd88dc3..eefbd7b 100644 --- a/wiarygodnik_frontend/src/pages/User.tsx +++ b/wiarygodnik_frontend/src/pages/User.tsx @@ -1,12 +1,12 @@ import { Box, Button, Divider, Typography } from "@mui/material"; -import NavBar from "../navbar/NavBar.tsx"; +import NavBar from "../layout/NavBar.tsx"; import PersonIcon from '@mui/icons-material/Person'; import theme from "../theme.ts"; import LogoutIcon from '@mui/icons-material/Logout'; import { userPageButton, userPageButtonIcon, userPageButtonText, userPageDivider } from "../Style.tsx"; import InfoIcon from '@mui/icons-material/Info'; import SettingsIcon from '@mui/icons-material/Settings'; -import useKeycloak from "../shared/hooks/useKeycloak.ts"; +import useKeycloak from "../features/auth/hooks/useKeycloak.ts"; function User() { const { keycloak } = useKeycloak(); diff --git a/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx b/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx index a87ec5d..0e9b53e 100644 --- a/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx +++ b/wiarygodnik_frontend/src/routing/ProtectedRoutes.tsx @@ -1,6 +1,6 @@ import React from "react"; import { Outlet } from "react-router-dom"; -import useKeycloak from "../shared/hooks/useKeycloak"; +import useKeycloak from "../features/auth/hooks/useKeycloak"; import AccessDenied from "../pages/AccessDenied"; import Loading from "../pages/Loading"; From ecb0036754505a37f9ca63d697edc1f77ddecd54 Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Wed, 31 Dec 2025 15:23:55 +0100 Subject: [PATCH 03/15] Adjust user page & add reports page redirect button --- .../features/auth/hooks/useKeycloakProfile.ts | 18 ++++++++++ wiarygodnik_frontend/src/layout/NavBar.tsx | 36 +++++++++++++------ wiarygodnik_frontend/src/pages/User.tsx | 19 +++++----- 3 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts diff --git a/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts b/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts new file mode 100644 index 0000000..a027da2 --- /dev/null +++ b/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts @@ -0,0 +1,18 @@ +import { useEffect, useState } from 'react' +import type Keycloak from 'keycloak-js' +import type { KeycloakProfile } from 'keycloak-js' + +export function useKeycloakProfile(keycloak: Keycloak | null, authenticated: boolean) { + const [profile, setProfile] = useState(null); + + useEffect(() => { + if (!keycloak || !authenticated) return; + + keycloak + .loadUserProfile() + .then(setProfile); + + }, [keycloak, authenticated]) + + return profile; +} diff --git a/wiarygodnik_frontend/src/layout/NavBar.tsx b/wiarygodnik_frontend/src/layout/NavBar.tsx index cdadea0..e0e9866 100644 --- a/wiarygodnik_frontend/src/layout/NavBar.tsx +++ b/wiarygodnik_frontend/src/layout/NavBar.tsx @@ -1,7 +1,8 @@ import { useIsMobile } from "../hooks/useIsMobile.ts"; -import { Box, Button, AppBar, Toolbar } from "@mui/material"; +import { Box, Button, AppBar, Toolbar, Tooltip } from "@mui/material"; import logo from "/logo_full_350_80.png"; import AccountCircleOutlinedIcon from '@mui/icons-material/AccountCircleOutlined'; +import ArticleIcon from '@mui/icons-material/Article'; import MenuOutlinedIcon from '@mui/icons-material/MenuOutlined'; import theme from "../theme.ts"; import { useLocation, useNavigate } from "react-router-dom"; @@ -32,6 +33,10 @@ function NavBar(props: NavBarProps) { } } + function handleReportsClick() { + navigate("/reports"); + } + return ( - {authenticated && location.pathname.startsWith("/reports") ? ( - - ) : null - } + {authenticated ? + location.pathname.startsWith("/reports") ? ( + + + + ) : ( + + + + ) + : null} @@ -61,9 +75,11 @@ function NavBar(props: NavBarProps) { {authenticated && location.pathname !== "/user" ? ( - + + + ) : null} diff --git a/wiarygodnik_frontend/src/pages/User.tsx b/wiarygodnik_frontend/src/pages/User.tsx index eefbd7b..dc02a14 100644 --- a/wiarygodnik_frontend/src/pages/User.tsx +++ b/wiarygodnik_frontend/src/pages/User.tsx @@ -1,4 +1,4 @@ -import { Box, Button, Divider, Typography } from "@mui/material"; +import { Box, Button, Container, Divider, Typography } from "@mui/material"; import NavBar from "../layout/NavBar.tsx"; import PersonIcon from '@mui/icons-material/Person'; import theme from "../theme.ts"; @@ -7,16 +7,17 @@ import { userPageButton, userPageButtonIcon, userPageButtonText, userPageDivider import InfoIcon from '@mui/icons-material/Info'; import SettingsIcon from '@mui/icons-material/Settings'; import useKeycloak from "../features/auth/hooks/useKeycloak.ts"; +import { useKeycloakProfile } from "../features/auth/hooks/useKeycloakProfile.ts"; function User() { - const { keycloak } = useKeycloak(); + const { keycloak, authenticated } = useKeycloak(); + const profile = useKeycloakProfile(keycloak, authenticated); - const handleLogout = () => { - keycloak?.logout(); - }; + const handleSettings = () => keycloak?.accountManagement(); + const handleLogout = () => keycloak?.logout({ redirectUri: window.location.origin }); return ( - + - {keycloak?.idTokenParsed?.name}! + {profile?.firstName} {profile?.lastName} - @@ -50,7 +51,7 @@ function User() { - + ) } From 8847eb2b7f0a66823564c3ad45c4979125d2822c Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Thu, 1 Jan 2026 21:18:10 +0100 Subject: [PATCH 04/15] Make analysis API available and show it under the report on UI --- content-analysis-service/build.gradle.kts | 5 + .../wiarygodnik/cas/amqp/RabbitMqProducer.kt | 8 +- .../cas/controller/AnalysisController.kt | 13 +- .../p/lodz/wiarygodnik/cas/model/Analysis.kt | 80 ++++++++++++ .../wiarygodnik/cas/model/AnalysisEntity.kt | 18 --- .../cas/model/ComparisonSourceFacts.kt | 11 ++ .../cas/model/ComparisonSummary.kt | 14 +++ .../wiarygodnik/cas/model/SentimentExample.kt | 15 +++ .../cas/model/SentimentExampleQuote.kt | 11 ++ .../wiarygodnik/cas/model/SentimentSummary.kt | 14 +++ .../wiarygodnik/cas/model/SourceSummary.kt | 11 ++ .../{AnalysisResult.kt => AnalysisData.kt} | 3 +- .../cas/model/dto/AnalysisResultMessage.kt | 9 ++ .../cas/model/dto/ContentAnalysis.kt | 2 +- .../cas/model/dto/ContentComparison.kt | 2 +- .../cas/model/dto/ContentSentiment.kt | 9 -- .../cas/model/dto/ContentSummarization.kt | 2 +- .../cas/model/dto/SentimentSummaryDto.kt | 9 ++ .../cas/model/mapper/AnalysisMapper.kt | 55 ++++++++ .../cas/repository/AnalysisRepository.kt | 7 +- .../cas/service/AnalysisProcessor.kt | 117 ++++++++++-------- .../cas/service/AnalysisService.kt | 36 +++++- .../service/agent/ContentSentimentAgent.kt | 4 +- .../cas/service/analyser/AiContentAnalyzer.kt | 4 +- .../service/searcher/KeywordWebSearcher.kt | 2 +- .../searcher/SerpKeywordWebSearcher.kt | 2 +- .../src/main/resources/application.yml | 2 - .../wiarygodnik/rgs/amqp/RabbitMqConsumer.kt | 4 +- .../controller/dto/ReportContentResponse.kt | 1 + .../p/lodz/wiarygodnik/rgs/model/Report.kt | 16 +-- ...ysisResult.kt => AnalysisResultMessage.kt} | 19 ++- .../rgs/model/dto/ReportGenerationResult.kt | 4 +- .../rgs/service/AiAnalysisReportGenerator.kt | 23 ++-- .../wiarygodnik/rgs/service/ReportService.kt | 4 +- .../src/main/resources/logback-spring.xml | 2 +- .../analysis_report_generation_system.txt | 70 ++++++++--- .../src/features/report/api/analysis.api.ts | 52 +++++++- .../components/ContentComparisonPart.tsx | 33 +++++ .../report/components/ContentSummaryPart.tsx | 24 ++++ .../report/components/ReportContent.tsx | 94 +++++++------- .../report/components/ReportLoading.tsx | 3 +- .../features/report/components/ReportPart.tsx | 17 +++ .../components/SentimentAnalysisPart.tsx | 47 +++++++ .../report/domain/CredibilityLevel.ts | 5 + .../features/report/domain/SentimentType.ts | 10 ++ .../src/features/report/hooks/useAnalysis.ts | 20 +++ .../report/hooks/useAnalysisStatus.ts | 4 +- .../report/lib/analysisStatusMapper.ts | 20 +++ .../report/lib/sentimentTypeMapper.ts | 24 ++++ wiarygodnik_frontend/src/layout/NavBar.tsx | 2 +- wiarygodnik_frontend/src/pages/Reports.tsx | 4 +- 51 files changed, 763 insertions(+), 204 deletions(-) create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt delete mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt rename content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/{AnalysisResult.kt => AnalysisData.kt} (79%) create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt delete mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSentiment.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/SentimentSummaryDto.kt create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/mapper/AnalysisMapper.kt rename report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/{AnalysisResult.kt => AnalysisResultMessage.kt} (51%) create mode 100644 wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx create mode 100644 wiarygodnik_frontend/src/features/report/components/ContentSummaryPart.tsx create mode 100644 wiarygodnik_frontend/src/features/report/components/ReportPart.tsx create mode 100644 wiarygodnik_frontend/src/features/report/components/SentimentAnalysisPart.tsx create mode 100644 wiarygodnik_frontend/src/features/report/domain/CredibilityLevel.ts create mode 100644 wiarygodnik_frontend/src/features/report/domain/SentimentType.ts create mode 100644 wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts create mode 100644 wiarygodnik_frontend/src/features/report/lib/analysisStatusMapper.ts create mode 100644 wiarygodnik_frontend/src/features/report/lib/sentimentTypeMapper.ts diff --git a/content-analysis-service/build.gradle.kts b/content-analysis-service/build.gradle.kts index 4ad056e..017d8fe 100644 --- a/content-analysis-service/build.gradle.kts +++ b/content-analysis-service/build.gradle.kts @@ -1,6 +1,7 @@ plugins { kotlin("jvm") version "1.9.25" kotlin("plugin.spring") version "1.9.25" + kotlin("plugin.noarg") version "2.3.0" id("org.springframework.boot") version "3.5.7" id("io.spring.dependency-management") version "1.1.7" id("org.sonarqube") version "5.0.0.4638" @@ -65,6 +66,10 @@ tasks.withType { useJUnitPlatform() } +noArg { + annotation("jakarta.persistence.Entity") +} + sonar { properties { property("sonar.projectKey", "goldenkacper_Wiarygodnik_content-analysis-service") diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt index 55cf1d9..ff0d3cd 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt @@ -5,16 +5,16 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate import org.springframework.stereotype.Service import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQConfig.Companion.ANALYSIS_ROUTING_KEY import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQConfig.Companion.EXCHANGE_NAME -import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisResultMessage @Service class RabbitMQProducer(val rabbitTemplate: RabbitTemplate) { private val log = KotlinLogging.logger {} - fun sendAnalysis(analysisResult: AnalysisResult) { - rabbitTemplate.convertAndSend(EXCHANGE_NAME, ANALYSIS_ROUTING_KEY, analysisResult) - log.info { "Sent analysis: $analysisResult" } + fun sendAnalysis(analysisResultMessage: AnalysisResultMessage) { + rabbitTemplate.convertAndSend(EXCHANGE_NAME, ANALYSIS_ROUTING_KEY, analysisResultMessage) + log.info { "Sent analysis: $analysisResultMessage" } } } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/controller/AnalysisController.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/controller/AnalysisController.kt index 2e7843e..53b4cbb 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/controller/AnalysisController.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/controller/AnalysisController.kt @@ -6,6 +6,8 @@ import org.springframework.http.ProblemDetail import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.* import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisData +import pl.edu.p.lodz.wiarygodnik.cas.model.mapper.AnalysisMapper import pl.edu.p.lodz.wiarygodnik.cas.service.AnalysisProcessor import pl.edu.p.lodz.wiarygodnik.cas.service.AnalysisService @@ -13,9 +15,11 @@ import pl.edu.p.lodz.wiarygodnik.cas.service.AnalysisService @RequestMapping("/api/analysis") class AnalysisController( private val analysisProcessor: AnalysisProcessor, - private val analysisService: AnalysisService + private val analysisService: AnalysisService, ) { + private val analysisMapper = AnalysisMapper() + @PostMapping("/process") fun analyze(@RequestBody request: AnalyseRequest): ResponseEntity { val analysisEntity = analysisProcessor.analyse(request.url) @@ -23,9 +27,13 @@ class AnalysisController( } @GetMapping("/status/{requestId}") - fun getAnalysis(@PathVariable requestId: String): ResponseEntity = + fun getAnalysisStatus(@PathVariable requestId: String): ResponseEntity = ResponseEntity.ok(AnalysisStatusResponse(analysisService.getAnalysisStatus(requestId))) + @GetMapping("/{requestId}") + fun getAnalysis(@PathVariable requestId: String): ResponseEntity = + ResponseEntity.ok(analysisMapper.mapToDto(analysisService.getAnalysis(requestId))) + @ResponseStatus(HttpStatus.NOT_FOUND) @ExceptionHandler fun handleNoSuchException(ex: NoSuchElementException): ProblemDetail = @@ -34,4 +42,5 @@ class AnalysisController( data class AnalyseRequest(val url: String) data class AnalyseResponse(val requestId: String) data class AnalysisStatusResponse(val status: AnalysisStatus) + } diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt new file mode 100644 index 0000000..7118606 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt @@ -0,0 +1,80 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* +import jakarta.persistence.GenerationType.IDENTITY +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentComparison + +enum class AnalysisStatus { + ANALYSING_CONTENT, COMPARING_SIMILAR_SOURCES, COMPLETED, FAILED +} + +@Entity +class Analysis( + val requestId: String, + val userId: String, + @Column(columnDefinition = "TEXT") var sourceUrl: String, + @Enumerated(EnumType.STRING) var status: AnalysisStatus, + @OneToOne(cascade = [CascadeType.ALL]) var sourceSummary: SourceSummary? = null, + @OneToOne(cascade = [CascadeType.ALL]) var sentimentSummary: SentimentSummary? = null, + @OneToOne(cascade = [CascadeType.ALL]) var comparisonSummary: ComparisonSummary? = null, + @Id @GeneratedValue(strategy = IDENTITY) var id: Long? = null +) { + + fun fillWith(contentAnalysis: ContentAnalysis) { + val sourceSummary = SourceSummary( + analysis = this, + summary = contentAnalysis.summarization.description, + keywords = contentAnalysis.summarization.keywords + ) + + val sentimentSummary = SentimentSummary( + analysis = this, + summary = contentAnalysis.sentiment.summary + ) + + val sentimentExamples = contentAnalysis.sentiment.examples.map { example -> + val sentimentExample = SentimentExample( + sentimentSummary = sentimentSummary, + sentiment = example.sentiment + ) + + val quotes = example.quotes.map { (quote, comment) -> + SentimentExampleQuote( + quote = quote, + explanation = comment, + sentimentExample = sentimentExample + ) + }.toMutableList() + + sentimentExample.sentimentExampleQuotes = quotes + + sentimentExample + }.toMutableList() + + sentimentSummary.examples = sentimentExamples + + this.sourceSummary = sourceSummary + this.sentimentSummary = sentimentSummary + } + + fun fillWith(contentComparison: ContentComparison) { + val comparisonSummary = ComparisonSummary( + analysis = this, + summary = contentComparison.description + ) + + val comparisonSourceFacts = contentComparison.sourcesFacts.map { + ComparisonSourceFacts( + comparisonSummary = comparisonSummary, + sourceUrl = it.url, + facts = it.facts + ) + }.toMutableList() + + comparisonSummary.examples = comparisonSourceFacts + + this.comparisonSummary = comparisonSummary + } + +} \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt deleted file mode 100644 index ab11d5a..0000000 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/AnalysisEntity.kt +++ /dev/null @@ -1,18 +0,0 @@ -package pl.edu.p.lodz.wiarygodnik.cas.model - -import jakarta.persistence.* -import jakarta.persistence.GenerationType.IDENTITY -import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus.ANALYSING_CONTENT - -enum class AnalysisStatus { - ANALYSING_CONTENT, COMPARING_SIMILAR_SOURCES, COMPLETED, FAILED -} - -@Entity -class AnalysisEntity( - @Id @GeneratedValue(strategy = IDENTITY) var id: Long = 0, - val requestId: String = "", - val userId: String = "", - var sourceUrl: String = "", - @Enumerated(EnumType.STRING) var status: AnalysisStatus = ANALYSING_CONTENT, -) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt new file mode 100644 index 0000000..10cd28e --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt @@ -0,0 +1,11 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* + +@Entity +class ComparisonSourceFacts( + @ManyToOne @JoinColumn(name = "comparison_summary_id") val comparisonSummary: ComparisonSummary, + @Column(columnDefinition = "TEXT") val sourceUrl: String, + @ElementCollection @CollectionTable(name = "source_facts") val facts: Set = mutableSetOf(), + @Id @GeneratedValue val id: Long? = null +) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt new file mode 100644 index 0000000..932ca49 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt @@ -0,0 +1,14 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* + +@Entity +class ComparisonSummary( + @OneToOne val analysis: Analysis, + @Column(columnDefinition = "TEXT") val summary: String, + @OneToMany( + mappedBy = "comparisonSummary", + cascade = [CascadeType.ALL] + ) var examples: MutableList = ArrayList(), + @Id @GeneratedValue val id: Long? = null +) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt new file mode 100644 index 0000000..deb4593 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt @@ -0,0 +1,15 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.Sentiment + +@Entity +class SentimentExample( + @ManyToOne @JoinColumn(name = "sentiment_summary_id") val sentimentSummary: SentimentSummary, + @Enumerated(EnumType.STRING) val sentiment: Sentiment, + @OneToMany( + mappedBy = "sentimentExample", + cascade = [CascadeType.ALL] + ) var sentimentExampleQuotes: MutableList = ArrayList(), + @Id @GeneratedValue val id: Long? = null +) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt new file mode 100644 index 0000000..330eef9 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt @@ -0,0 +1,11 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* + +@Entity +class SentimentExampleQuote( + @ManyToOne @JoinColumn(name = "sentiment_example_id") val sentimentExample: SentimentExample, + @Column(columnDefinition = "TEXT") val quote: String, + @Column(columnDefinition = "TEXT") val explanation: String, + @Id @GeneratedValue val id: Long? = null +) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt new file mode 100644 index 0000000..93c1362 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt @@ -0,0 +1,14 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* + +@Entity +class SentimentSummary( + @OneToOne val analysis: Analysis, + @Column(columnDefinition = "TEXT") val summary: String, + @OneToMany( + mappedBy = "sentimentSummary", + cascade = [CascadeType.ALL] + ) var examples: MutableList = ArrayList(), + @Id @GeneratedValue val id: Long? = null +) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt new file mode 100644 index 0000000..d8cb09f --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt @@ -0,0 +1,11 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model + +import jakarta.persistence.* + +@Entity +class SourceSummary( + @OneToOne val analysis: Analysis, + @Column(columnDefinition = "TEXT") val summary: String, + @ElementCollection @CollectionTable(name = "source_keywords") val keywords: Set = mutableSetOf(), + @Id @GeneratedValue val id: Long? = null +) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisData.kt similarity index 79% rename from content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt rename to content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisData.kt index 8b88747..8f329f0 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResult.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisData.kt @@ -1,8 +1,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.model.dto -data class AnalysisResult( +data class AnalysisData( val requestId: String, - val userId: String, val sourceUrl: String, val contentAnalysis: ContentAnalysis, val contentComparison: ContentComparison diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt new file mode 100644 index 0000000..90f91f9 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt @@ -0,0 +1,9 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model.dto + +data class AnalysisResultMessage( + val requestId: String, + val userId: String, + val sourceUrl: String, + val contentAnalysis: ContentAnalysis, + val contentComparison: ContentComparison? +) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentAnalysis.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentAnalysis.kt index d1d80d4..e53106b 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentAnalysis.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentAnalysis.kt @@ -1,3 +1,3 @@ package pl.edu.p.lodz.wiarygodnik.cas.model.dto -data class ContentAnalysis(val summarization: ContentSummarization, val sentiment: ContentSentiment) \ No newline at end of file +data class ContentAnalysis(val summarization: ContentSummarization, val sentiment: SentimentSummaryDto) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentComparison.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentComparison.kt index 55643c9..385dc3a 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentComparison.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentComparison.kt @@ -1,4 +1,4 @@ package pl.edu.p.lodz.wiarygodnik.cas.model.dto data class ContentComparison(val description: String, val sourcesFacts: List) -data class SourceFacts(val url: String, val facts: List) \ No newline at end of file +data class SourceFacts(val url: String, val facts: Set) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSentiment.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSentiment.kt deleted file mode 100644 index f7c1522..0000000 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSentiment.kt +++ /dev/null @@ -1,9 +0,0 @@ -package pl.edu.p.lodz.wiarygodnik.cas.model.dto - -enum class Sentiment { - NEUTRAL, POSITIVE, NEGATIVE, ALARMIST, IRONIC, PERSUASIVE, AGGRESSIVE, FORMAL -} - -data class ContentSentiment(val description: String, val examples: List) -data class SentimentExample(val sentiment: Sentiment, val quotes: List) -data class CommentedQuote(val quote: String, val comment: String) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSummarization.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSummarization.kt index e291d9f..b309435 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSummarization.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/ContentSummarization.kt @@ -1,3 +1,3 @@ package pl.edu.p.lodz.wiarygodnik.cas.model.dto -data class ContentSummarization(val description: String, val keywords: List) +data class ContentSummarization(val description: String, val keywords: Set) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/SentimentSummaryDto.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/SentimentSummaryDto.kt new file mode 100644 index 0000000..a0bb96c --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/SentimentSummaryDto.kt @@ -0,0 +1,9 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model.dto + +enum class Sentiment { + NEUTRAL, POSITIVE, NEGATIVE, ALARMIST, IRONIC, PERSUASIVE, AGGRESSIVE, FORMAL +} + +data class SentimentSummaryDto(val summary: String, val examples: List) +data class SentimentExampleDto(val sentiment: Sentiment, val quotes: List) +data class SentimentExampleQuoteDto(val quote: String, val explanation: String) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/mapper/AnalysisMapper.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/mapper/AnalysisMapper.kt new file mode 100644 index 0000000..084b2f5 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/mapper/AnalysisMapper.kt @@ -0,0 +1,55 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model.mapper + +import pl.edu.p.lodz.wiarygodnik.cas.model.Analysis +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.* + +class AnalysisMapper { + + fun mapToDto(analysis: Analysis): AnalysisData { + val sourceSummary = requireNotNull(analysis.sourceSummary) { + "sourceSummary is required to map AnalysisData" + } + val sentimentSummary = requireNotNull(analysis.sentimentSummary) { + "sentimentSummary is required to map AnalysisData" + } + val comparisonSummary = requireNotNull(analysis.comparisonSummary) { + "comparisonSummary is required to map AnalysisData" + } + + return AnalysisData( + requestId = analysis.requestId, + sourceUrl = analysis.sourceUrl, + contentAnalysis = ContentAnalysis( + summarization = ContentSummarization( + description = sourceSummary.summary, + keywords = sourceSummary.keywords + ), + sentiment = SentimentSummaryDto( + summary = sentimentSummary.summary, + examples = sentimentSummary.examples.map { example -> + SentimentExampleDto( + sentiment = example.sentiment, + quotes = example.sentimentExampleQuotes.map { quote -> + SentimentExampleQuoteDto( + quote = quote.quote, + explanation = quote.explanation + ) + } + ) + } + ) + ), + contentComparison = ContentComparison( + description = comparisonSummary.summary, + sourcesFacts = comparisonSummary.examples.map { example -> + SourceFacts( + url = example.sourceUrl, + facts = example.facts + ) + } + ) + ) + } + + +} \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/repository/AnalysisRepository.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/repository/AnalysisRepository.kt index bcd0615..b636112 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/repository/AnalysisRepository.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/repository/AnalysisRepository.kt @@ -2,9 +2,10 @@ package pl.edu.p.lodz.wiarygodnik.cas.repository import org.springframework.data.jpa.repository.JpaRepository import org.springframework.transaction.annotation.Transactional -import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisEntity +import pl.edu.p.lodz.wiarygodnik.cas.model.Analysis @Transactional -interface AnalysisRepository : JpaRepository { - fun findAnalysisEntityByRequestId(requestId: String): AnalysisEntity? +interface AnalysisRepository : JpaRepository { + fun findAnalysisByRequestId(requestId: String): Analysis? + fun findAnalysisEntityByRequestIdAndUserId(requestId: String, userId: String): Analysis? } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt index 9b96084..9142013 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt @@ -7,20 +7,16 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQProducer -import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisEntity -import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus +import pl.edu.p.lodz.wiarygodnik.cas.model.Analysis import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus.* -import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentComparison import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ScrapedWebContent -import pl.edu.p.lodz.wiarygodnik.cas.repository.AnalysisRepository -import pl.edu.p.lodz.wiarygodnik.cas.security.PrincipalProvider import pl.edu.p.lodz.wiarygodnik.cas.service.analyser.ContentAnalyser import pl.edu.p.lodz.wiarygodnik.cas.service.comparator.ContentComparator import pl.edu.p.lodz.wiarygodnik.cas.service.scraper.WebScraper import pl.edu.p.lodz.wiarygodnik.cas.service.searcher.KeywordWebSearcher -import java.util.* import kotlin.coroutines.CoroutineContext @Component @@ -29,7 +25,7 @@ class AnalysisProcessor( private val contentAnalyzer: ContentAnalyser, private val keywordWebSearcher: KeywordWebSearcher, private val contentComparator: ContentComparator, - private val analysisRepository: AnalysisRepository, + private val analysisService: AnalysisService, private val producer: RabbitMQProducer ) : CoroutineScope { @@ -37,58 +33,79 @@ class AnalysisProcessor( override val coroutineContext: CoroutineContext = SupervisorJob() + Dispatchers.IO - fun analyse(url: String): AnalysisEntity { - val analysisEntity = prepareNewAnalysis(url) - val persistedAnalysis = analysisRepository.save(analysisEntity) - + fun analyse(url: String): Analysis { + val persistedAnalysis = analysisService.initializeAnalysis(url) asyncProcessAnalysis(persistedAnalysis) - return persistedAnalysis } - private fun prepareNewAnalysis(url: String) = - AnalysisEntity( - requestId = UUID.randomUUID().toString(), - userId = PrincipalProvider.getCurrentUserId(), - sourceUrl = url, - status = ANALYSING_CONTENT - ) - - private fun asyncProcessAnalysis(analysisEntity: AnalysisEntity) = launch { + private fun asyncProcessAnalysis(analysis: Analysis) = launch { try { - log.info { "Analysis for url: ${analysisEntity.sourceUrl} process started. [analysisId: ${analysisEntity.id}, requestId: ${analysisEntity.requestId}]" } - - val scrapedWebContent: ScrapedWebContent = webScraper.scrape(analysisEntity.sourceUrl) - log.info { "Analysing content of scraped web page. [analysisId: ${analysisEntity.id}, requestId: ${analysisEntity.requestId}]" } - val analysis: ContentAnalysis = contentAnalyzer.analyse(scrapedWebContent.text) - - switchAnalysisStatus(analysisEntity, COMPARING_SIMILAR_SOURCES) - log.info { "Comparing content of similar web pages. [analysisId: ${analysisEntity.id}, requestId: ${analysisEntity.requestId}]" } - val topSimilarUrls: List = keywordWebSearcher.searchTopUrls(analysis.summarization.keywords) - val scrapedSimilarWebContents: List = topSimilarUrls.map { webScraper.scrape(it) } - val comparison: ContentComparison = contentComparator.compare( - analysis.summarization.description, scrapedSimilarWebContents - ) - switchAnalysisStatus(analysisEntity, COMPLETED) - - val result = AnalysisResult( - analysisEntity.requestId, - analysisEntity.userId, - analysisEntity.sourceUrl, - analysis, - comparison - ) - log.info { "Analysis process finished. Sending result for report generation. [analysisId: ${analysisEntity.id}, requestId: ${analysisEntity.requestId}]" } - producer.sendAnalysis(result) + log.info { "Analysis for url: ${analysis.sourceUrl} process started. [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + val contentAnalysis: ContentAnalysis = analyseContent(analysis) + analysis.fillWith(contentAnalysis) + + analysis.status = COMPARING_SIMILAR_SOURCES + val updatedAnalysis: Analysis = analysisService.update(analysis) + + val contentComparison: ContentComparison? = compareSimilarSources(updatedAnalysis, contentAnalysis) + contentComparison?.let { updatedAnalysis.fillWith(it) } + + updatedAnalysis.status = COMPLETED + analysisService.update(updatedAnalysis) + log.info { "Analysis process finished. [analysisId: ${updatedAnalysis.id}, requestId: ${updatedAnalysis.requestId}]" } + + sendAnalysisResult(updatedAnalysis, contentAnalysis, contentComparison) } catch (e: Exception) { - log.error { "Error while analysing content [analysisId: ${analysisEntity.id}, requestId: ${analysisEntity.requestId}]: $e" } - switchAnalysisStatus(analysisEntity, FAILED) + log.error { "Error while analysing content [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]: $e" } + analysis.status = FAILED + analysisService.updateStatus(analysis.requestId, FAILED) } } - private fun switchAnalysisStatus(analysis: AnalysisEntity, status: AnalysisStatus) { - analysis.status = status - analysisRepository.save(analysis) + private fun analyseContent(analysis: Analysis): ContentAnalysis { + log.info { "Scraping source web page. [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + val scrapedWebContent: ScrapedWebContent = webScraper.scrape(analysis.sourceUrl) + + log.info { "Analysing content of scraped web page. [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + val contentAnalysis: ContentAnalysis = contentAnalyzer.analyse(scrapedWebContent.text) + + return contentAnalysis + } + + private fun compareSimilarSources(analysis: Analysis, contentAnalysis: ContentAnalysis): ContentComparison? { + log.info { "Searching for top matching urls to the keywords. [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + val topSimilarUrls: List = keywordWebSearcher.searchTopUrls(contentAnalysis.summarization.keywords) + + log.info { "Scraping top matched urls [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + val scrapedSimilarWebContents: List = topSimilarUrls + .map { webScraper.scrape(it) } + .filter { it.text.isNotBlank() } + + if (scrapedSimilarWebContents.isEmpty()) { + log.info { "No valid matched sources were found [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + return null + } + + log.info { "Comparing top matched sources [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + val contentComparison: ContentComparison = contentComparator.compare( + contentAnalysis.summarization.description, scrapedSimilarWebContents + ) + + return contentComparison + } + + private fun sendAnalysisResult( + analysis: Analysis, + contentAnalysis: ContentAnalysis, + contentComparison: ContentComparison? + ) { + val result = AnalysisResultMessage( + analysis.requestId, analysis.userId, analysis.sourceUrl, + contentAnalysis, contentComparison + ) + log.info { "Sending result for report generation. [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } + producer.sendAnalysis(result) } } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt index f07b65e..9ff0b4b 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt @@ -1,17 +1,47 @@ package pl.edu.p.lodz.wiarygodnik.cas.service import org.springframework.stereotype.Service -import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisEntity +import pl.edu.p.lodz.wiarygodnik.cas.model.Analysis import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus +import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus.ANALYSING_CONTENT import pl.edu.p.lodz.wiarygodnik.cas.repository.AnalysisRepository +import pl.edu.p.lodz.wiarygodnik.cas.security.PrincipalProvider +import java.util.* @Service class AnalysisService(private val analysisRepository: AnalysisRepository) { fun getAnalysisStatus(requestId: String): AnalysisStatus { - val analysis: AnalysisEntity = analysisRepository.findAnalysisEntityByRequestId(requestId) - ?: throw NoSuchElementException("Analysis not found") + val analysis: Analysis = getAnalysis(requestId) return analysis.status } + fun getAnalysis(requestId: String): Analysis { + val currentUserId: String = PrincipalProvider.getCurrentUserId() + return analysisRepository.findAnalysisEntityByRequestIdAndUserId(requestId, currentUserId) + ?: throw NoSuchElementException("Analysis not found") + } + + fun initializeAnalysis(url: String): Analysis { + val initialAnalysis = Analysis( + requestId = UUID.randomUUID().toString(), + userId = PrincipalProvider.getCurrentUserId(), + sourceUrl = url, + status = ANALYSING_CONTENT + ) + val persistedAnalysis: Analysis = analysisRepository.save(initialAnalysis) + return persistedAnalysis + } + + fun update(analysis: Analysis): Analysis { + return analysisRepository.save(analysis) + } + + fun updateStatus(requestId: String, status: AnalysisStatus) { + val analysis: Analysis = analysisRepository.findAnalysisByRequestId(requestId) + ?: throw NoSuchElementException("Analysis not found") + analysis.status = status + analysisRepository.save(analysis) + } + } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt index 9f86762..ba4cd04 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSentimentAgent.kt @@ -2,11 +2,11 @@ package pl.edu.p.lodz.wiarygodnik.cas.service.agent import org.springframework.ai.chat.model.ChatModel import org.springframework.stereotype.Component -import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentSentiment +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.SentimentSummaryDto @Component class ContentSentimentAgent(chatModel: ChatModel) : - AbstractAgent(chatModel, ContentSentiment::class.java) { + AbstractAgent(chatModel, SentimentSummaryDto::class.java) { override fun systemPrompt(): String = """ Jesteś systemem analizującym nacechowanie tekstów artykułów informacyjnych. Otrzymasz treść artykułu (uprzednio oczyszczoną z elementów technicznych strony lub w surowej formie). diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/analyser/AiContentAnalyzer.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/analyser/AiContentAnalyzer.kt index a3ed791..5737a7b 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/analyser/AiContentAnalyzer.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/analyser/AiContentAnalyzer.kt @@ -3,7 +3,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.service.analyser import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.cas.model.dto.CleanedContent import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis -import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentSentiment +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.SentimentSummaryDto import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentSummarization import pl.edu.p.lodz.wiarygodnik.cas.service.agent.ContentCleanerAgent import pl.edu.p.lodz.wiarygodnik.cas.service.agent.ContentSentimentAgent @@ -19,7 +19,7 @@ class AiContentAnalyzer( override fun analyse(content: String): ContentAnalysis { val cleanedContent: CleanedContent = contentCleanerAgent.work(content) val summarization: ContentSummarization = contentSummarizationAgent.work(cleanedContent.text) - val sentiment: ContentSentiment = contentSentimentAgent.work(cleanedContent.text) + val sentiment: SentimentSummaryDto = contentSentimentAgent.work(cleanedContent.text) return ContentAnalysis(summarization, sentiment) } diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/KeywordWebSearcher.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/KeywordWebSearcher.kt index 80efdd6..2c7d273 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/KeywordWebSearcher.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/KeywordWebSearcher.kt @@ -1,5 +1,5 @@ package pl.edu.p.lodz.wiarygodnik.cas.service.searcher interface KeywordWebSearcher { - fun searchTopUrls(keywords: List): List + fun searchTopUrls(keywords: Set): List } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/SerpKeywordWebSearcher.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/SerpKeywordWebSearcher.kt index 268e415..a36646d 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/SerpKeywordWebSearcher.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/searcher/SerpKeywordWebSearcher.kt @@ -15,7 +15,7 @@ class SerpKeywordWebSearcher( private val webClient: WebClient = webClientBuilder.baseUrl(baseUrl).build() - override fun searchTopUrls(keywords: List): List = + override fun searchTopUrls(keywords: Set): List = webClient.get() .uri { builder -> builder.path("/search.json") diff --git a/content-analysis-service/src/main/resources/application.yml b/content-analysis-service/src/main/resources/application.yml index 9067817..ec267ae 100644 --- a/content-analysis-service/src/main/resources/application.yml +++ b/content-analysis-service/src/main/resources/application.yml @@ -31,8 +31,6 @@ spring: logging: logstash: server: "localhost:5000" - level: - org.springframework.security: DEBUG jina: url: "https://r.jina.ai" diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt index 103278c..1b561b8 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt @@ -4,7 +4,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.amqp.rabbit.annotation.RabbitListener import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.rgs.amqp.RabbitMQConfig.Companion.ANALYSIS_RESULTS_QUEUE -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.service.ReportService @Component @@ -13,7 +13,7 @@ class RabbitMQConsumer(private val reportService: ReportService) { private val log = KotlinLogging.logger {} @RabbitListener(queues = [ANALYSIS_RESULTS_QUEUE]) - fun contentAnalysisServiceResultsQueue(message: AnalysisResult) { + fun contentAnalysisServiceResultsQueue(message: AnalysisResultMessage) { log.info { "Received message: $message" } reportService.createReport(message) } diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt index 2594c3d..95898d2 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt @@ -2,6 +2,7 @@ package pl.edu.p.lodz.wiarygodnik.rgs.controller.dto import pl.edu.p.lodz.wiarygodnik.rgs.model.CredibilityLevel import pl.edu.p.lodz.wiarygodnik.rgs.model.Report +import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus data class ReportContentResponse( val requestId: String, diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt index 8368268..54f8135 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt @@ -2,7 +2,7 @@ package pl.edu.p.lodz.wiarygodnik.rgs.model import jakarta.persistence.* import jakarta.persistence.GenerationType.IDENTITY -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult enum class ReportStatus { @@ -22,7 +22,7 @@ class Report( var sourceUrl: String, @Enumerated(EnumType.STRING) var status: ReportStatus, var title: String = "Not generated yet", - @Enumerated(EnumType.STRING) var credibilityLevel: CredibilityLevel, + @Enumerated(EnumType.STRING) var credibilityLevel: CredibilityLevel = CredibilityLevel.LOW, @Lob @Column(columnDefinition = "TEXT") var content: String = "Not generated yet", @OneToMany( cascade = [CascadeType.ALL], @@ -31,17 +31,18 @@ class Report( ) { companion object { - fun fromAnalysisResult(analysisResult: AnalysisResult): Report { + fun fromAnalysisResult(analysisResult: AnalysisResultMessage): Report { val initialReport = Report( requestId = analysisResult.requestId, userId = analysisResult.userId, sourceUrl = analysisResult.sourceUrl, - credibilityLevel = CredibilityLevel.MEDIUM, status = ReportStatus.GENERATING ) - initialReport.similarSources = analysisResult.contentComparison.sourcesFacts - .map { SimilarSource(sourceUrl = it.url, report = initialReport) } - .toMutableList() + analysisResult.contentComparison?.let { contentComparison -> + initialReport.similarSources = contentComparison.sourcesFacts + .map { SimilarSource(sourceUrl = it.url, report = initialReport) } + .toMutableList() + } return initialReport } } @@ -49,6 +50,7 @@ class Report( fun fillWithGeneratedContent(reportGenerationResult: ReportGenerationResult) { this.title = reportGenerationResult.title this.content = reportGenerationResult.content + this.credibilityLevel = reportGenerationResult.credibilityLevel this.status = ReportStatus.GENERATED } diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResultMessage.kt similarity index 51% rename from report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt rename to report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResultMessage.kt index 739bf27..45da968 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResult.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResultMessage.kt @@ -4,23 +4,20 @@ enum class Sentiment { NEUTRAL, POSITIVE, NEGATIVE, ALARMIST, IRONIC, PERSUASIVE, AGGRESSIVE, FORMAL } -data class AnalysisResult( +data class AnalysisResultMessage( val requestId: String, val userId: String, val sourceUrl: String, val contentAnalysis: ContentAnalysis, - val contentComparison: ContentComparison, + val contentComparison: ContentComparison? ) -data class ContentAnalysis(val summarization: ContentSummarization, val sentiment: ContentSentiment) -data class ContentSummarization(val description: String, val keywords: List) +data class ContentAnalysis(val summarization: ContentSummarization, val sentiment: SentimentSummaryDto) +data class ContentSummarization(val description: String, val keywords: Set) -data class ContentSentiment(val description: String, val examples: List) -data class SentimentExample(val sentiment: Sentiment, val quotes: List) -data class CommentedQuote(val quote: String, val comment: String) +data class SentimentSummaryDto(val summary: String, val examples: List) +data class SentimentExampleDto(val sentiment: Sentiment, val quotes: List) +data class SentimentExampleQuoteDto(val quote: String, val explanation: String) data class ContentComparison(val description: String, val sourcesFacts: List) -data class SourceFacts(val url: String, val facts: List) - - - +data class SourceFacts(val url: String, val facts: Set) diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt index 7e31080..06227fc 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/ReportGenerationResult.kt @@ -1,3 +1,5 @@ package pl.edu.p.lodz.wiarygodnik.rgs.model.dto -data class ReportGenerationResult(val title: String, val content: String) +import pl.edu.p.lodz.wiarygodnik.rgs.model.CredibilityLevel + +data class ReportGenerationResult(val title: String, val content: String, val credibilityLevel: CredibilityLevel) diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt index 0219be6..596a6eb 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt @@ -4,8 +4,7 @@ import org.springframework.ai.chat.client.ChatClient import org.springframework.ai.chat.model.ChatModel import org.springframework.core.io.ResourceLoader import org.springframework.stereotype.Component -import pl.edu.p.lodz.wiarygodnik.rgs.model.Report -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult @Component @@ -13,7 +12,7 @@ class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader private val chatClient = ChatClient.create(chatModel) - fun generate(input: AnalysisResult): ReportGenerationResult { + fun generate(input: AnalysisResultMessage): ReportGenerationResult { val analysisReportGenerationPrompt: String = prepareAnalysisReportGenerationPrompt(input) return callChatGeneration(analysisReportGenerationPrompt) } @@ -31,9 +30,9 @@ class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader .bufferedReader() .readText() - private fun prepareAnalysisReportGenerationPrompt(analysisResult: AnalysisResult): String = """ + private fun prepareAnalysisReportGenerationPrompt(analysisResult: AnalysisResultMessage): String = """ ### Analiza nacechowania: - ${analysisResult.contentAnalysis.sentiment.description} + ${analysisResult.contentAnalysis.sentiment.summary} ### Przykłady nacechowania: ${ @@ -56,18 +55,24 @@ class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader } } + ${ + analysisResult.contentComparison?.let { + """ ### Porównanie z innymi źródłami: - ${analysisResult.contentComparison.description} - + ${it.description} + ### Przykłady porównań: ${ - analysisResult.contentComparison.sourcesFacts.map { source -> - """ + it.sourcesFacts.map { source -> + """ Źródło: ${source.url} Fakty: ${source.facts.joinToString { it }} """.trimIndent() + } + } + """ } } """.trimIndent() diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt index 8fd8d6e..515848e 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt @@ -6,7 +6,7 @@ import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.FAILED import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.GENERATED -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult import pl.edu.p.lodz.wiarygodnik.rgs.repo.ReportRepository import pl.edu.p.lodz.wiarygodnik.rgs.security.PrincipalProvider @@ -19,7 +19,7 @@ class ReportService( private val log = KotlinLogging.logger {} - fun createReport(analysisResult: AnalysisResult) { + fun createReport(analysisResult: AnalysisResultMessage) { val newReport = Report.fromAnalysisResult(analysisResult) val persistedReport = reportRepository.save(newReport) log.info { "Initial report persisted to database [reportId: ${persistedReport.id}, requestId: ${analysisResult.requestId}]" } diff --git a/report-generation-service/src/main/resources/logback-spring.xml b/report-generation-service/src/main/resources/logback-spring.xml index 0a50deb..7de0c95 100644 --- a/report-generation-service/src/main/resources/logback-spring.xml +++ b/report-generation-service/src/main/resources/logback-spring.xml @@ -5,7 +5,7 @@ - %d{HH:mm:ss} %-5level - %msg%n + %white(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%C{1}): %msg%n%throwable diff --git a/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt b/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt index bd0798a..f6084e4 100644 --- a/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt +++ b/report-generation-service/src/main/resources/prompts/analysis_report_generation_system.txt @@ -1,25 +1,59 @@ -Jesteś systemem generującym zwięzłe, informacyjne raporty na podstawie analizy nacechowania tekstu (z przykładami) oraz porównania innych źródeł z oryginalnym tekstem. +# SYSTEM PROMPT — GENEROWANIE RAPORTU WIARYGODNOŚCI ŹRÓDŁA +Jesteś systemem generującym **zwięzłe, lecz pogłębione raporty informacyjne** na podstawie: +- **analizy nacechowania tekstu** (z przykładami), +- **porównania treści z innymi, podobnymi źródłami**. + +**CAŁY wygenerowany tekst MUSI być ZAWSZE w języku polskim.** +Nie wolno używać żadnego innego języka. + +## Dane wejściowe Otrzymasz: -- szczegółową analizę nacechowania tekstu (z opisem ogólnego tonu oraz przykładami cytatów wraz z komentarzami), -- wynik porównania kilku źródeł (opis zgodności i rozbieżności pomiędzy źródłami oraz wskazania, które informacje zostały potwierdzone, uzupełnione lub zanegowane przez konkretne źródła). +- szczegółową analizę nacechowania tekstu (opis ogólnego tonu, dominujących cech językowych oraz przykłady wraz z komentarzami), +- wynik porównania kilku źródeł (opis zgodności i rozbieżności pomiędzy źródłami oraz wskazanie informacji potwierdzonych, uzupełnionych lub zakwestionowanych przez konkretne źródła). + +## Zadania systemu + +### 1. Tytuł raportu +Wygeneruj **tytuł raportu**, który: +- składa się z **maksymalnie 5 słów**, +- opisuje **wyłącznie temat oryginalnego źródła**, +- nie odnosi się do analizy, tonu, porównań ani wiarygodności, +- jest neutralny, rzeczowy i informacyjny, +- nie zawiera ocen, emocji ani sensacyjnych sformułowań, +- nie jest pytaniem ani poleceniem, +- jest napisany **wyłącznie po polsku**. -Twoje zadanie: +### 2. Podsumowanie raportu +Wygeneruj **podsumowanie raportu (5–8 zdań)**, które: +- opisuje ogólne nacechowanie tekstu i jego wpływ na odbiór treści, +- odnosi się do cech językowych wskazanych w analizie nacechowania, +- łączy wnioski z analizy nacechowania z wynikami porównania źródeł, +- wskazuje, które informacje są potwierdzane, uzupełniane lub kwestionowane przez inne źródła, +- opisuje stopień spójności treści z materiałami porównawczymi, +- formułuje ostrożne, rzeczowe wnioski dotyczące możliwej wiarygodności przekazu, +- nie zawiera cytatów ani dosłownych fragmentów analizy. -1. **Wygeneruj tytuł raportu**, który: - - składa się z **maksymalnie 5 słów**, - - opisuje **wyłącznie temat oryginalnego źródła**, bez odniesień do analizy, tonu, wiarygodności ani porównań, - - jest neutralny, rzeczowy i informacyjny, - - nie zawiera ocen, emocji, sensacji ani sugestii wniosków, - - nie używa pytań ani trybu rozkazującego, - - użyj tylko języka polskiego. +### 3. Ocena wiarygodności źródła +Na podstawie **całości dostarczonej analizy** (nacechowanie + porównanie źródeł) określ poziom wiarygodności źródła. +Dozwolone są **WYŁĄCZNIE** następujące wartości: +- `HIGH` – treść w dużej mierze neutralna lub informacyjna, a kluczowe informacje są potwierdzone przez niezależne źródła; brak istotnych rozbieżności. +- `MEDIUM` – treść zawiera elementy nacechowania lub uproszczeń, a informacje są częściowo potwierdzone lub uzupełniane; występują ograniczone rozbieżności. +- `LOW` – treść silnie nacechowana, emocjonalna lub sugestywna, a istotne informacje są kwestionowane, niespójne lub niepotwierdzone przez inne źródła. -2. **Wygeneruj krótkie podsumowanie** (3–6 zdań), które: - - jasno i treściwie opisuje ogólne nacechowanie tekstu oraz jego wpływ na odbiór i potencjalną wiarygodność treści, - - wskazuje, czy oraz które cechy nacechowania mają odzwierciedlenie w analizie porównawczej z innymi źródłami, - - informuje, czy informacje przedstawione w tekście są potwierdzane, uzupełniane czy kwestionowane przez źródła porównawcze, - - zawiera rzeczowe wnioski dotyczące spójności przekazu i możliwej wiarygodności treści, wyłącznie w oparciu o dostarczone analizy. +**Musisz wybrać dokładnie jedną wartość: `HIGH`, `MEDIUM` albo `LOW`.** +Nie wolno stosować innych skal ani wartości pośrednich. -3. **Nie kopiuj pełnych cytatów ani fragmentów z analizy** – prezentuj wnioski własnymi słowami na podstawie dostarczonych danych. +### 4. Uzasadnienie oceny +Uzasadnij ocenę wiarygodności w **2–4 zdaniach**, przy czym: +- odwołuj się wyłącznie do wyników analizy nacechowania i porównania źródeł, +- nie oceniaj intencji autora, +- nie spekuluj, +- nie używaj języka emocjonalnego, +- nie powtarzaj dosłownie treści podsumowania. -4. **Nie oceniaj wiarygodności na podstawie osobistych sądów** – odnoś się wyłącznie do konkluzji wynikających z analizy nacechowania oraz porównania źródeł. +## Zasady ogólne +- nie dodawaj własnej wiedzy ani opinii spoza dostarczonych danych, +- nie kopiuj cytatów ani fragmentów analizy, +- zachowuj styl raportowy i neutralny, +- **cały wynik musi być w języku polskim**. diff --git a/wiarygodnik_frontend/src/features/report/api/analysis.api.ts b/wiarygodnik_frontend/src/features/report/api/analysis.api.ts index 75110dc..5f800e2 100644 --- a/wiarygodnik_frontend/src/features/report/api/analysis.api.ts +++ b/wiarygodnik_frontend/src/features/report/api/analysis.api.ts @@ -1,4 +1,5 @@ import { useHttpClient } from '../../../hooks/useHttpClient'; +import { SentimentType } from '../domain/SentimentType'; export interface AnalyseRequest { url: string; @@ -12,6 +13,48 @@ export interface AnalysisStatusResponse { status: string; } +export interface ContentSummarization { + description: string; + keywords: string[]; +} + +export interface SentimentQuote { + quote: string; + explanation: string; +} + +export interface SentimentGroup { + sentiment: typeof SentimentType; + quotes: SentimentQuote[]; +} + +export interface SentimentAnalysis { + summary: string; + examples: SentimentGroup[]; +} + +export interface ContentAnalysis { + summarization: ContentSummarization; + sentiment: SentimentAnalysis; +} + +export interface SourceFacts { + url: string; + facts: string[]; +} + +export interface ContentComparison { + description: string; + sourcesFacts: SourceFacts[]; +} + +export interface AnalysisData { + requestId: string; + sourceUrl: string; + contentAnalysis: ContentAnalysis; + contentComparison: ContentComparison; +} + const API_ANALYSIS_PATH = '/api/analysis'; export const useAnalysisApi = () => { @@ -22,10 +65,15 @@ export const useAnalysisApi = () => { return response.data; }; - const getAnalysisStatus = async (requestId: string): Promise => { + const getMyAnalysisStatus = async (requestId: string): Promise => { const response = await http.get(`${API_ANALYSIS_PATH}/status/${requestId}`); return response.data; }; - return { analyseSource, getAnalysisStatus }; + const getMyAnalysis = async (requestId: string): Promise => { + const response = await http.get(`${API_ANALYSIS_PATH}/${requestId}`); + return response.data; + } + + return { analyseSource, getMyAnalysisStatus, getMyAnalysis }; }; diff --git a/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx b/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx new file mode 100644 index 0000000..510e00b --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx @@ -0,0 +1,33 @@ +import { Box, Typography, Link } from "@mui/material"; +import type { ContentComparison } from "../api/analysis.api"; +import { getDomain } from "../../../lib/domainExtractor"; + +interface ContentComparisonPartProps { + contentComparison: ContentComparison; +} + +export const ContentComparisonPart = ({ contentComparison }: ContentComparisonPartProps) => ( + + + Porównanie z innymi źródłami + + + {contentComparison.description} + + {contentComparison.sourcesFacts.map((src, i) => ( + + + {getDomain(src.url)} + + +
    + {src.facts.map((fact, j) => ( +
  • + {fact} +
  • + ))} +
+
+ ))} +
+); diff --git a/wiarygodnik_frontend/src/features/report/components/ContentSummaryPart.tsx b/wiarygodnik_frontend/src/features/report/components/ContentSummaryPart.tsx new file mode 100644 index 0000000..20481fb --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/components/ContentSummaryPart.tsx @@ -0,0 +1,24 @@ +import { Box, Chip, Typography } from "@mui/material"; +import type { ContentSummarization } from "../api/analysis.api"; + +interface ContentSummaryPartProps { + contentSummary: ContentSummarization; +} + +export const ContentSummaryPart = ({ contentSummary }: ContentSummaryPartProps) => ( + + + Podsumowanie treści + + + + {contentSummary.description} + + + + {contentSummary.keywords.map((k, i) => ( + + ))} + + +); diff --git a/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx index db630a7..e6d333d 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx @@ -8,16 +8,22 @@ import { getDomain } from "../../../lib/domainExtractor.ts"; import { sourceDot, sourceLink } from "../../../Style.tsx"; import type { ReportContentResponse } from "../api/report.api.ts"; import { ReportCredability } from "./ReportCredability.tsx"; +import { ContentSummaryPart } from "./ContentSummaryPart.tsx"; +import { SentimentAnalysisPart } from "./SentimentAnalysisPart.tsx"; +import { ContentComparisonPart } from "./ContentComparisonPart.tsx"; +import type { AnalysisData } from "../api/analysis.api.ts"; +import { ReportPart } from "./ReportPart.tsx"; interface ReportContentProps { report?: ReportContentResponse; + analysis?: AnalysisData; } -export const ReportContent = ({ report }: ReportContentProps) => { +export const ReportContent = ({ report, analysis }: ReportContentProps) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); - - if (!report) { + + if (!report || !analysis) { return <>; } @@ -28,49 +34,49 @@ export const ReportContent = ({ report }: ReportContentProps) => { const reportCreadabilityLevel = report.credibilityLevel; return ( - - - - - - - {reportTitle} - - - - - Analizowane źródło - - - - - {getDomain(analyzedSource)} - - - - - - - Znalezione źródła - - { - similarSourceUrls.map((source, index) => ( - - - - {getDomain(source)} - - - )) - } - + + + + + + + {reportTitle} - - Raport - - {reportContent} - + + + + Analizowane źródło + + + + + {getDomain(analyzedSource)} + + + + + + Znalezione źródła + + { + similarSourceUrls.map((source, index) => ( + + + + {getDomain(source)} + + + )) + } + + + + + + + {analysis.contentComparison && } + ); } \ No newline at end of file diff --git a/wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx b/wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx index 65dc792..9ecb873 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportLoading.tsx @@ -1,5 +1,6 @@ import { Box, CircularProgress, Typography } from "@mui/material"; import theme from "../../../theme"; +import { mapAnalysisStatus } from "../lib/AnalysisStatusMapper"; interface ReportLoadingProps { loadingStatus?: string; @@ -14,7 +15,7 @@ export const ReportLoading = ({ loadingStatus }: ReportLoadingProps) => { }}> - {loadingStatus} + {loadingStatus && mapAnalysisStatus(loadingStatus)} ); diff --git a/wiarygodnik_frontend/src/features/report/components/ReportPart.tsx b/wiarygodnik_frontend/src/features/report/components/ReportPart.tsx new file mode 100644 index 0000000..a06a0f4 --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/components/ReportPart.tsx @@ -0,0 +1,17 @@ +import { Box, Typography } from "@mui/material"; + +interface ReportPartProps { + content: string; +} + +export const ReportPart = ({ content }: ReportPartProps) => ( + + + Raport z analizy + + + + {content} + + +); diff --git a/wiarygodnik_frontend/src/features/report/components/SentimentAnalysisPart.tsx b/wiarygodnik_frontend/src/features/report/components/SentimentAnalysisPart.tsx new file mode 100644 index 0000000..2356fbd --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/components/SentimentAnalysisPart.tsx @@ -0,0 +1,47 @@ +import { + Accordion, + AccordionSummary, + AccordionDetails, + Typography, + Box +} from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import type { SentimentAnalysis } from "../api/analysis.api"; +import { mapSentimentType } from "../lib/sentimentTypeMapper"; + +interface SentimentAnalysisPartProps { + sentimentAnalysis: SentimentAnalysis; +} + +export const SentimentAnalysisPart = ({ sentimentAnalysis }: SentimentAnalysisPartProps) => ( + + + Analiza sentymentu + + + {sentimentAnalysis.summary} + + {sentimentAnalysis.examples.map((group, i) => ( + + }> + + {mapSentimentType(String(group.sentiment))} + + + + + {group.quotes.map((q, j) => ( + + + „{q.quote}” + + + {q.explanation} + + + ))} + + + ))} + +); diff --git a/wiarygodnik_frontend/src/features/report/domain/CredibilityLevel.ts b/wiarygodnik_frontend/src/features/report/domain/CredibilityLevel.ts new file mode 100644 index 0000000..ecbed4c --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/domain/CredibilityLevel.ts @@ -0,0 +1,5 @@ +export type CredibilityLevel = { + LOW: "LOW", + MEDIUM: "MEDIUM", + HIGH: "HIGH", +} diff --git a/wiarygodnik_frontend/src/features/report/domain/SentimentType.ts b/wiarygodnik_frontend/src/features/report/domain/SentimentType.ts new file mode 100644 index 0000000..db1156e --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/domain/SentimentType.ts @@ -0,0 +1,10 @@ +export const SentimentType = { + POSITIVE: "POSITIVE", + NEUTRAL: "NEUTRAL", + NEGATIVE: "NEGATIVE", + ALARMIST: "ALARMIST", + IRONIC: "IRONIC", + PERSUASIVE: "PERSUASIVE", + AGGRESSIVE: "AGGRESSIVE", + FORMAL: "FORMAL" +} diff --git a/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts b/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts new file mode 100644 index 0000000..6eae283 --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts @@ -0,0 +1,20 @@ +import { useEffect, useState } from 'react'; +import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; +import { useAnalysisApi, type AnalysisData } from '../api/analysis.api.ts'; + +export const useAnalysis = (requestId: string | undefined, status: string | undefined) => { + const { getMyAnalysis } = useAnalysisApi(); + + const [analysis, setAnalysis] = useState(undefined); + + useEffect(() => { + if (!requestId || (status !== AnalysisStatus.GENERATED)) { + setAnalysis(undefined); + return; + } + + getMyAnalysis(requestId).then(setAnalysis); + }, [requestId, status]); + + return analysis; +}; diff --git a/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts b/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts index 9445bcc..15cb556 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts @@ -4,7 +4,7 @@ import { useReportApi, type ReportStatusResponse } from '../api/report.api'; import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; export const useAnalysisStatus = (requestId: string | undefined) => { - const { getAnalysisStatus } = useAnalysisApi(); + const { getMyAnalysisStatus } = useAnalysisApi(); const { getMyReportStatus } = useReportApi(); const [status, setStatus] = useState(undefined); @@ -22,7 +22,7 @@ export const useAnalysisStatus = (requestId: string | undefined) => { let analysisCompleted: boolean = false; while (active) { if (!analysisCompleted) { - const res: AnalysisStatusResponse = await getAnalysisStatus(requestId); + const res: AnalysisStatusResponse = await getMyAnalysisStatus(requestId); setStatus(res.status); if (res.status === AnalysisStatus.COMPLETED) { analysisCompleted = true; diff --git a/wiarygodnik_frontend/src/features/report/lib/analysisStatusMapper.ts b/wiarygodnik_frontend/src/features/report/lib/analysisStatusMapper.ts new file mode 100644 index 0000000..652d1ac --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/lib/analysisStatusMapper.ts @@ -0,0 +1,20 @@ +import { AnalysisStatus } from "../domain/AnalysisStatus"; + +export const mapAnalysisStatus = (status: string) => { + switch (status) { + case AnalysisStatus.ANALYSISNG_CONTENT: + return "Analizowanie treści źródła"; + case AnalysisStatus.COMPARING_SIMILAR_SOURCES: + return "Porównywanie z podobnymi źródłami"; + case AnalysisStatus.COMPLETED: + return "Analiza zakończona"; + case AnalysisStatus.GENERATING: + return "Generowanie raportu"; + case AnalysisStatus.GENERATED: + return "Raport wygenerowany"; + case AnalysisStatus.FAILED: + return "Analiza nie powiodła się"; + default: + return "Nieznany status"; + } +}; \ No newline at end of file diff --git a/wiarygodnik_frontend/src/features/report/lib/sentimentTypeMapper.ts b/wiarygodnik_frontend/src/features/report/lib/sentimentTypeMapper.ts new file mode 100644 index 0000000..c097939 --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/lib/sentimentTypeMapper.ts @@ -0,0 +1,24 @@ +import { SentimentType } from "../domain/SentimentType"; + +export const mapSentimentType = (status: string) => { + switch (status) { + case SentimentType.POSITIVE: + return "Pozytywny"; + case SentimentType.NEGATIVE: + return "Negatywny"; + case SentimentType.NEUTRAL: + return "Neutralny"; + case SentimentType.ALARMIST: + return "Alarmistyczny"; + case SentimentType.IRONIC: + return "Ironiczny"; + case SentimentType.PERSUASIVE: + return "Perswazyjny"; + case SentimentType.AGGRESSIVE: + return "Agresywny"; + case SentimentType.FORMAL: + return "Formalny"; + default: + return "Nieznany typ sentymentu"; + } +}; \ No newline at end of file diff --git a/wiarygodnik_frontend/src/layout/NavBar.tsx b/wiarygodnik_frontend/src/layout/NavBar.tsx index e0e9866..77b5d71 100644 --- a/wiarygodnik_frontend/src/layout/NavBar.tsx +++ b/wiarygodnik_frontend/src/layout/NavBar.tsx @@ -49,7 +49,7 @@ function NavBar(props: NavBarProps) { {authenticated ? location.pathname.startsWith("/reports") ? ( - diff --git a/wiarygodnik_frontend/src/pages/Reports.tsx b/wiarygodnik_frontend/src/pages/Reports.tsx index 70bf7a9..baf314d 100644 --- a/wiarygodnik_frontend/src/pages/Reports.tsx +++ b/wiarygodnik_frontend/src/pages/Reports.tsx @@ -11,6 +11,7 @@ import { ReportContent } from "../features/report/components/ReportContent.tsx"; import { ReportLoading } from "../features/report/components/ReportLoading.tsx"; import { enqueueSnackbar } from "notistack"; import { AnalysisStatus } from "../features/report/domain/AnalysisStatus.ts"; +import { useAnalysis } from "../features/report/hooks/useAnalysis.ts"; function Reports() { const isMobile = useIsMobile(); @@ -19,6 +20,7 @@ function Reports() { const { requestId } = useParams(); const status = useAnalysisStatus(requestId); const report = useReport(requestId, status); + const analysis = useAnalysis(requestId, status); const [menuActive, setMenuActive] = useState(!isMobile); @@ -35,7 +37,7 @@ function Reports() { {menuActive && } - {report ? : status ? : } + {report && analysis ? : status ? : } From 9f8d4ff520bc1be9276e355ea0fc5b78e3fc373f Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Thu, 1 Jan 2026 21:54:18 +0100 Subject: [PATCH 05/15] Fix layout for Reports page --- .../report/components/ReportContent.tsx | 20 ++++++++----------- wiarygodnik_frontend/src/pages/Reports.tsx | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx index e6d333d..3628d40 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx @@ -27,20 +27,16 @@ export const ReportContent = ({ report, analysis }: ReportContentProps) => { return <>; } - const analyzedSource = report.sourceUrl; - const similarSourceUrls = report.similarSourceUrls; - const reportTitle = report.title; - const reportContent = report.content; - const reportCreadabilityLevel = report.credibilityLevel; + const similarSourceUrls = analysis.contentComparison.sourcesFacts.map(sourceFact => sourceFact.url); return ( - + - + - {reportTitle} + {report.title} @@ -49,8 +45,8 @@ export const ReportContent = ({ report, analysis }: ReportContentProps) => { - - {getDomain(analyzedSource)} + + {getDomain(report.sourceUrl)} @@ -71,8 +67,8 @@ export const ReportContent = ({ report, analysis }: ReportContentProps) => { } - - + + {analysis.contentComparison && } diff --git a/wiarygodnik_frontend/src/pages/Reports.tsx b/wiarygodnik_frontend/src/pages/Reports.tsx index baf314d..70e5ffc 100644 --- a/wiarygodnik_frontend/src/pages/Reports.tsx +++ b/wiarygodnik_frontend/src/pages/Reports.tsx @@ -34,7 +34,7 @@ function Reports() { return ( <> - + {menuActive && } {report && analysis ? : status ? : } From 4edbc26bf1c13a4e7c66bd39b11185654dba5ab9 Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Fri, 2 Jan 2026 22:24:46 +0100 Subject: [PATCH 06/15] Prepare initial configuration for startup & configure dockerized infrastracture --- .env | 2 + ContentFetcher/.gitignore | 86 - ContentFetcher/README.md | 190 -- ContentFetcher/content_fetcher/.env.example | 11 - ContentFetcher/content_fetcher/Dockerfile | 19 - ContentFetcher/content_fetcher/alembic.ini | 141 - ContentFetcher/content_fetcher/alembic/README | 1 - ContentFetcher/content_fetcher/alembic/env.py | 97 - .../content_fetcher/alembic/script.py.mako | 28 - .../0e3352f50b1f_create_contents_table.py | 42 - ...pdate_content_table_changed_user_id_to_.py | 34 - ...b0e0bdd22d71_contents_extend_url_length.py | 38 - .../content_fetcher/app/__init__.py | 0 ContentFetcher/content_fetcher/app/config.py | 12 - ContentFetcher/content_fetcher/app/db.py | 11 - ContentFetcher/content_fetcher/app/logging.py | 16 - ContentFetcher/content_fetcher/app/main.py | 127 - .../content_fetcher/app/messaging/__init__.py | 0 .../content_fetcher/app/messaging/rabbit.py | 188 -- ContentFetcher/content_fetcher/app/models.py | 13 - ContentFetcher/content_fetcher/app/schemas.py | 13 - .../content_fetcher/app/services/__init__.py | 0 .../content_fetcher/app/services/fetcher.py | 0 .../content_fetcher/app/tests/__init__.py | 0 .../content_fetcher/app/tests/test_main.py | 0 .../content_fetcher/requirements.txt | 14 - ContentFetcher/docker-compose.yml | 38 - CredabilityService/.gitattributes | 2 - CredabilityService/.gitignore | 33 - .../.mvn/wrapper/maven-wrapper.properties | 19 - CredabilityService/Dockerfile | 10 - CredabilityService/docker-compose.yml | 44 - CredabilityService/mvnw | 259 -- CredabilityService/mvnw.cmd | 149 - CredabilityService/pom.xml | 87 - .../CredabilityServiceApplication.java | 13 - .../application/UrlContent.java | 6 - .../application/UrlService.java | 70 - .../presentation/CredabilityController.java | 42 - .../presentation/RabbitConfig.java | 66 - .../presentation/RabbitConsumer.java | 27 - .../presentation/RabbitProducer.java | 28 - .../presentation/UrlContentDTO.java | 6 - .../presentation/UrlsListDTO.java | 6 - .../storage/UrlsPostgresJpaRepository.java | 14 - .../storage/UrlsRecord.java | 34 - .../storage/UrlsRepository.java | 28 - .../src/main/resources/application.properties | 18 - .../src/main/resources/logback-spring.xml | 23 - .../CredabilityServiceApplicationTests.java | 13 - README.md | 17 + content-analysis-service/build.gradle.kts | 5 +- .../wiarygodnik/cas/config/CorsProperties.kt | 13 + .../cas/model/ComparisonSummary.kt | 2 +- .../wiarygodnik/cas/model/SentimentSummary.kt | 2 +- .../wiarygodnik/cas/model/SourceSummary.kt | 2 +- .../wiarygodnik/cas/security/CorsConfig.kt | 26 +- .../cas/service/AnalysisProcessor.kt | 1 + .../src/main/resources/application.yml | 35 +- .../main/resources/initial-db/analysis.sql | 3 + .../initial-db/comparison_source_facts.sql | 11 + .../initial-db/comparison_summary.sql | 3 + .../initial-db/sentiment_example.sql | 9 + .../initial-db/sentiment_example_quote.sql | 12 + .../initial-db/sentiment_summary.sql | 3 + .../resources/initial-db/source_facts.sql | 26 + .../resources/initial-db/source_keywords.sql | 28 + .../resources/initial-db/source_summary.sql | 3 + docker-compose.yml | 112 +- elk/docker-compose.yml | 4 +- keycloak/wiarygodnik-realm.json | 2617 +++++++++++++++++ load-balancer/conf.d/nginx.conf | 12 +- report-generation-service/build.gradle.kts | 9 +- .../wiarygodnik/rgs/amqp/RabbitMqConsumer.kt | 4 +- .../wiarygodnik/rgs/config/CorsProperties.kt | 13 + .../rgs/controller/ReportController.kt | 2 +- .../controller/dto/ReportContentResponse.kt | 6 +- .../p/lodz/wiarygodnik/rgs/model/Report.kt | 13 +- .../wiarygodnik/rgs/model/SimilarSource.kt | 14 - .../wiarygodnik/rgs/repo/ReportRepository.kt | 1 + .../wiarygodnik/rgs/security/CorsConfig.kt | 26 +- .../wiarygodnik/rgs/service/ReportService.kt | 28 +- .../src/main/resources/application.yml | 22 + .../src/main/resources/initial-db/report.sql | 3 + .../wiarygodnik/ReportApplicationTests.kt | 2 + wiarygodnik_frontend/.env | 3 +- wiarygodnik_frontend/.env.production | 1 + wiarygodnik_frontend/Dockerfile | 25 + wiarygodnik_frontend/nginx.conf | 10 + wiarygodnik_frontend/package-lock.json | 421 ++- wiarygodnik_frontend/package.json | 2 +- .../features/report/components/ReportList.tsx | 8 +- .../report/components/ReportLoading.tsx | 2 +- .../report/hooks/useAnalysisStatus.ts | 21 +- .../features/report/hooks/useReportList.ts | 4 +- wiarygodnik_frontend/src/pages/Reports.tsx | 2 +- 96 files changed, 3326 insertions(+), 2380 deletions(-) create mode 100644 .env delete mode 100644 ContentFetcher/.gitignore delete mode 100644 ContentFetcher/README.md delete mode 100644 ContentFetcher/content_fetcher/.env.example delete mode 100644 ContentFetcher/content_fetcher/Dockerfile delete mode 100644 ContentFetcher/content_fetcher/alembic.ini delete mode 100644 ContentFetcher/content_fetcher/alembic/README delete mode 100644 ContentFetcher/content_fetcher/alembic/env.py delete mode 100644 ContentFetcher/content_fetcher/alembic/script.py.mako delete mode 100644 ContentFetcher/content_fetcher/alembic/versions/0e3352f50b1f_create_contents_table.py delete mode 100644 ContentFetcher/content_fetcher/alembic/versions/267ff639f45d_update_content_table_changed_user_id_to_.py delete mode 100644 ContentFetcher/content_fetcher/alembic/versions/b0e0bdd22d71_contents_extend_url_length.py delete mode 100644 ContentFetcher/content_fetcher/app/__init__.py delete mode 100644 ContentFetcher/content_fetcher/app/config.py delete mode 100644 ContentFetcher/content_fetcher/app/db.py delete mode 100644 ContentFetcher/content_fetcher/app/logging.py delete mode 100644 ContentFetcher/content_fetcher/app/main.py delete mode 100644 ContentFetcher/content_fetcher/app/messaging/__init__.py delete mode 100644 ContentFetcher/content_fetcher/app/messaging/rabbit.py delete mode 100644 ContentFetcher/content_fetcher/app/models.py delete mode 100644 ContentFetcher/content_fetcher/app/schemas.py delete mode 100644 ContentFetcher/content_fetcher/app/services/__init__.py delete mode 100644 ContentFetcher/content_fetcher/app/services/fetcher.py delete mode 100644 ContentFetcher/content_fetcher/app/tests/__init__.py delete mode 100644 ContentFetcher/content_fetcher/app/tests/test_main.py delete mode 100644 ContentFetcher/content_fetcher/requirements.txt delete mode 100644 ContentFetcher/docker-compose.yml delete mode 100644 CredabilityService/.gitattributes delete mode 100644 CredabilityService/.gitignore delete mode 100644 CredabilityService/.mvn/wrapper/maven-wrapper.properties delete mode 100644 CredabilityService/Dockerfile delete mode 100644 CredabilityService/docker-compose.yml delete mode 100644 CredabilityService/mvnw delete mode 100644 CredabilityService/mvnw.cmd delete mode 100644 CredabilityService/pom.xml delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplication.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlContent.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlService.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/CredabilityController.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConfig.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConsumer.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitProducer.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlContentDTO.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlsListDTO.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsPostgresJpaRepository.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRecord.java delete mode 100644 CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRepository.java delete mode 100644 CredabilityService/src/main/resources/application.properties delete mode 100644 CredabilityService/src/main/resources/logback-spring.xml delete mode 100644 CredabilityService/src/test/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplicationTests.java create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/CorsProperties.kt create mode 100644 content-analysis-service/src/main/resources/initial-db/analysis.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/comparison_summary.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/sentiment_example.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/source_facts.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/source_keywords.sql create mode 100644 content-analysis-service/src/main/resources/initial-db/source_summary.sql create mode 100644 keycloak/wiarygodnik-realm.json create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/CorsProperties.kt delete mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt create mode 100644 report-generation-service/src/main/resources/initial-db/report.sql create mode 100644 wiarygodnik_frontend/.env.production create mode 100644 wiarygodnik_frontend/Dockerfile create mode 100644 wiarygodnik_frontend/nginx.conf diff --git a/.env b/.env new file mode 100644 index 0000000..12c6508 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +JINA_API_KEY= +SERPAPI_API_KEY= \ No newline at end of file diff --git a/ContentFetcher/.gitignore b/ContentFetcher/.gitignore deleted file mode 100644 index 66a615e..0000000 --- a/ContentFetcher/.gitignore +++ /dev/null @@ -1,86 +0,0 @@ -### PyCharm+all template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# Don't add pycharm project files to git -.idea/* -.venv/* - -# Don't add environment files to git -.env - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# AWS User-specific -.idea/**/aws.xml - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -# .idea/artifacts -# .idea/compiler.xml -# .idea/jarRepositories.xml -# .idea/modules.xml -# .idea/*.iml -# .idea/modules -# *.iml -# *.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# SonarLint plugin -.idea/sonarlint/ - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - diff --git a/ContentFetcher/README.md b/ContentFetcher/README.md deleted file mode 100644 index c404bd4..0000000 --- a/ContentFetcher/README.md +++ /dev/null @@ -1,190 +0,0 @@ -# Content Fetcher Service - -> Mikroserwis Projektu **Wiarygodnik** odpowiedzialny za pobieranie treści stron WWW, ekstrakcję słów kluczowych i publikowanie wyniku w architekturze event‑driven (RabbitMQ). - ---- - -## Spis treści - -1. [Wymagania](#wymagania) -2. [Szybki start](#szybki-start) -3. [Plik ](#plik-env)[`.env`](#plik-env) -4. [Struktura projektu](#struktura-projektu) -5. [Format komunikatów](#format-komunikatów) -6. [Przydatne komendy](#przydatne-komendy) -7. [Jak podejrzeć bazę danych](#jak-podejrzeć-bazę-danych) - ---- - -## Wymagania - -- **Docker 20.10+** -- **Docker Compose v2** (wbudowany w Docker Desktop) --  Plik `.env` w katalogu `content_fetcher/` (może być skopiowany z `.env.example`). - ---- - -## Szybki start - -```bash -# 1. Klonujesz repozytorium (jeśli to zewnętrzny klon) -# git clone ... - -# 2. Uzupełniasz zmienne środowiskowe -cp content_fetcher/.env.example content_fetcher/.env -nano content_fetcher/.env # wstaw hasła / URL brokerów - -# 3. Budujesz i uruchamiasz wszystkie serwisy -docker compose up -d --build -``` - -Po kilku sekundach: - -- kontener **postgres** podnosi bazę i stosuje migracje Alembic, -- kontener **content\_fetcher** słucha kolejki `content.fetch.request` oraz wystawia HTTP (`8090`). - ---- - -## Plik `.env` - -| Klucz | Opis | Przykład | -| ------------------------ | -------------------------------- | ------------------------------------------------------------------------ | -| `DATABASE_URL` | URL do bazy PostgreSQL (asyncpg) | `postgresql+asyncpg://wiarygodnik:secret@postgres:5432/contentfetcherdb` | -| `RABBITMQ_URL` | Adres brokera | `amqp://guest:guest@rabbitmq:5672/` | -| `RABBITMQ_REQUEST_QUEUE` | Kolejka wejściowa | `content.fetch.request` | -| `RABBITMQ_RESULT_QUEUE` | Kolejka wyjściowa | `content.fetch.result` | -| `RABBITMQ_EXCHANGE` | Exchange typu **direct** | `content.events` | - ---- - -## Struktura projektu - -``` -Content-Fetcher/ -├── docker-compose.yml # konfiguracja Docker Compose -└── content_fetcher/ - ├── alembic/ # migracje bazy (kopiowane do obrazu) - │   └── versions/ … - ├── app/ - │   ├── main.py # FastAPI + lifespan - │   ├── messaging/ # kod RabbitMQ (aio‑pika) - │   ├── services/ # logika biznesowa - │   ├── models.py # SQLAlchemy ORM - │   ├── schemas.py # Pydantic - │   └── db.py # sesja AsyncSession - ├── requirements.txt # zależności Pythona - ├── .env # plik konfiguracyjny (wymagany) - ├── alembic.ini # konfiguracja Alembica - └── Dockerfile -``` - -Migracje uruchamiają się automatycznie przy starcie kontenera dzięki poleceniu - -```sh -alembic upgrade head -``` - ---- - -## Format komunikatów - -### Wejście → kolejka `content.fetch.request` - -Lista **1..N** obiektów: - -```json -[ - {"url": "https://www.lipsum.com/feed/html", "report_id": "rep1"}, - {"url": "https://example.com"}, - {"url": "https://bad.example.com"} -] -``` - -`url` – max 1000 znaków,\ -`report_id` – opcjonalnie, max 50 znaków. - -### Wyjście ← kolejka `content.fetch.result` - -Również lista; dla każdego elementu wejściowego zwracamy: - -```json -[ - { - "url": "https://www.lipsum.com/feed/html", - "keywords": ["keyword1", "keyword2", "keyword3"], - "content": "Lorem ipsum dolor sit amet…", - "report_id": "rep1" - }, - { - "url": "https://example.com", - "keywords": ["keyword1", "keyword2", "keyword3"], - "content": "Lorem ipsum dolor sit amet…", - "report_id": null - }, - { - "status": "error", - "reason": "404 Client Error: Not Found for url", - "url": "https://bad.example.com", - "report_id": null - } -] -``` - -Sukces → pełny `FetchResponse`.\ -Błąd (sieć / DB / duplicate) → obiekt z `status` i `reason`. - ---- - -## Przydatne komendy - -```bash -# zatrzymaj i usuń kontenery (+ sieci, ale bez wolumenów) -docker compose down - -# wyczyść kontenery i wolumen (uwaga: traci się dane) -docker compose down -v - -# podejrzyj logi tylko usługi content_fetcher -docker compose logs -f content_fetcher - -# ręczne wywołanie endpointu HTTP -auth_json='{"url": "https://example.com"}' -http POST localhost:8090/fetch url=https://example.com -``` - ---- - -## Jak podejrzeć bazę danych - -```bash -# wejdź do kontenera Postgresa -docker compose exec postgres bash - -# zaloguj się do bazy -psql -U wiarygodnik -d contentfetcherdb - -# sprawdź strukturę i dane -d+ web_contents; -- opis tabeli (struktura) -SELECT COUNT(*) FROM web_contents; -SELECT url, report_id FROM web_contents ORDER BY created_at DESC; -``` - -Wyjście z `psql` – polecenie `\q`; wyjście z kontenera – `exit`. - -> **Tip:** migracje Alembica są idempotentne – ponowny start kontenera nie psuje istniejącej bazy. - ---- - -## FAQ - -- **Czy muszę sam uruchamiać migracje?**\ - Nie – `alembic upgrade head` jest odpalane przy starcie `content_fetcher`. -- **Jak dodać nową kolumnę?** - 1. Zmień `models.py`, 2) `alembic revision --autogenerate -m "..."`, 3) `docker compose up -d --build`. -- **Jak przetestować RabbitMQ?**\ - Wejdź na `http://localhost:15672` (guest/guest) i użyj zakładki *Queues* → *Publish message*. - ---- - -> Projekt rozwijany w ramach **studiów magisterskich** 😉 - diff --git a/ContentFetcher/content_fetcher/.env.example b/ContentFetcher/content_fetcher/.env.example deleted file mode 100644 index 22003bd..0000000 --- a/ContentFetcher/content_fetcher/.env.example +++ /dev/null @@ -1,11 +0,0 @@ -DATABASE_URL=postgresql+asyncpg://POSTGRES_USER:POSTGRES_PASSWORD@postgres:PORT/contentfetcherdb -# Example: -# DATABASE_URL=postgresql+asyncpg://wiarygodnik:secret@postgres:5432/contentfetcherdb - -RABBITMQ_URL=amqp://RABBITMQ_DEFAULT_USER:RABBITMQ_DEFAULT_PASS@rabbitmq:AMQP_PORT/ -# Example: -# RABBITMQ_URL=amqp://guest:guest@rabbitmq:5672/ - -RABBITMQ_REQUEST_QUEUE=report.service.order.queue -RABBITMQ_RESULT_QUEUE=content.fetch.result -RABBITMQ_EXCHANGE=wiarygodnik.exchange diff --git a/ContentFetcher/content_fetcher/Dockerfile b/ContentFetcher/content_fetcher/Dockerfile deleted file mode 100644 index 4fe0b17..0000000 --- a/ContentFetcher/content_fetcher/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM python:3.13-slim - -LABEL version="1.0" -LABEL description="Content Fetcher Service" -LABEL org.opencontainers.image.authors="kacperjagodzinski@op.pl" -LABEL author="Kacper Jagodziński" - -WORKDIR /app - -COPY requirements.txt . - -RUN pip install --no-cache-dir -r requirements.txt - -COPY app/ ./app/ - -COPY alembic.ini . -COPY alembic/ ./alembic/ - -CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"] diff --git a/ContentFetcher/content_fetcher/alembic.ini b/ContentFetcher/content_fetcher/alembic.ini deleted file mode 100644 index 2e7a7e5..0000000 --- a/ContentFetcher/content_fetcher/alembic.ini +++ /dev/null @@ -1,141 +0,0 @@ -# A generic, single database configuration. - -[alembic] -# path to migration scripts. -# this is typically a path given in POSIX (e.g. forward slashes) -# format, relative to the token %(here)s which refers to the location of this -# ini file -script_location = ./alembic/ - -# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s -# Uncomment the line below if you want the files to be prepended with date and time -# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file -# for all available tokens -# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s - -# sys.path path, will be prepended to sys.path if present. -# defaults to the current working directory. for multiple paths, the path separator -# is defined by "path_separator" below. -prepend_sys_path = . - - -# timezone to use when rendering the date within the migration file -# as well as the filename. -# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library. -# Any required deps can installed by adding `alembic[tz]` to the pip requirements -# string value is passed to ZoneInfo() -# leave blank for localtime -# timezone = - -# max length of characters to apply to the "slug" field -# truncate_slug_length = 40 - -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate -# revision_environment = false - -# set to 'true' to allow .pyc and .pyo files without -# a source .py file to be detected as revisions in the -# versions/ directory -# sourceless = false - -# version location specification; This defaults -# to /versions. When using multiple version -# directories, initial revisions must be specified with --version-path. -# The path separator used here should be the separator specified by "path_separator" -# below. -# version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions - -# path_separator; This indicates what character is used to split lists of file -# paths, including version_locations and prepend_sys_path within configparser -# files such as alembic.ini. -# The default rendered in new alembic.ini files is "os", which uses os.pathsep -# to provide os-dependent path splitting. -# -# Note that in order to support legacy alembic.ini files, this default does NOT -# take place if path_separator is not present in alembic.ini. If this -# option is omitted entirely, fallback logic is as follows: -# -# 1. Parsing of the version_locations option falls back to using the legacy -# "version_path_separator" key, which if absent then falls back to the legacy -# behavior of splitting on spaces and/or commas. -# 2. Parsing of the prepend_sys_path option falls back to the legacy -# behavior of splitting on spaces, commas, or colons. -# -# Valid values for path_separator are: -# -# path_separator = : -# path_separator = ; -# path_separator = space -# path_separator = newline -# -# Use os.pathsep. Default configuration used for new projects. -path_separator = os - -# set to 'true' to search source files recursively -# in each "version_locations" directory -# new in Alembic version 1.10 -# recursive_version_locations = false - -# the output encoding used when revision files -# are written from script.py.mako -# output_encoding = utf-8 - -# database URL. This is consumed by the user-maintained env.py script only. -# other means of configuring database URLs may be customized within the env.py -# file. -sqlalchemy.url = driver://user:pass@localhost/dbname - - -[post_write_hooks] -# post_write_hooks defines scripts or Python functions that are run -# on newly generated revision scripts. See the documentation for further -# detail and examples - -# format using "black" - use the console_scripts runner, against the "black" entrypoint -# hooks = black -# black.type = console_scripts -# black.entrypoint = black -# black.options = -l 79 REVISION_SCRIPT_FILENAME - -# lint with attempts to fix using "ruff" - use the exec runner, execute a binary -# hooks = ruff -# ruff.type = exec -# ruff.executable = %(here)s/.venv/bin/ruff -# ruff.options = check --fix REVISION_SCRIPT_FILENAME - -# Logging configuration. This is also consumed by the user-maintained -# env.py script only. -[loggers] -keys = root,sqlalchemy,alembic - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARNING -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARNING -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = INFO -handlers = -qualname = alembic - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/ContentFetcher/content_fetcher/alembic/README b/ContentFetcher/content_fetcher/alembic/README deleted file mode 100644 index e0d0858..0000000 --- a/ContentFetcher/content_fetcher/alembic/README +++ /dev/null @@ -1 +0,0 @@ -Generic single-database configuration with an async dbapi. \ No newline at end of file diff --git a/ContentFetcher/content_fetcher/alembic/env.py b/ContentFetcher/content_fetcher/alembic/env.py deleted file mode 100644 index 44a47df..0000000 --- a/ContentFetcher/content_fetcher/alembic/env.py +++ /dev/null @@ -1,97 +0,0 @@ -import sys, os -sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) - -import asyncio -from logging.config import fileConfig - -from sqlalchemy import pool -from sqlalchemy.engine import Connection -from sqlalchemy.ext.asyncio import async_engine_from_config -from alembic import context - -from app.config import settings -from app.models import Base - -# this is the Alembic Config object, which provides -# access to the values within the .ini file in use. -config = context.config - -# Interpret the config file for Python logging. -# This line sets up loggers basically. -if config.config_file_name is not None: - fileConfig(config.config_file_name) - -# ustawiamy URL z .env -config.set_main_option("sqlalchemy.url", settings.DATABASE_URL) - -# add your model's MetaData object here -# for 'autogenerate' support -# from myapp import mymodel -# target_metadata = mymodel.Base.metadata -target_metadata = Base.metadata - -# other values from the config, defined by the needs of env.py, -# can be acquired: -# my_important_option = config.get_main_option("my_important_option") -# ... etc. - - -def run_migrations_offline() -> None: - """Run migrations in 'offline' mode. - - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. - - Calls to context.execute() here emit the given string to the - script output. - - """ - url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, - target_metadata=target_metadata, - literal_binds=True, - # dialect_opts={"paramstyle": "named"}, - ) - - with context.begin_transaction(): - context.run_migrations() - - -def do_run_migrations(connection: Connection) -> None: - context.configure(connection=connection, target_metadata=target_metadata) - - with context.begin_transaction(): - context.run_migrations() - - -async def run_async_migrations() -> None: - """In this scenario we need to create an Engine - and associate a connection with the context. - - """ - - connectable = async_engine_from_config( - config.get_section(config.config_ini_section, {}), - prefix="sqlalchemy.", - poolclass=pool.NullPool, - ) - - async with connectable.connect() as connection: - await connection.run_sync(do_run_migrations) - - await connectable.dispose() - - -def run_migrations_online() -> None: - """Run migrations in 'online' mode.""" - - asyncio.run(run_async_migrations()) - - -if context.is_offline_mode(): - run_migrations_offline() -else: - run_migrations_online() diff --git a/ContentFetcher/content_fetcher/alembic/script.py.mako b/ContentFetcher/content_fetcher/alembic/script.py.mako deleted file mode 100644 index 480b130..0000000 --- a/ContentFetcher/content_fetcher/alembic/script.py.mako +++ /dev/null @@ -1,28 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -# revision identifiers, used by Alembic. -revision: str = ${repr(up_revision)} -down_revision: Union[str, None] = ${repr(down_revision)} -branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)} -depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)} - - -def upgrade() -> None: - """Upgrade schema.""" - ${upgrades if upgrades else "pass"} - - -def downgrade() -> None: - """Downgrade schema.""" - ${downgrades if downgrades else "pass"} diff --git a/ContentFetcher/content_fetcher/alembic/versions/0e3352f50b1f_create_contents_table.py b/ContentFetcher/content_fetcher/alembic/versions/0e3352f50b1f_create_contents_table.py deleted file mode 100644 index 2f3f25a..0000000 --- a/ContentFetcher/content_fetcher/alembic/versions/0e3352f50b1f_create_contents_table.py +++ /dev/null @@ -1,42 +0,0 @@ -"""create contents table - -Revision ID: 0e3352f50b1f -Revises: -Create Date: 2025-06-15 18:34:04.359854 - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision: str = '0e3352f50b1f' -down_revision: Union[str, None] = None -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - """Upgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('web_contents', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('url', sa.String(length=100), nullable=False), - sa.Column('content', sa.Text(), nullable=True), - sa.Column('keywords', sa.JSON(), nullable=True), - sa.Column('created_at', sa.TIMESTAMP(timezone=True), server_default=sa.text('now()'), nullable=False), - sa.Column('user_id', sa.String(length=50), nullable=True), - sa.PrimaryKeyConstraint('id') - ) - op.create_index(op.f('ix_web_contents_id'), 'web_contents', ['id'], unique=False) - # ### end Alembic commands ### - - -def downgrade() -> None: - """Downgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.drop_index(op.f('ix_web_contents_id'), table_name='web_contents') - op.drop_table('web_contents') - # ### end Alembic commands ### diff --git a/ContentFetcher/content_fetcher/alembic/versions/267ff639f45d_update_content_table_changed_user_id_to_.py b/ContentFetcher/content_fetcher/alembic/versions/267ff639f45d_update_content_table_changed_user_id_to_.py deleted file mode 100644 index bb6b904..0000000 --- a/ContentFetcher/content_fetcher/alembic/versions/267ff639f45d_update_content_table_changed_user_id_to_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""update content table, changed user_id to report_id - -Revision ID: 267ff639f45d -Revises: 0e3352f50b1f -Create Date: 2025-06-15 20:16:23.085560 - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision: str = '267ff639f45d' -down_revision: Union[str, None] = '0e3352f50b1f' -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - """Upgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('web_contents', sa.Column('report_id', sa.String(length=50), nullable=True)) - op.drop_column('web_contents', 'user_id') - # ### end Alembic commands ### - - -def downgrade() -> None: - """Downgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.add_column('web_contents', sa.Column('user_id', sa.VARCHAR(length=50), autoincrement=False, nullable=True)) - op.drop_column('web_contents', 'report_id') - # ### end Alembic commands ### diff --git a/ContentFetcher/content_fetcher/alembic/versions/b0e0bdd22d71_contents_extend_url_length.py b/ContentFetcher/content_fetcher/alembic/versions/b0e0bdd22d71_contents_extend_url_length.py deleted file mode 100644 index 204792f..0000000 --- a/ContentFetcher/content_fetcher/alembic/versions/b0e0bdd22d71_contents_extend_url_length.py +++ /dev/null @@ -1,38 +0,0 @@ -"""contents - extend url length - -Revision ID: b0e0bdd22d71 -Revises: 267ff639f45d -Create Date: 2025-06-15 21:24:08.707723 - -""" -from typing import Sequence, Union - -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision: str = 'b0e0bdd22d71' -down_revision: Union[str, None] = '267ff639f45d' -branch_labels: Union[str, Sequence[str], None] = None -depends_on: Union[str, Sequence[str], None] = None - - -def upgrade() -> None: - """Upgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.alter_column('web_contents', 'url', - existing_type=sa.VARCHAR(length=100), - type_=sa.String(length=1000), - existing_nullable=False) - # ### end Alembic commands ### - - -def downgrade() -> None: - """Downgrade schema.""" - # ### commands auto generated by Alembic - please adjust! ### - op.alter_column('web_contents', 'url', - existing_type=sa.String(length=1000), - type_=sa.VARCHAR(length=100), - existing_nullable=False) - # ### end Alembic commands ### diff --git a/ContentFetcher/content_fetcher/app/__init__.py b/ContentFetcher/content_fetcher/app/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ContentFetcher/content_fetcher/app/config.py b/ContentFetcher/content_fetcher/app/config.py deleted file mode 100644 index cc7f612..0000000 --- a/ContentFetcher/content_fetcher/app/config.py +++ /dev/null @@ -1,12 +0,0 @@ -from pydantic_settings import BaseSettings, SettingsConfigDict - -class Settings(BaseSettings): - DATABASE_URL: str - RABBITMQ_URL: str - RABBITMQ_REQUEST_QUEUE: str = "content.fetch.request" - RABBITMQ_RESULT_QUEUE: str = "content.fetch.result" - RABBITMQ_EXCHANGE: str = "content.events" - - model_config = SettingsConfigDict(env_file=".env") - -settings = Settings() diff --git a/ContentFetcher/content_fetcher/app/db.py b/ContentFetcher/content_fetcher/app/db.py deleted file mode 100644 index ef9ee7b..0000000 --- a/ContentFetcher/content_fetcher/app/db.py +++ /dev/null @@ -1,11 +0,0 @@ -from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession -from sqlalchemy.orm import sessionmaker, declarative_base -from .config import settings - -engine = create_async_engine(settings.DATABASE_URL, echo=True, future=True) -AsyncSessionLocal = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False) -Base = declarative_base() - -async def get_db(): - async with AsyncSessionLocal() as session: - yield session diff --git a/ContentFetcher/content_fetcher/app/logging.py b/ContentFetcher/content_fetcher/app/logging.py deleted file mode 100644 index 6ede9ab..0000000 --- a/ContentFetcher/content_fetcher/app/logging.py +++ /dev/null @@ -1,16 +0,0 @@ -import logging -import logstash - -# Configure Logstash host and port -logstash_host = 'logstash' -logstash_port = 5000 - -logger = logging.getLogger('content-fetcher-logger') -logger.setLevel(logging.INFO) - -# Add TCP handler -logger.addHandler(logstash.TCPLogstashHandler( - host=logstash_host, - port=logstash_port, - version=1 # Logstash event schema version -)) \ No newline at end of file diff --git a/ContentFetcher/content_fetcher/app/main.py b/ContentFetcher/content_fetcher/app/main.py deleted file mode 100644 index 165ba0a..0000000 --- a/ContentFetcher/content_fetcher/app/main.py +++ /dev/null @@ -1,127 +0,0 @@ -import httpx -import asyncio -import contextlib -from typing import List -from contextlib import asynccontextmanager -from fastapi import FastAPI, Body, Depends, HTTPException, status -from sqlalchemy.exc import IntegrityError -from sqlalchemy.ext.asyncio import AsyncSession - -from .db import get_db -from .models import Content -from .schemas import FetchRequest, FetchResponse -from .messaging.rabbit import run_consumer - - -@asynccontextmanager -async def lifespan(app: FastAPI): - # start-up - loop = asyncio.get_event_loop() - consumer_task = loop.create_task(run_consumer()) - yield - # shut-down - consumer_task.cancel() - with contextlib.suppress(asyncio.CancelledError): - await consumer_task - -app = FastAPI(lifespan=lifespan) - - -@app.post( - "/fetch", - response_model=FetchResponse, - summary="Fetch page content & extract keywords", - description=( - "Fetches content from the provided URL, extracts keywords, " - "and saves the content to the database. Returns the URL, " - "extracted keywords, page's content, and optionally a report ID (if provided)." - ), - status_code=status.HTTP_200_OK, - responses={ - 200: {"description": "Content fetched and keywords extracted"}, - 422: {"description": "Validation error"}, - 404: {"description": "URL unreachable"}, - 409: {"description": "Duplicate entry"}, - 500: {"description": "Internal server error"}, - }, -) -async def fetch_url( - body: FetchRequest = Body( - ..., - title="FetchRequest schema", - description=( - "URL (≤1000 characters) for processing and optional identifier of the report (≤50 characters)." - ), - examples=[ - { - "url": "https://www.lipsum.com/feed/html", - "report_id": "report_1" - }, - { - "url": "https://www.youtube.com/watch?v=X6n3O7up83I", - } - ], - embed=False, - ), - db: AsyncSession = Depends(get_db), -): - """ - **Opis** - - Przyjmuje URL, pobiera treść (mock), generuje listę słów kluczowych - - Zapisuje rekord w tabeli `web_contents` - - Zwraca 201 na sukces oraz url, listę słów kluczowych jako json oraz treść strony, ew. pozostałe kody przy błędach - - **Możliwe błędy** - - **422** – walidacja Pydantic - - **404** – strona niedostępna - - **409** – konflikt (url, report_id) - - **500** – błąd wewnętrzny serwera - """ - # ── 1. (Mock) Pobranie treści i ekstrakcja słów kluczowych ────────────── - try: - # realnie: resp = await httpx.get(body.url, timeout=10) - # if resp.status_code >= 400: raise HTTPException(status_code=404, …) - page_content = ( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ac." - ) - except httpx.RequestError as exc: # sieć/down → 404 - raise HTTPException(status_code=404, detail=str(exc)) - - keywords: List[str] = ["keyword1", "keyword2", "keyword3"] - - # W prawdziwej aplikacji tutaj byłby kod do pobrania treści z URL i ekstrakcji słów kluczowych - # TODO: Implement actual content fetching and keyword extraction logic - - # ── 2. Zapis do bazy z obsługą wyjątków ───────────────────────────────── - try: - row = Content( - url=body.url, - content=page_content, - keywords=keywords, - report_id=body.report_id, - ) - db.add(row) - await db.commit() - await db.refresh(row) - - except IntegrityError as exc: # unikalność / not null - await db.rollback() - raise HTTPException( - status_code=status.HTTP_409_CONFLICT, - detail=f"Unexpected conflict (url, report_id)\n{str(exc)}", - ) - - except Exception as exc: - await db.rollback() - raise HTTPException( - status_code=500, - detail=f"Error writing to database.\n{str(exc)}", - ) - - # ── 3. Zwróć odpowiedź ──────────────────────────────────────────────── - return FetchResponse( - url=row.url, - keywords=keywords, - content=page_content, - report_id=row.report_id, - ) diff --git a/ContentFetcher/content_fetcher/app/messaging/__init__.py b/ContentFetcher/content_fetcher/app/messaging/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ContentFetcher/content_fetcher/app/messaging/rabbit.py b/ContentFetcher/content_fetcher/app/messaging/rabbit.py deleted file mode 100644 index b6619fa..0000000 --- a/ContentFetcher/content_fetcher/app/messaging/rabbit.py +++ /dev/null @@ -1,188 +0,0 @@ -import json -import asyncio -from contextlib import asynccontextmanager -from typing import List, Dict, Optional, Coroutine, Any - -from aio_pika import connect_robust, Message, IncomingMessage, ExchangeType -from pydantic import ValidationError -import httpx -from sqlalchemy.exc import IntegrityError -from sqlalchemy.ext.asyncio import AsyncSession - -from ..logging import logger -from ..schemas import FetchRequest, FetchResponse -from ..db import AsyncSessionLocal -from ..models import Content -from ..config import settings # DATABASE_URL & RABBITMQ_URL - -REQUEST_QUEUE = settings.RABBITMQ_REQUEST_QUEUE -RESULT_QUEUE = settings.RABBITMQ_RESULT_QUEUE -EXCHANGE = settings.RABBITMQ_EXCHANGE - -# ---------- narzędzie do pobierania i ekstrakcji (mock) ---------- -async def _fetch_and_extract(url: str) -> tuple[str, List[str]]: - # TODO: zastąpić realnym httpx + beautifulsoup + yake - page_content = ( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ac." - ) - keywords = ["keyword1", "keyword2", "keyword3"] - return page_content, keywords - - -# ---------- DB helper ---------- -@asynccontextmanager -async def db_session(): - async with AsyncSessionLocal() as session: - try: - yield session - finally: - await session.close() - -# ---------- główny handler wiadomości ---------- -async def handle_request(msg: IncomingMessage) -> Coroutine[Any, Any, None]: - async with msg.process(ignore_processed=True): - try: - logger.info("[*] Received message:", extra={'message-body': msg.body.decode()}) - raw = json.loads(msg.body.decode()) - - # ujednolicamy: jeśli przyszedł pojedynczy obiekt, ubieramy w listę - if not isinstance(raw, list): - raw = [raw] - - batch: List[FetchRequest] = [FetchRequest(**item) for item in raw] - except (json.JSONDecodeError, ValidationError) as exc: - logger.error(f"[x] Invalid payload: {exc}") - return - - results: List[Dict[str, Any]] = [] - async with db_session() as db: - for req in batch: - # 1) pobieranie - try: - content, keywords = await _fetch_and_extract(req.url) - except httpx.RequestError as exc: - logger.error(f"[x] Request error: {exc}") - results.append( - { - "status": "error", - "reason": str(exc), - "url": req.url, - "reportId": req.reportId, - } - ) - continue - - # 2) zapis do DB - try: - row = Content( - url=req.url, - content=content, - keywords=keywords, - report_id=str(req.reportId), - ) - db.add(row) - await db.commit() - await db.refresh(row) - - # 3) sukces ⇒ serializujemy schematem Pydantic - results.append( - FetchResponse( - url=row.url, - keywords=keywords, - content=content, - reportId=int(req.reportId), - ).model_dump() - ) - - except IntegrityError as exc: - logger.error(f"[x] Integrity error: {exc}") - await db.rollback() - results.append( - { - "status": "conflict", - "reason": "duplicate (url, report_id)", - "url": req.url, - "reportId": req.reportId, - } - ) - - except Exception as exc: - logger.error(f"[x] DB error: {exc}") - await db.rollback() - results.append( - { - "status": "error", - "reason": f"DB error: {exc}", - "url": req.url, - "reportId": req.reportId, - } - ) - - await publish_result(results) - logger.info("[*] Results published to RabbitMQ exchange:", extra={'exchange': EXCHANGE}) - -# ---------- publish helper ---------- -async def publish_result(body: list[dict]): - connection = await connect_robust(host="rabbitmq") - async with connection: - channel = await connection.channel() - await channel.declare_exchange(EXCHANGE, ExchangeType.TOPIC, durable=True) - result_queue = await channel.declare_queue(RESULT_QUEUE, durable=True) - await result_queue.bind(EXCHANGE, routing_key=RESULT_QUEUE) - await channel.default_exchange.publish( - Message(json.dumps(body).encode()), - routing_key=RESULT_QUEUE, - ) - -# ---------- główna pętla konsumenta ---------- -async def run_consumer() -> None: - logger.info("[*] Starting RabbitMQ consumer...") - try: - connection = await connect_robust(host="rabbitmq") - except Exception as exc: - logger.error(f"[x] Failed to connect to RabbitMQ: {exc}") - return - logger.info("[*] Connected to RabbitMQ at") - async with connection: - try: - channel = await connection.channel() - await channel.declare_exchange(EXCHANGE, ExchangeType.TOPIC, durable=True) - queue = await channel.declare_queue(REQUEST_QUEUE, durable=True) - await queue.bind(EXCHANGE, routing_key=REQUEST_QUEUE) - logger.info("[*] Waiting for messages (batch mode). To exit press CTRL+C") - await queue.consume(handle_request) - await asyncio.Future() # run forever - except Exception as exc: - logger.error(f"[x] Error in consumer: {exc}") - await connection.close() - raise - - -# Przykładowy payload do kolejki `content.fetch.request` -# [ -# {"url": "https://www.lipsum.com/feed/html", "report_id": "rep1"}, -# {"url": "https://example.com"}, -# {"url": "https://bad.example.com"} // zasymuluje błąd 404 -# ] - -# Wynik w kolejce `content.fetch.result` będzie wyglądał tak: -# [ -# { -# "url": "https://www.lipsum.com/feed/html", -# "keywords": ["keyword1", "keyword2", "keyword3"], -# "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ac.", -# "report_id": "rep1" -# }, -# { -# "url": "https://example.com", -# "keywords": ["keyword1", "keyword2", "keyword3"], -# "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ac.", -# "report_id": null -# }, -# { -# "status": "error", -# "reason": "404 Client Error: Not Found for url", -# "url": "https://bad.example.com", -# "report_id": null -# } -# ] \ No newline at end of file diff --git a/ContentFetcher/content_fetcher/app/models.py b/ContentFetcher/content_fetcher/app/models.py deleted file mode 100644 index 28e7687..0000000 --- a/ContentFetcher/content_fetcher/app/models.py +++ /dev/null @@ -1,13 +0,0 @@ -from sqlalchemy import Column, Integer, String, Text, JSON, TIMESTAMP, func -from .db import Base - - -class Content(Base): - __tablename__ = "web_contents" - - id = Column(Integer, primary_key=True, index=True) - url = Column(String(1000), nullable=False) - content = Column(Text, nullable=True) - keywords = Column(JSON, nullable=True) - created_at = Column(TIMESTAMP(timezone=True), server_default=func.now(), nullable=False) - report_id = Column(String(50), nullable=True) diff --git a/ContentFetcher/content_fetcher/app/schemas.py b/ContentFetcher/content_fetcher/app/schemas.py deleted file mode 100644 index 02daadf..0000000 --- a/ContentFetcher/content_fetcher/app/schemas.py +++ /dev/null @@ -1,13 +0,0 @@ -from pydantic import BaseModel, constr, Field -from typing import List, Optional - -class FetchRequest(BaseModel): - url: constr(max_length=100) = Field(..., examples=["https://example.com"]) - reportId: int - -class FetchResponse(BaseModel): - url: constr(max_length=100) - keywords: List[constr(strip_whitespace=True)] - content: Optional[str] = None - reportId: int - diff --git a/ContentFetcher/content_fetcher/app/services/__init__.py b/ContentFetcher/content_fetcher/app/services/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ContentFetcher/content_fetcher/app/services/fetcher.py b/ContentFetcher/content_fetcher/app/services/fetcher.py deleted file mode 100644 index e69de29..0000000 diff --git a/ContentFetcher/content_fetcher/app/tests/__init__.py b/ContentFetcher/content_fetcher/app/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/ContentFetcher/content_fetcher/app/tests/test_main.py b/ContentFetcher/content_fetcher/app/tests/test_main.py deleted file mode 100644 index e69de29..0000000 diff --git a/ContentFetcher/content_fetcher/requirements.txt b/ContentFetcher/content_fetcher/requirements.txt deleted file mode 100644 index d51462b..0000000 --- a/ContentFetcher/content_fetcher/requirements.txt +++ /dev/null @@ -1,14 +0,0 @@ -fastapi~=0.115.12 -uvicorn[standard]~=0.34.3 -python-dotenv~=1.1.0 -pydantic~=2.11.6 -pydantic-settings~=2.9.1 -SQLAlchemy~=2.0.41 -alembic~=1.16.1 -asyncpg~=0.30.0 -psycopg2-binary~=2.9.10 -aio-pika~=9.5.5 -httpx~=0.28.1 -python-logstash~=0.4.8 -pytest~=8.2.2 -pytest-asyncio~=0.23.7 diff --git a/ContentFetcher/docker-compose.yml b/ContentFetcher/docker-compose.yml deleted file mode 100644 index 432d05e..0000000 --- a/ContentFetcher/docker-compose.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: '3.8' - -services: - postgres: - image: postgres:17 - environment: - POSTGRES_USER: wiarygodnik - POSTGRES_PASSWORD: secret - POSTGRES_DB: contentfetcherdb - volumes: - - contentfetcherpgdata:/var/lib/postgresql/data - - rabbitmq: - image: rabbitmq:3-management - environment: - RABBITMQ_DEFAULT_USER: guest - RABBITMQ_DEFAULT_PASS: guest - ports: - - "5672:5672" # AMQP - - "15672:15672" # Management UI :contentReference[oaicite:10]{index=10} - - content_fetcher: - build: - context: ./content_fetcher - dockerfile: Dockerfile - env_file: - - ./content_fetcher/.env - depends_on: - - postgres - - rabbitmq - command: > - sh -c "alembic upgrade head && - uvicorn app.main:app --host 0.0.0.0 --port 8080" - ports: - - "8090:8080" - -volumes: - contentfetcherpgdata: diff --git a/CredabilityService/.gitattributes b/CredabilityService/.gitattributes deleted file mode 100644 index 3b41682..0000000 --- a/CredabilityService/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -/mvnw text eol=lf -*.cmd text eol=crlf diff --git a/CredabilityService/.gitignore b/CredabilityService/.gitignore deleted file mode 100644 index 667aaef..0000000 --- a/CredabilityService/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -HELP.md -target/ -.mvn/wrapper/maven-wrapper.jar -!**/src/main/**/target/ -!**/src/test/**/target/ - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ -build/ -!**/src/main/**/build/ -!**/src/test/**/build/ - -### VS Code ### -.vscode/ diff --git a/CredabilityService/.mvn/wrapper/maven-wrapper.properties b/CredabilityService/.mvn/wrapper/maven-wrapper.properties deleted file mode 100644 index 2f94e61..0000000 --- a/CredabilityService/.mvn/wrapper/maven-wrapper.properties +++ /dev/null @@ -1,19 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -wrapperVersion=3.3.2 -distributionType=only-script -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.10/apache-maven-3.9.10-bin.zip diff --git a/CredabilityService/Dockerfile b/CredabilityService/Dockerfile deleted file mode 100644 index 65c4c0e..0000000 --- a/CredabilityService/Dockerfile +++ /dev/null @@ -1,10 +0,0 @@ -FROM maven:3.9.6-eclipse-temurin-21 AS build -WORKDIR /app -COPY pom.xml . -COPY src ./src -RUN mvn clean package -DskipTests - -FROM openjdk:21-jdk-slim -WORKDIR /app -COPY --from=build /app/target/*.jar app.jar -ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/CredabilityService/docker-compose.yml b/CredabilityService/docker-compose.yml deleted file mode 100644 index cd833d5..0000000 --- a/CredabilityService/docker-compose.yml +++ /dev/null @@ -1,44 +0,0 @@ -version: '3.8' - -services: - rabbitmq: - image: rabbitmq:3-management - container_name: rabbitmq - restart: always - ports: - - "5672:5672" - - "15672:15672" - environment: - RABBITMQ_DEFAULT_USER: guest - RABBITMQ_DEFAULT_PASS: guest - - credability-db: - image: postgres:15 - container_name: credability-db - restart: always - ports: - - "5431:5432" - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DB: credability - volumes: - - postgres_data_credability:/var/lib/postgresql/data - - app: - build: - context: . - dockerfile: Dockerfile - container_name: spring-app - ports: - - "8080:8080" - depends_on: - - rabbitmq - - credability-db - environment: - SPRING_PROFILES_ACTIVE: default - SPRING_DATASOURCE_URL: jdbc:postgresql://credability-db:5431/credability - SPRING_RABBIT_HOST: rabbitmq - -volumes: - postgres_data_credability: diff --git a/CredabilityService/mvnw b/CredabilityService/mvnw deleted file mode 100644 index 19529dd..0000000 --- a/CredabilityService/mvnw +++ /dev/null @@ -1,259 +0,0 @@ -#!/bin/sh -# ---------------------------------------------------------------------------- -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# ---------------------------------------------------------------------------- - -# ---------------------------------------------------------------------------- -# Apache Maven Wrapper startup batch script, version 3.3.2 -# -# Optional ENV vars -# ----------------- -# JAVA_HOME - location of a JDK home dir, required when download maven via java source -# MVNW_REPOURL - repo url base for downloading maven distribution -# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output -# ---------------------------------------------------------------------------- - -set -euf -[ "${MVNW_VERBOSE-}" != debug ] || set -x - -# OS specific support. -native_path() { printf %s\\n "$1"; } -case "$(uname)" in -CYGWIN* | MINGW*) - [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" - native_path() { cygpath --path --windows "$1"; } - ;; -esac - -# set JAVACMD and JAVACCMD -set_java_home() { - # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched - if [ -n "${JAVA_HOME-}" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - JAVACCMD="$JAVA_HOME/jre/sh/javac" - else - JAVACMD="$JAVA_HOME/bin/java" - JAVACCMD="$JAVA_HOME/bin/javac" - - if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then - echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 - echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 - return 1 - fi - fi - else - JAVACMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v java - )" || : - JAVACCMD="$( - 'set' +e - 'unset' -f command 2>/dev/null - 'command' -v javac - )" || : - - if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then - echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 - return 1 - fi - fi -} - -# hash string like Java String::hashCode -hash_string() { - str="${1:-}" h=0 - while [ -n "$str" ]; do - char="${str%"${str#?}"}" - h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) - str="${str#?}" - done - printf %x\\n $h -} - -verbose() { :; } -[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } - -die() { - printf %s\\n "$1" >&2 - exit 1 -} - -trim() { - # MWRAPPER-139: - # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. - # Needed for removing poorly interpreted newline sequences when running in more - # exotic environments such as mingw bash on Windows. - printf "%s" "${1}" | tr -d '[:space:]' -} - -# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties -while IFS="=" read -r key value; do - case "${key-}" in - distributionUrl) distributionUrl=$(trim "${value-}") ;; - distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; - esac -done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties" -[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties" - -case "${distributionUrl##*/}" in -maven-mvnd-*bin.*) - MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ - case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in - *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; - :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; - :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; - :Linux*x86_64*) distributionPlatform=linux-amd64 ;; - *) - echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 - distributionPlatform=linux-amd64 - ;; - esac - distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" - ;; -maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; -*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; -esac - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" -distributionUrlName="${distributionUrl##*/}" -distributionUrlNameMain="${distributionUrlName%.*}" -distributionUrlNameMain="${distributionUrlNameMain%-bin}" -MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" -MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" - -exec_maven() { - unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : - exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" -} - -if [ -d "$MAVEN_HOME" ]; then - verbose "found existing MAVEN_HOME at $MAVEN_HOME" - exec_maven "$@" -fi - -case "${distributionUrl-}" in -*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; -*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; -esac - -# prepare tmp dir -if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then - clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } - trap clean HUP INT TERM EXIT -else - die "cannot create temp dir" -fi - -mkdir -p -- "${MAVEN_HOME%/*}" - -# Download and Install Apache Maven -verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -verbose "Downloading from: $distributionUrl" -verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -# select .zip or .tar.gz -if ! command -v unzip >/dev/null; then - distributionUrl="${distributionUrl%.zip}.tar.gz" - distributionUrlName="${distributionUrl##*/}" -fi - -# verbose opt -__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' -[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v - -# normalize http auth -case "${MVNW_PASSWORD:+has-password}" in -'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; -has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; -esac - -if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then - verbose "Found wget ... using wget" - wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" -elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then - verbose "Found curl ... using curl" - curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" -elif set_java_home; then - verbose "Falling back to use Java to download" - javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" - targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" - cat >"$javaSource" <<-END - public class Downloader extends java.net.Authenticator - { - protected java.net.PasswordAuthentication getPasswordAuthentication() - { - return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); - } - public static void main( String[] args ) throws Exception - { - setDefault( new Downloader() ); - java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); - } - } - END - # For Cygwin/MinGW, switch paths to Windows format before running javac and java - verbose " - Compiling Downloader.java ..." - "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" - verbose " - Running Downloader.java ..." - "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" -fi - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -if [ -n "${distributionSha256Sum-}" ]; then - distributionSha256Result=false - if [ "$MVN_CMD" = mvnd.sh ]; then - echo "Checksum validation is not supported for maven-mvnd." >&2 - echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - elif command -v sha256sum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - elif command -v shasum >/dev/null; then - if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then - distributionSha256Result=true - fi - else - echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 - echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 - exit 1 - fi - if [ $distributionSha256Result = false ]; then - echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 - echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 - exit 1 - fi -fi - -# unzip and move -if command -v unzip >/dev/null; then - unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" -else - tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" -fi -printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url" -mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" - -clean || : -exec_maven "$@" diff --git a/CredabilityService/mvnw.cmd b/CredabilityService/mvnw.cmd deleted file mode 100644 index 249bdf3..0000000 --- a/CredabilityService/mvnw.cmd +++ /dev/null @@ -1,149 +0,0 @@ -<# : batch portion -@REM ---------------------------------------------------------------------------- -@REM Licensed to the Apache Software Foundation (ASF) under one -@REM or more contributor license agreements. See the NOTICE file -@REM distributed with this work for additional information -@REM regarding copyright ownership. The ASF licenses this file -@REM to you under the Apache License, Version 2.0 (the -@REM "License"); you may not use this file except in compliance -@REM with the License. You may obtain a copy of the License at -@REM -@REM http://www.apache.org/licenses/LICENSE-2.0 -@REM -@REM Unless required by applicable law or agreed to in writing, -@REM software distributed under the License is distributed on an -@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -@REM KIND, either express or implied. See the License for the -@REM specific language governing permissions and limitations -@REM under the License. -@REM ---------------------------------------------------------------------------- - -@REM ---------------------------------------------------------------------------- -@REM Apache Maven Wrapper startup batch script, version 3.3.2 -@REM -@REM Optional ENV vars -@REM MVNW_REPOURL - repo url base for downloading maven distribution -@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven -@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output -@REM ---------------------------------------------------------------------------- - -@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) -@SET __MVNW_CMD__= -@SET __MVNW_ERROR__= -@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% -@SET PSModulePath= -@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( - IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) -) -@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% -@SET __MVNW_PSMODULEP_SAVE= -@SET __MVNW_ARG0_NAME__= -@SET MVNW_USERNAME= -@SET MVNW_PASSWORD= -@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*) -@echo Cannot start maven from wrapper >&2 && exit /b 1 -@GOTO :EOF -: end batch / begin powershell #> - -$ErrorActionPreference = "Stop" -if ($env:MVNW_VERBOSE -eq "true") { - $VerbosePreference = "Continue" -} - -# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties -$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl -if (!$distributionUrl) { - Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" -} - -switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { - "maven-mvnd-*" { - $USE_MVND = $true - $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" - $MVN_CMD = "mvnd.cmd" - break - } - default { - $USE_MVND = $false - $MVN_CMD = $script -replace '^mvnw','mvn' - break - } -} - -# apply MVNW_REPOURL and calculate MAVEN_HOME -# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ -if ($env:MVNW_REPOURL) { - $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" } - $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')" -} -$distributionUrlName = $distributionUrl -replace '^.*/','' -$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' -$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain" -if ($env:MAVEN_USER_HOME) { - $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain" -} -$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' -$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" - -if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { - Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" - Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" - exit $? -} - -if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { - Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" -} - -# prepare tmp dir -$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile -$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" -$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null -trap { - if ($TMP_DOWNLOAD_DIR.Exists) { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } - } -} - -New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null - -# Download and Install Apache Maven -Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." -Write-Verbose "Downloading from: $distributionUrl" -Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" - -$webclient = New-Object System.Net.WebClient -if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { - $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) -} -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null - -# If specified, validate the SHA-256 sum of the Maven distribution zip file -$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum -if ($distributionSha256Sum) { - if ($USE_MVND) { - Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." - } - Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash - if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { - Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." - } -} - -# unzip and move -Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null -Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null -try { - Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null -} catch { - if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { - Write-Error "fail to move MAVEN_HOME" - } -} finally { - try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } - catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } -} - -Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/CredabilityService/pom.xml b/CredabilityService/pom.xml deleted file mode 100644 index d764c07..0000000 --- a/CredabilityService/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - 4.0.0 - - org.springframework.boot - spring-boot-starter-parent - 3.5.0 - - - org.wiarygodnik - CredabilityService - 0.0.1-SNAPSHOT - CredabilityService - CredabilityService - - - - - - - - - - - - - - - 21 - - - - org.springframework.boot - spring-boot-starter - - - - org.springframework.boot - spring-boot-starter-test - test - - - - org.springframework.boot - spring-boot-starter-amqp - - - org.projectlombok - lombok - provided - - - org.jsoup - jsoup - 1.17.2 - - - net.logstash.logback - logstash-logback-encoder - 7.4 - - - org.springframework.boot - spring-boot-starter-data-jpa - - - - org.postgresql - postgresql - - - org.springframework.boot - spring-boot-starter-web - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplication.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplication.java deleted file mode 100644 index cac24a0..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.wiarygodnik.credabilityservice; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class CredabilityServiceApplication { - - public static void main(String[] args) { - SpringApplication.run(CredabilityServiceApplication.class, args); - } - -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlContent.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlContent.java deleted file mode 100644 index 380b48f..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlContent.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.wiarygodnik.credabilityservice.application; - -import java.util.List; - -public record UrlContent(int reportId, String url, String content, List keywords) { -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlService.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlService.java deleted file mode 100644 index 53c3f87..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/application/UrlService.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.wiarygodnik.credabilityservice.application; - -import lombok.extern.slf4j.Slf4j; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; -import org.jsoup.nodes.Element; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.wiarygodnik.credabilityservice.presentation.RabbitProducer; -import org.wiarygodnik.credabilityservice.storage.UrlsRepository; - -import java.io.IOException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -@Service -@Slf4j -public class UrlService { - private final RabbitProducer rabbitProducer; - private final UrlsRepository urlsRepository; - - @Autowired - public UrlService(RabbitProducer rabbitProducer, UrlsRepository urlsRepository) { - this.rabbitProducer = rabbitProducer; - this.urlsRepository = urlsRepository; - } - - public List handleUrlContent(UrlContent urlContent) { - List urls = getUrlsBasedOnKeywords(urlContent.keywords()); - urlsRepository.save(urlContent.url(), urls); - rabbitProducer.sendUrls(urls, urlContent.reportId()); - - return urls; - } - - private List getUrlsBasedOnKeywords(List keywords) { - try { - String url = "https://html.duckduckgo.com/html/?q=" + String.join("+", keywords); - - Document doc = Jsoup.connect(url) - .userAgent("Mozilla/5.0") - .timeout(10000) - .get(); - - List urlsBasedOnKeywords = new ArrayList<>(); - - for (Element result : doc.select("a.result__a")) { - String href = result.attr("href"); - - if (href.contains("uddg=")) { - String encodedUrl = href.substring(href.indexOf("uddg=") + 5); - String decodedUrl = URLDecoder.decode(encodedUrl, StandardCharsets.UTF_8); - - String cleanUrl = decodedUrl.split("&rut=")[0]; - urlsBasedOnKeywords.add(cleanUrl); - } - - if (urlsBasedOnKeywords.size() >= 6) break; - } - - return urlsBasedOnKeywords; - } catch (IOException e) { - log.error("Error getting URLs based on keywords!", e); - return Collections.emptyList(); - } - } -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/CredabilityController.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/CredabilityController.java deleted file mode 100644 index 655b620..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/CredabilityController.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.wiarygodnik.credabilityservice.presentation; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import org.wiarygodnik.credabilityservice.application.UrlContent; -import org.wiarygodnik.credabilityservice.application.UrlService; - -import java.util.Arrays; -import java.util.List; - -//---------------------- -// FOR TESTING ONLY -//---------------------- -@RestController -public class CredabilityController { - private UrlService urlService; - - @Autowired - public CredabilityController(UrlService urlService) { - this.urlService = urlService; - } - - @GetMapping("/findUrls") - public ResponseEntity newEmployee(@RequestBody String keywords) { - List keywordsList = Arrays.asList(keywords.split("-")); - List urls = urlService.handleUrlContent(new UrlContent(0, "test.url", "test", keywordsList)); - return ResponseEntity.ok(String.join(" ", urls)); - } - - @PostMapping("/findUrlsAndSend/{reportId}") - public ResponseEntity findAndSend(@PathVariable int reportId, @RequestBody String keywords) { - List keywordsList = Arrays.asList(keywords.split("-")); - urlService.handleUrlContent(new UrlContent(reportId, "test.url", "test", keywordsList)); - return ResponseEntity.ok().build(); - } - -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConfig.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConfig.java deleted file mode 100644 index d0f8d42..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.wiarygodnik.credabilityservice.presentation; - -import org.springframework.amqp.core.TopicExchange; -import org.springframework.amqp.rabbit.connection.ConnectionFactory; -import org.springframework.amqp.rabbit.core.RabbitTemplate; -import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; -import org.springframework.amqp.support.converter.MessageConverter; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.amqp.core.Binding; -import org.springframework.amqp.core.BindingBuilder; -import org.springframework.amqp.core.Queue; - -@Configuration -public class RabbitConfig { - - public static final String EXCHANGE_NAME = "wiarygodnik.exchange"; - public static final String QUEUE_CONTENT = "content.fetch.result"; - public static final String ROUTING_CONTENT = "routing.content"; - public static final String QUEUE_RESULTS = "credibility.service.results.queue"; - public static final String ROUTING_RESULTS = "routing.results"; - - @Bean - public TopicExchange exchange() { - return new TopicExchange(EXCHANGE_NAME); - } - - @Bean - public Queue keywordsQueue() { - return new Queue(QUEUE_CONTENT); - } - - @Bean - public Queue resultsQueue() { - return new Queue(QUEUE_RESULTS); - } - - @Bean - public Binding contentBinding(@Qualifier("keywordsQueue") Queue urlQueue, TopicExchange exchange) { - return BindingBuilder - .bind(urlQueue) - .to(exchange) - .with(ROUTING_CONTENT); - } - - @Bean - public Binding resultsBinding(@Qualifier("resultsQueue") Queue resultsQueue, TopicExchange exchange) { - return BindingBuilder - .bind(resultsQueue) - .to(exchange) - .with(ROUTING_RESULTS); - } - - @Bean - public MessageConverter jsonMessageConverter() { - return new Jackson2JsonMessageConverter(); - } - - @Bean - public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { - RabbitTemplate template = new RabbitTemplate(connectionFactory); - template.setMessageConverter(jsonMessageConverter()); - return template; - } -} \ No newline at end of file diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConsumer.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConsumer.java deleted file mode 100644 index 365782e..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitConsumer.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.wiarygodnik.credabilityservice.presentation; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.rabbit.annotation.RabbitListener; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.wiarygodnik.credabilityservice.application.UrlService; - -import java.util.List; - -@Service -@Slf4j -public class RabbitConsumer { - private final UrlService urlService; - - @Autowired - public RabbitConsumer(UrlService urlService) { - this.urlService = urlService; - } - - @RabbitListener(queues = RabbitConfig.QUEUE_CONTENT) - public void receiveContent(List urlContentDTO) { - var dto = urlContentDTO.getFirst(); - urlService.handleUrlContent(new org.wiarygodnik.credabilityservice.application.UrlContent(dto.reportId(), dto.url(), null, List.of("test"))); - log.info("URL content received"); - } -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitProducer.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitProducer.java deleted file mode 100644 index 20a24b3..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/RabbitProducer.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.wiarygodnik.credabilityservice.presentation; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.amqp.core.AmqpTemplate; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -@Slf4j -public class RabbitProducer { - private final AmqpTemplate amqpTemplate; - - @Autowired - public RabbitProducer(AmqpTemplate amqpTemplate) { - this.amqpTemplate = amqpTemplate; - } - - public void sendUrls(List urls, int reportId) { - amqpTemplate.convertAndSend( - RabbitConfig.EXCHANGE_NAME, - RabbitConfig.ROUTING_RESULTS, - new UrlsListDTO(reportId, urls) - ); - log.info("Links sent for reportId: {}", reportId); - } -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlContentDTO.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlContentDTO.java deleted file mode 100644 index b12719c..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlContentDTO.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.wiarygodnik.credabilityservice.presentation; - -import java.util.List; - -public record UrlContentDTO(int reportId, String url/*, String content, List keywords*/) { -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlsListDTO.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlsListDTO.java deleted file mode 100644 index 78dbf6a..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/presentation/UrlsListDTO.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.wiarygodnik.credabilityservice.presentation; - -import java.util.List; - -public record UrlsListDTO (int reportId, List urls) { -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsPostgresJpaRepository.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsPostgresJpaRepository.java deleted file mode 100644 index 4d7bead..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsPostgresJpaRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.wiarygodnik.credabilityservice.storage; - -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.Optional; - -@Repository -public interface UrlsPostgresJpaRepository extends JpaRepository { - @Query("SELECT u FROM UrlsRecord u WHERE u.originalUrl = :url") - Optional getUrlsByOriginalUrl(@Param("url") String url); -} diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRecord.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRecord.java deleted file mode 100644 index 56a9730..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRecord.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.wiarygodnik.credabilityservice.storage; - -import jakarta.persistence.*; -import lombok.Getter; -import lombok.Setter; - -import java.util.List; - -@Entity -public class UrlsRecord { - - @Id - @Getter - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Setter - @Getter - private String originalUrl; - - @Setter - @Getter - @ElementCollection - @CollectionTable(name = "related_urls", joinColumns = @JoinColumn(name = "record_id")) - @Column(name = "url") - private List relatedUrls; - - public UrlsRecord() {} - - public UrlsRecord(String originalUrl, List relatedUrls) { - this.originalUrl = originalUrl; - this.relatedUrls = relatedUrls; - } -} \ No newline at end of file diff --git a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRepository.java b/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRepository.java deleted file mode 100644 index f061dcb..0000000 --- a/CredabilityService/src/main/java/org/wiarygodnik/credabilityservice/storage/UrlsRepository.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.wiarygodnik.credabilityservice.storage; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -import java.util.List; - -@Repository -@Slf4j -public class UrlsRepository { - private final UrlsPostgresJpaRepository jpaRepository; - - @Autowired - public UrlsRepository(UrlsPostgresJpaRepository jpaRepository) { - this.jpaRepository = jpaRepository; - } - - public List getUrlsByOriginalUrl(String originalUrl) { - return jpaRepository.getUrlsByOriginalUrl(originalUrl).map(UrlsRecord::getRelatedUrls).orElse(null); - } - - public void save(String originalUrl, List relatedUrls) { - jpaRepository.save(new UrlsRecord(originalUrl, relatedUrls)); - log.info("Saved related links for {}", originalUrl); - } -} diff --git a/CredabilityService/src/main/resources/application.properties b/CredabilityService/src/main/resources/application.properties deleted file mode 100644 index 6ecd96b..0000000 --- a/CredabilityService/src/main/resources/application.properties +++ /dev/null @@ -1,18 +0,0 @@ -spring.application.name=CredabilityService - -spring.rabbitmq.host=localhost -spring.rabbitmq.port=5672 -spring.rabbitmq.username=guest -spring.rabbitmq.password=guest - -spring.datasource.url=jdbc:postgresql://localhost:5431/credibility -spring.datasource.username=postgres -spring.datasource.password=postgres - -spring.jpa.hibernate.ddl-auto=update -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect - -server.port=8082 - -logging.logstash.server=localhost:5000 diff --git a/CredabilityService/src/main/resources/logback-spring.xml b/CredabilityService/src/main/resources/logback-spring.xml deleted file mode 100644 index 19d9a10..0000000 --- a/CredabilityService/src/main/resources/logback-spring.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - %d{HH:mm:ss} %-5level - %msg%n - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/CredabilityService/src/test/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplicationTests.java b/CredabilityService/src/test/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplicationTests.java deleted file mode 100644 index d46ffd2..0000000 --- a/CredabilityService/src/test/java/org/wiarygodnik/credabilityservice/CredabilityServiceApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.wiarygodnik.credabilityservice; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class CredabilityServiceApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/README.md b/README.md index b3151ce..18c9950 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,19 @@ # Wiarygodnik Projekt wiarygodnik + +### Uruchamianie pełnej infrastruktury +W przypadku uruchamiania infrastruktury w środowisku Docker'owym pojawił się problem z Keycloak'iem. +Otóż zwracając się po token z frontend'u wysyłamy żądanie z `localhost`, natomiast żeby serwisy mogły zweryfikować token muszą wysląć żądanie w sieci kontenerów (bridge) na domenę `keycloak`. +Ze względu na wymóg tej samej domeny w `iss` zawartym w JWT zwracanym z Keycloak'a zostało zastosowane obejście, gdzie musimy oszukać Keycloak'a odwołując się do niego po tej samej domenie - `keycloak`. +Należy więc dodać do `/etc/hosts` poniższy wiersz: + +``` +127.0.0.1 keycloak +``` + +Reszta konfiguracji jest przygotowana pod to rozwiązanie. +Wystarczy teraz uruchomić: + +```shell +docker compose up -d +``` \ No newline at end of file diff --git a/content-analysis-service/build.gradle.kts b/content-analysis-service/build.gradle.kts index 017d8fe..a40bb94 100644 --- a/content-analysis-service/build.gradle.kts +++ b/content-analysis-service/build.gradle.kts @@ -40,14 +40,13 @@ dependencies { implementation("io.github.oshai:kotlin-logging-jvm:5.1.0") implementation("net.logstash.logback:logstash-logback-encoder:7.4") - - runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") testImplementation("com.h2database:h2:2.3.232") + + testRuntimeOnly("org.junit.platform:junit-platform-launcher") } dependencyManagement { diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/CorsProperties.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/CorsProperties.kt new file mode 100644 index 0000000..8df5cf3 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/CorsProperties.kt @@ -0,0 +1,13 @@ +package pl.edu.p.lodz.wiarygodnik.cas.config + +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties(prefix = "cors") +data class CorsProperties( + val allowedOrigins: List = emptyList(), + val allowedMethods: List = emptyList(), + val allowedHeaders: List = emptyList(), + val exposedHeaders: List = emptyList(), + val allowCredentials: Boolean = true, + val maxAge: Long = 3600 +) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt index 932ca49..7beb1f3 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt @@ -4,7 +4,7 @@ import jakarta.persistence.* @Entity class ComparisonSummary( - @OneToOne val analysis: Analysis, + @OneToOne(mappedBy = "comparisonSummary") val analysis: Analysis, @Column(columnDefinition = "TEXT") val summary: String, @OneToMany( mappedBy = "comparisonSummary", diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt index 93c1362..dcbc7e0 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt @@ -4,7 +4,7 @@ import jakarta.persistence.* @Entity class SentimentSummary( - @OneToOne val analysis: Analysis, + @OneToOne(mappedBy = "sentimentSummary") val analysis: Analysis, @Column(columnDefinition = "TEXT") val summary: String, @OneToMany( mappedBy = "sentimentSummary", diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt index d8cb09f..52dbc80 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt @@ -4,7 +4,7 @@ import jakarta.persistence.* @Entity class SourceSummary( - @OneToOne val analysis: Analysis, + @OneToOne(mappedBy = "sourceSummary") val analysis: Analysis, @Column(columnDefinition = "TEXT") val summary: String, @ElementCollection @CollectionTable(name = "source_keywords") val keywords: Set = mutableSetOf(), @Id @GeneratedValue val id: Long? = null diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt index cbeecd8..2c26763 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/CorsConfig.kt @@ -1,27 +1,31 @@ package pl.edu.p.lodz.wiarygodnik.cas.security +import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource +import pl.edu.p.lodz.wiarygodnik.cas.config.CorsProperties @Configuration -class CorsConfig { +@EnableConfigurationProperties(CorsProperties::class) +class CorsConfig(private val corsProperties: CorsProperties) { @Bean fun corsConfigurationSource(): CorsConfigurationSource { - val configuration = CorsConfiguration() - configuration.allowedOrigins = listOf("http://localhost:5173") - configuration.allowedMethods = listOf("*") - configuration.allowedHeaders = listOf("*") - configuration.exposedHeaders = listOf("*") - configuration.allowCredentials = true - configuration.maxAge = 3600L + val configuration = CorsConfiguration().apply { + allowedOrigins = corsProperties.allowedOrigins + allowedMethods = corsProperties.allowedMethods + allowedHeaders = corsProperties.allowedHeaders + exposedHeaders = corsProperties.exposedHeaders + allowCredentials = corsProperties.allowCredentials + maxAge = corsProperties.maxAge + } - val source = UrlBasedCorsConfigurationSource() - source.registerCorsConfiguration("/**", configuration) - return source + return UrlBasedCorsConfigurationSource().apply { + registerCorsConfiguration("/**", configuration) + } } } \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt index 9142013..b4a1b61 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt @@ -80,6 +80,7 @@ class AnalysisProcessor( log.info { "Scraping top matched urls [analysisId: ${analysis.id}, requestId: ${analysis.requestId}]" } val scrapedSimilarWebContents: List = topSimilarUrls .map { webScraper.scrape(it) } + .filter { it.url != analysis.sourceUrl } .filter { it.text.isNotBlank() } if (scrapedSimilarWebContents.isEmpty()) { diff --git a/content-analysis-service/src/main/resources/application.yml b/content-analysis-service/src/main/resources/application.yml index ec267ae..ad15b12 100644 --- a/content-analysis-service/src/main/resources/application.yml +++ b/content-analysis-service/src/main/resources/application.yml @@ -21,6 +21,20 @@ spring: jpa: hibernate: ddl-auto: create + defer-datasource-initialization: true + sql: + init: + mode: always + data-locations: + - classpath:initial-db/comparison_summary.sql + - classpath:initial-db/comparison_source_facts.sql + - classpath:initial-db/sentiment_summary.sql + - classpath:initial-db/sentiment_example.sql + - classpath:initial-db/sentiment_example_quote.sql + - classpath:initial-db/source_summary.sql + - classpath:initial-db/source_facts.sql + - classpath:initial-db/source_keywords.sql + - classpath:initial-db/analysis.sql ai: ollama: @@ -28,6 +42,25 @@ spring: options: model: "gpt-oss" +server: + port: 8081 + +cors: + allowed-origins: + - http://localhost:5173 + - http://localhost + allowed-methods: + - GET + - POST + - PUT + - DELETE + allowed-headers: + - "*" + exposed-headers: + - "*" + allow-credentials: true + max-age: 3600 + logging: logstash: server: "localhost:5000" @@ -37,7 +70,7 @@ jina: serpapi: url: "https://serpapi.com" - limit: 1 + limit: 5 management: endpoints: diff --git a/content-analysis-service/src/main/resources/initial-db/analysis.sql b/content-analysis-service/src/main/resources/initial-db/analysis.sql new file mode 100644 index 0000000..b2c0aa4 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/analysis.sql @@ -0,0 +1,3 @@ +INSERT INTO public.analysis (comparison_summary_id, id, sentiment_summary_id, source_summary_id, request_id, source_url, status, user_id) VALUES (1, 1, 1, 1, 'a313eb04-204a-419e-87e1-040c6c3f419c', 'https://www.gazeta.pl/lifestyle/7,198977,32504339,trump-wygadal-sie-dlaczego-bierze-duze-dawki-leku-wspomnial.html', 'COMPLETED', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); +INSERT INTO public.analysis (comparison_summary_id, id, sentiment_summary_id, source_summary_id, request_id, source_url, status, user_id) VALUES (2, 2, 2, 2, '0e91e351-499e-4f79-8f07-38779edd6681', 'https://www.pudelek.pl/anna-kurnikowa-urodzila-enrique-iglesias-zostal-ojcem-po-raz-czwarty-i-pokazal-zdjecie-dziecka-foto-7235350816422400a', 'COMPLETED', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); +INSERT INTO public.analysis (comparison_summary_id, id, sentiment_summary_id, source_summary_id, request_id, source_url, status, user_id) VALUES (5, 6, 5, 5, '4945f556-7734-4103-a2e0-7c83f8bd8d6a', 'https://www.pudelek.pl/viki-gabor-potwierdza-rozpoczecie-nowego-etapu-w-zyciu-jestem-mega-happy-7237349098839008a', 'COMPLETED', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); diff --git a/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql b/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql new file mode 100644 index 0000000..f2189fb --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql @@ -0,0 +1,11 @@ +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (1, 1, 'https://dziennik.com/trump-ujawnil-ktore-zalecenia-lekarzy-ignoruje-chce-miec-ladna-rzadka-krew/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (1, 2, 'https://wiadomosci.wp.pl/siniaki-na-dloniach-trumpa-zaskakujace-tlumaczenie-prezydenta-7238994732128768a'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (1, 3, 'https://www.rmf24.pl/fakty/swiat/newsamp-od-siniakow-po-problemy-ze-snem-trump-o-tym-dlaczego-ignoruj,nId,8054769'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (1, 4, 'https://wiadomosci.onet.pl/swiat/siniaki-na-dloniach-donalda-trumpa-rzeczniczka-bialego-domu-podala-zaskakujacy-powod/t2ldwwd'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (2, 5, 'https://www.instagram.com/p/DSzLsM1jAKY/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (2, 6, 'https://www.instagram.com/reel/DSmH_lIlEUs/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (2, 7, 'https://www.facebook.com/enews/videos/enrique-iglesias-anna-kournikova-share-sweet-family-photo-after-welcoming-baby-n/1643646783371034/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 15, 'https://www.instagram.com/p/DS4wZkmgHT-/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 16, 'https://www.instagram.com/reel/DSxwISCDItJ/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 17, 'https://www.instagram.com/p/DSx6ZhKiKK8/'); +INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 18, 'https://www.youtube.com/watch?v=BJsyIThFaFU'); diff --git a/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql b/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql new file mode 100644 index 0000000..eeb0d86 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql @@ -0,0 +1,3 @@ +INSERT INTO public.comparison_summary (id, summary) VALUES (1, 'Większość podobnych źródeł potwierdza główne informacje z głównego źródła, zwłaszcza dotyczące codziennego przyjmowania 325 mg aspiryny i dążenia do "ładnej, rzadkiej" krwi, z jedynie jednym źródłem dodającym dodatkową przyczynę siniaków.'); +INSERT INTO public.comparison_summary (id, summary) VALUES (2, 'Wszystkie podobne źródła potwierdzają ogłoszenie narodzin czwartego dziecka przez Annę Kournikovu i Enrique Iglesias, opisując rodzinne zdjęcie i celebrację. Nie ma sprzeczności, a dodatkowo podkreślają, że dziecko przyszło tuż przed świętami.'); +INSERT INTO public.comparison_summary (id, summary) VALUES (5, 'Podobne źródła w większości przeczą głównemu źródłu, twierdząc, że Viki Gabor jest żoną Giovanniego Trojanek, zamiast być tylko narzeczoną, choć jedno z nich potwierdza, że jest w związku, lecz z innym partnerem.'); diff --git a/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql b/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql new file mode 100644 index 0000000..1bf4aa6 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql @@ -0,0 +1,9 @@ +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (1, 1, 'NEGATIVE'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (2, 1, 'ALARMIST'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (3, 1, 'IRONIC'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (4, 1, 'PERSUASIVE'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (5, 2, 'POSITIVE'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (6, 2, 'PERSUASIVE'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (13, 5, 'POSITIVE'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (14, 5, 'AGGRESSIVE'); +INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (15, 5, 'IRONIC'); diff --git a/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql b/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql new file mode 100644 index 0000000..cd46244 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql @@ -0,0 +1,12 @@ +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (1, 1, 'To zdanie ukazuje odrzucenie lekarzy, co nadaje tekstowi negatywny wydźwięk.', 'Donald Trump całkowicie ignoruje zalecenia lekarzy.'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (2, 2, 'Wzmianka o siniakach i ich przyczynie wywołuje niepokój i alarm o zdrowiu prezydenta.', 'Na jego dłoniach pojawiają się siniaki, które, jak wynika z tłumaczeń Białego Domu, wynikają ze zbyt częstego brania aspiryny, a także... witania się z innymi poprzez ściśnięcie ręki.'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (3, 3, 'Zobowiązanie do powyższego zdania zawiera przesadny ton, sugerujący ironiczny komentarz autora.', 'Genetyka jest bardzo ważna, a ja mam bardzo dobre geny" - ocenił.'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (4, 4, 'Trump wyraża argument, który ma na celu przekonanie czytelników o korzyściach dużych dawek aspiryny.', 'Mówią, że aspiryna jest dobra na rozrzedzanie krwi, a ja nie chcę gęstej krwi przepływającej przez moje serce. Chcę ładnej, rzadkiej krwi przepływającej przez moje serce.'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (5, 5, 'Wykrzyknik i wielkie litery podkreślają radość i ekscytację, co czyni fragmentem wyrazistą celebrację narodzin.', 'Anna Kurnikowa URODZIŁA!'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (6, 5, 'Wypowiedź podkreśla pozytywne wydarzenie oraz udostępnienie zdjęcia, co wzmacnia poczucie szczęścia i nowej rodziny.', 'Enrique Iglesias został ojcem po raz CZWARTY i pokazał ZDJĘCIE dziecka (FOTO)'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (7, 5, 'Szczegółowe opisanie nowego dziecka i wspólnego powitania wywołuje pozytywny nastrój.', 'Późnym poniedziałkowym wieczorem poinformowała jednak w sieci, że razem z Enrique Iglesiasem powitali na świecie nowego członka rodziny.'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (8, 6, 'Wezwanie „ZOBACZ” zachęca czytelnika do aktywnego uczestnictwa i wzbudza ciekawość, co nadaje fragmentowi charakter perswazyjny.', 'ZOBACZ: Anna Kournikova z mocno zaokrąglonym brzuszkiem na zakupach z synem.'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (9, 6, 'Użycie wyrazu „NIE UKRYWA” oraz wezwanie do obejrzenia zdjęcia podkreśla perswazję, zmuszając czytelnika do sprawdzenia informacji.', 'ZOBACZ: 44-letnia Anna Kournikova już NIE UKRYWA ciążowych krągłości (ZDJĘCIA).'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (16, 13, 'Wypowiedź wyraża radość i ekscytację z nowego etapu życia, co stanowi przykład nacechowania pozytywnego.', 'Tak, zaręczyłam się i jestem mega happy'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (17, 14, 'Twardy, krytyczny ton i bezpośrednie oskarżenie wobec komentatorów wskazują na nacechowanie agresywne.', 'NIE MACIE GUSTU!'); +INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (18, 15, 'Opisanie reakcji z przśmiewczą miną sugeruje lekki, satyryczny ton, co można zakwalifikować jako ironię.', 'Moja reakcja na wasze tiktoki - podpisała zdjęcie z przśmiewczą miną'); diff --git a/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql b/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql new file mode 100644 index 0000000..5b1df01 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql @@ -0,0 +1,3 @@ +INSERT INTO public.sentiment_summary (id, summary) VALUES (1, 'Artykuł wykorzystuje negatywny, alarmistyczny oraz ironiczny ton, aby podkreślić kontrowersje dotyczące zdrowia Donalda Trumpa, jednocześnie prezentując jego własne usprawiedliwienia w sposób perswazyjny.'); +INSERT INTO public.sentiment_summary (id, summary) VALUES (2, 'Artykuł zachowuje pozytywny, sensacyjny ton, celebrując narodziny nowego członka rodziny, jednocześnie wykorzystując chwytliwe wyrażenia i wywołujące ciekawość wezwania do działania, co nadaje mu perswazyjny charakter.'); +INSERT INTO public.sentiment_summary (id, summary) VALUES (5, 'Tekst ma w większości neutralny wydźwięk, ale zawiera fragmenty radości (pozytywne), krytyki i szarpania (agresywne) oraz lekko ironicznego komentarza.'); diff --git a/content-analysis-service/src/main/resources/initial-db/source_facts.sql b/content-analysis-service/src/main/resources/initial-db/source_facts.sql new file mode 100644 index 0000000..867fb72 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/source_facts.sql @@ -0,0 +1,26 @@ +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (1, 'potwierdza, że dąży do "ładnej, rzadkiej" krwi'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (1, 'potwierdza, że siniaki na dłoniach wynikają z przyjmowania aspiryny'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (1, 'potwierdza, że Trump przyjmuje 325 mg aspiryny codziennie, pomimo zaleceń lekarzy'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (2, 'potwierdza, że dąży do "ładnej, rzadkiej" krwi'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (2, 'potwierdza, że Trump przyjmuje 325 mg aspiryny codziennie, pomimo zaleceń lekarzy'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (2, 'potwierdza, że siniaki wynikają z przyjmowania aspiryny'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (3, 'potwierdza, że dąży do "ładnej, rzadkiej" krwi'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (3, 'potwierdza, że siniaki na dłoniach wynikają z przyjmowania aspiryny'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (3, 'potwierdza, że Trump przyjmuje 325 mg aspiryny codziennie, mimo zaleceń lekarzy'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (4, 'dodaje, że siniaki mogą być spowodowane częstym ściskaniem rąk podczas spotkań'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (4, 'częściowo potwierdza, że siniaki wynikają z przyjmowania aspiryny'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (5, 'Ogłoszenie narodzin czwartego dziecka na Instagramie'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (5, 'Dziecko przyszło tuż przed Świętami Bożego Narodzenia'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (5, 'Zobrazowanie wszystkich czterech dzieci'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (6, 'Pokojowe przyjęcie czwartego dziecka'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (6, 'Rozszerzenie rodziny przed świętami'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (7, 'Publikacja ciepłego zdjęcia rodzinnego'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (7, 'Świętowanie narodzin czwartego dziecka'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (15, 'Viki Gabor jest w związku z Giovanniem Trojanek'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (15, 'Ten opis wprost potwierdza, że artystka ma partnera, choć nazwa partnera różni się od Bogdana Trojanek z głównego źródła'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (16, 'Ten relacja kontrastuje z głównym stwierdzeniem o narzeczeństwie i szczęściu'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (16, 'Viki Gabor zawarła ślub z Giovanniem Trojanek'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (17, 'Viki Gabor została małżonką, ślub w stylu romskim'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (17, 'Twierdzi to, że artystka ma już małżeństwo, co nie zgadza się z informacją o narzeczeniu'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (18, 'Bogdan Trojanek opisuje wesele Viki Gabor z Giovanniem Trojanek'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (18, 'Podkreśla, że para zawarła małżeństwo i „uciekła” z tradycyjnego obrzędu, co neguje stwierdzenie o narzeczeniu'); diff --git a/content-analysis-service/src/main/resources/initial-db/source_keywords.sql b/content-analysis-service/src/main/resources/initial-db/source_keywords.sql new file mode 100644 index 0000000..91576f0 --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/source_keywords.sql @@ -0,0 +1,28 @@ +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'krwiołamy'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'Donald Trump'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, '325 mg'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'siniaki'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'genetyka'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'Wall Street Journal'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'zdrowie'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'dłonie'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'aspiryna'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (1, 'Mar-a-Lago'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'prawa prywatności'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'rodzina'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'para'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'tenis'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'Enrique Iglesias'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'muzyka'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'Instagram'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'czwarte dziecko'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'Anna Kournikova'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (2, 'cięża'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'szczęście'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'engagement'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'Viki Gabor'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'Bogdan Trojanek'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'narzeczony'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'Instagram'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'media'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'zaślubin'); diff --git a/content-analysis-service/src/main/resources/initial-db/source_summary.sql b/content-analysis-service/src/main/resources/initial-db/source_summary.sql new file mode 100644 index 0000000..f85847a --- /dev/null +++ b/content-analysis-service/src/main/resources/initial-db/source_summary.sql @@ -0,0 +1,3 @@ +INSERT INTO public.source_summary (id, summary) VALUES (1, 'Donald Trump w wywiadzie udzielonym „Wall Street Journal” oświadczył, że codziennie przyjmuje 325 mg aspiryny ze względu na genetyczne predyspozycje do gęstej krwi i dąży do utrzymania „ładnej, rzadkiej” krwi. Wskazał, że lekarze zalecają obniżenie dawki, lecz on nie planuje zmian. Trump przyznał się również do występowania siniaków na dłoniach, które ma ukrywać makijażem, i wyjaśnił, że są wynikiem wrażliwości skóry i częstego brania aspiryny.'); +INSERT INTO public.source_summary (id, summary) VALUES (2, 'Anna Kournikova i Enrique Iglesias ogłosili narodziny czwartego dziecka. Para, znana z utrzymywania prywatności, potwierdziła nowy członek rodziny na Instagramie. Wcześniej mają dzieci Lucy, Nicholas (bliźniaki) oraz Mary. Pomimo wcześniejszych spekulacji o kolejnej ciąży, oboje nie komentowali sytuacji przed ogłoszeniem.'); +INSERT INTO public.source_summary (id, summary) VALUES (5, 'Viki Gabor potwierdziła na swoim Instagramie, że oficjalnie ma narzeczonego i jest szczęśliwa. Artystka zareagowała na rozpowszechnione w mediach informacje o jej zaślubinach z 19‑letnim Bogdanem Trojanem, które wywołały duże poruszenie. Gabor zakomentowała również komentarze publiczne i wyraziła zadowolenie z nowego etapu życia.'); diff --git a/docker-compose.yml b/docker-compose.yml index e4907d5..12e77f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,18 +1,35 @@ services: + wiarygodnik-ui: + build: + context: wiarygodnik_frontend + ports: + - "80:80" + networks: + - wiarygodnik + depends_on: + - content-analysis-service + - report-generation-service + - keycloak + content-analysis-service: build: context: content-analysis-service image: content-analysis-service:latest deploy: - replicas: 2 + replicas: 1 + ports: + - "8081:8081" + env_file: + - .env environment: - - SPRING_DATASOURCE_URL=jdbc:postgresql://content-analysis-service-db:5431/content-analysis-service-db + - SPRING_DATASOURCE_URL=jdbc:postgresql://content-analysis-service-db:5432/content-analysis-service-db - SPRING_RABBITMQ_HOST=rabbitmq - LOGGING_LOGSTASH_SERVER=logstash:5000 + - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUERURI=http://keycloak:8888/realms/wiarygodnik networks: - wiarygodnik - - elk_network +# - elk_network depends_on: - content-analysis-service-db - rabbitmq @@ -36,14 +53,17 @@ services: context: report-generation-service image: report-generation-service:latest deploy: - replicas: 2 + replicas: 1 + ports: + - "8082:8082" environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://report-generation-service-db:5432/report-generation-service-db - SPRING_RABBITMQ_HOST=rabbitmq - LOGGING_LOGSTASH_SERVER=logstash:5000 + - SPRING_SECURITY_OAUTH2_RESOURCESERVER_JWT_ISSUERURI=http://keycloak:8888/realms/wiarygodnik networks: - wiarygodnik - - elk_network +# - elk_network depends_on: - report-generation-service-db - rabbitmq @@ -62,70 +82,6 @@ services: networks: - wiarygodnik - credibility-service: - build: - context: CredabilityService - dockerfile: Dockerfile - ports: - - "8080:8080" - depends_on: - - rabbitmq - - credibility-db - environment: - - SPRING_PROFILES_ACTIVE=default - - SPRING_DATASOURCE_URL=jdbc:postgresql://credibility-db:5432/credibility - - SPRING_RABBITMQ_HOST=rabbitmq - - LOGGING_LOGSTASH_SERVER=logstash:5000 - networks: - - wiarygodnik - - elk_network - - credibility-db: - image: postgres:15 - container_name: credibility-db - restart: always - ports: - - "5431:5432" - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DB: credibility - volumes: - - postgres_data_credibility:/var/lib/postgresql/data - networks: - - wiarygodnik - - content-fetcher-service: - build: - context: ./ContentFetcher/content_fetcher - dockerfile: Dockerfile - env_file: - - ./ContentFetcher/content_fetcher/.env - depends_on: - - content-fetcher-db - - rabbitmq - command: > - sh -c "alembic upgrade head && - uvicorn app.main:app --host 0.0.0.0 --port 8080" - ports: - - "8090:8080" - networks: - - wiarygodnik - - elk_network - - content-fetcher-db: - image: postgres:17 - ports: - - "5430:5432" - environment: - POSTGRES_USER: wiarygodnik - POSTGRES_PASSWORD: secret - POSTGRES_DB: contentfetcherdb - volumes: - - contentfetcherpgdata:/var/lib/postgresql/data - networks: - - wiarygodnik - rabbitmq: image: rabbitmq:4.2.1 container_name: rabbitmq @@ -149,6 +105,7 @@ services: - wiarygodnik depends_on: - content-analysis-service + - report-generation-service keycloak: image: quay.io/keycloak/keycloak:26.4 @@ -160,10 +117,17 @@ services: KC_DB_PASSWORD: password KEYCLOAK_ADMIN: admin KC_BOOTSTRAP_ADMIN_PASSWORD: admin + KC_HTTP_PORT: 8888 +# KC_HOSTNAME: keycloak command: - start-dev + - --import-realm ports: - - "8888:8080" + - "8888:8888" + volumes: + - ./keycloak:/opt/keycloak/data/import/ + networks: + - wiarygodnik depends_on: - keycloak-db @@ -176,16 +140,16 @@ services: POSTGRES_PASSWORD: password volumes: - keycloak-db:/var/lib/postgresql/data + networks: + - wiarygodnik volumes: content-analysis-service-db: report-generation-service-db: keycloak-db: - postgres_data_credibility: - contentfetcherpgdata: networks: wiarygodnik: driver: bridge - elk_network: - external: true +# elk_network: +# external: true diff --git a/elk/docker-compose.yml b/elk/docker-compose.yml index 86d0d84..7091a8d 100644 --- a/elk/docker-compose.yml +++ b/elk/docker-compose.yml @@ -13,12 +13,13 @@ services: - network logstash: + platform: "linux/amd64" image: logstash:7.10.1 command: -f /etc/logstash/conf.d/ volumes: - ./logstash/:/etc/logstash/conf.d/ ports: - - "5000:5000" + - "5001:5000" environment: LS_JAVA_OPTS: "-Xmx256m -Xms256m" depends_on: @@ -27,6 +28,7 @@ services: - network kibana: + platform: "linux/amd64" image: kibana:7.10.1 volumes: - ./kibana/:/usr/share/kibana/config/ diff --git a/keycloak/wiarygodnik-realm.json b/keycloak/wiarygodnik-realm.json new file mode 100644 index 0000000..af0dd82 --- /dev/null +++ b/keycloak/wiarygodnik-realm.json @@ -0,0 +1,2617 @@ +{ + "id": "dbda9af0-e331-4bbb-94ed-5649a13bf01f", + "realm": "wiarygodnik", + "displayName": "", + "displayNameHtml": "", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "external", + "registrationAllowed": true, + "registrationEmailAsUsername": false, + "rememberMe": true, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": true, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "bruteForceStrategy": "MULTIPLE", + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "e5902201-f70f-44e1-aea3-db1bb1988a00", + "name": "default-roles-wiarygodnik", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization", + "user" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "dbda9af0-e331-4bbb-94ed-5649a13bf01f", + "attributes": {} + }, + { + "id": "b60dedb6-29b8-44c7-ad2b-ec2bd67db100", + "name": "user", + "description": "Common user of Wiarygodnik's main functionality", + "composite": false, + "clientRole": false, + "containerId": "dbda9af0-e331-4bbb-94ed-5649a13bf01f", + "attributes": {} + }, + { + "id": "fbf4d8fc-50ad-433c-a05d-f7b75d24e6e4", + "name": "admin", + "description": "Administrator for Wiarygodnik", + "composite": false, + "clientRole": false, + "containerId": "dbda9af0-e331-4bbb-94ed-5649a13bf01f", + "attributes": {} + }, + { + "id": "e531a616-198e-45b5-bf6f-bda54d744f56", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "dbda9af0-e331-4bbb-94ed-5649a13bf01f", + "attributes": {} + }, + { + "id": "2c9a8236-4f2a-432a-b2bb-4dd7344d83c2", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "dbda9af0-e331-4bbb-94ed-5649a13bf01f", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "712cc2fe-945a-41b4-8420-13f805299969", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "5978d899-c4b1-42f4-8450-f217db44f873", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "7255d29e-cc87-4544-a5a2-e5a103d877b1", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "d7d38f9c-201d-460e-bee7-05bfd5d00671", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "f903a0ab-2f1f-4b10-9c8e-a0cb45419e2b", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "6e1d8749-c0a9-41c7-a410-87f717137c36", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-users", + "query-groups" + ] + } + }, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "769a8219-4f20-4d20-b541-afef389d01e1", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "bae8f727-c526-413d-a891-fcb9386d07cd", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "manage-authorization", + "query-users", + "query-groups", + "create-client", + "impersonation", + "view-users", + "view-identity-providers", + "view-realm", + "query-clients", + "manage-events", + "manage-identity-providers", + "manage-users", + "view-clients", + "view-events", + "manage-realm", + "query-realms", + "view-authorization", + "manage-clients" + ] + } + }, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "cac2a2de-f659-4e11-87de-ed128829b108", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "6ae472e9-cd39-4400-9f75-8fa5271d7901", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "d2553a62-095b-44a4-8efe-521bbc462f24", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "784f4c86-a295-471c-a232-346931bf99db", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "08981caf-959e-4cfc-bab6-90bc3455d39d", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "5f57ceb4-7809-4e16-92b7-2abc7778b485", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "c998ed6f-6da6-4754-b94f-13fc649a8788", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "e435e727-e888-47b2-bac9-f1f88e4cbf85", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "8f30bc73-3dec-4503-9bf0-a86764eeed6a", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "b882e6d4-27c2-4338-b0c8-7d21c8dd1d48", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + }, + { + "id": "7a575382-9028-4526-acf5-043a8af824a2", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "attributes": {} + } + ], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "wiarygodnik-ui": [], + "broker": [ + { + "id": "662fa88f-498d-434c-8e2f-3cee9f59c7c9", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "7a961b64-19da-408d-ae28-9b02ff222d4a", + "attributes": {} + } + ], + "account": [ + { + "id": "42c30240-9dea-43a5-ae03-7dedb7dd4b89", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "92560564-ac10-4b6c-9d22-830cced477fa", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "6d040aaf-4e2b-4a0b-bc02-cc0dd320d4dd", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "0785d2f3-e435-4fb8-9736-3a9422d436fe", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "7aa4d257-a1a1-436f-924f-9c15925ff702", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "221f69a3-9856-4483-9048-5a6e29805c5f", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "4f30c283-cadf-49a3-bdcb-9a2239251225", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + }, + { + "id": "d011213d-4950-4dd9-a995-1919f6032110", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "08891115-9c24-4b3e-9571-2743a4c9befb", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "e5902201-f70f-44e1-aea3-db1bb1988a00", + "name": "default-roles-wiarygodnik", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "dbda9af0-e331-4bbb-94ed-5649a13bf01f" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256", + "RS256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256", + "RS256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "Yes", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "required", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "08891115-9c24-4b3e-9571-2743a4c9befb", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/wiarygodnik/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/wiarygodnik/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7f1921c3-d362-4f06-b6c0-b02c6c02f080", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/wiarygodnik/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/wiarygodnik/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "30f4dd53-ce82-4603-9b24-14e057de5488", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "3fa8e0b9-30a0-4f4a-8631-fe39ebd5eef9", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "7a961b64-19da-408d-ae28-9b02ff222d4a", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "cbe4c97b-dc03-451b-9b0d-c85423cea992", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "b92b8dba-99d4-4ee1-af1d-607b966cc2ad", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/wiarygodnik/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/wiarygodnik/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true", + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "4f670bd4-9332-4b23-aec7-fc04d0b8ec24", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "168b4c3b-4344-4885-8bfa-3d39823b104c", + "clientId": "wiarygodnik-ui", + "name": "User Interface for Wiarygodnik", + "description": "", + "rootUrl": "http://keycloak", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "http://localhost:5173/*", + "http://localhost/*" + ], + "webOrigins": [ + "http://localhost", + "http://localhost:5173" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "request.object.signature.alg": "any", + "frontchannel.logout.session.required": "true", + "post.logout.redirect.uris": "http://localhost:5173/*##http://localhost/*", + "oauth2.device.authorization.grant.enabled": "false", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "realm_client": "false", + "oidc.ciba.grant.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "require.pushed.authorization.requests": "false", + "request.object.encryption.enc": "any", + "dpop.bound.access.tokens": "false", + "id.token.as.detached.signature": "false", + "client.secret.creation.time": "1764936065", + "request.object.encryption.alg": "any", + "client.introspection.response.allow.jwt.claim.enabled": "false", + "standard.token.exchange.enabled": "false", + "client.use.lightweight.access.token.enabled": "false", + "request.object.required": "not required", + "access.token.header.type.rfc9068": "false", + "acr.loa.map": "{}", + "tls.client.certificate.bound.access.tokens": "false", + "display.on.consent.screen": "false", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "organization", + "offline_access", + "microprofile-jwt" + ] + } + ], + "clientScopes": [ + { + "id": "bef5cb12-7d8d-4cee-b067-fdd9c52093e4", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "ba4915ac-1822-4504-9de0-e87df6541ece", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "d01092c2-070b-4359-95b4-764d1b69ffd5", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${emailScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "07f2a64e-2069-4482-ae48-332142165324", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "3442d6db-1c6f-4ee4-8c61-370567a6145c", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "0e56b95d-f2b9-41c3-9e2d-516347d8e355", + "name": "basic", + "description": "OpenID Connect scope for add all basic claims to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "f716245b-e85a-4218-a647-7f9d4f20eeb8", + "name": "sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-sub-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "e424a190-4683-4aac-8ac8-dd12b73ed93b", + "name": "auth_time", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "AUTH_TIME", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "auth_time", + "jsonType.label": "long" + } + } + ] + }, + { + "id": "0fc53523-200a-46d9-9247-5e658fcd3d96", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "${rolesScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "6499572d-90a1-4367-8dba-446373c9a4df", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "a86a4383-e042-4f97-8e8f-84a2af00726b", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "4359a6ee-2e72-4b7b-93e5-d4eee2bb0805", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + } + ] + }, + { + "id": "9e9d0398-42bc-4c13-9983-4696b5fe4651", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "937d9511-2911-487a-b4df-d189c89ea6fc", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "28d6151f-e8d9-42fd-ae83-feeaa5cc54a4", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "5e5fa2da-fbc0-40b6-b2b6-b4e6b2a45012", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "b01e2042-0400-420d-9cbf-e3026a614a84", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "fc86877a-603a-477b-9573-bebb74c46a1c", + "name": "service_account", + "description": "Specific scope for a client enabled for service accounts", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "620ba5e5-4a2f-4ac9-be61-835555c18d32", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "258dad16-3711-4f60-8787-f035a7954c94", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "client_id", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "client_id", + "jsonType.label": "String" + } + }, + { + "id": "0e2e95d8-8c6a-4063-98a5-51bbe241f8b7", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "a93c490b-b489-413b-b1a1-aee0517a579a", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "1c953e80-df52-41e4-94a7-701636d30ffd", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "07ebe42d-e382-4a53-9873-f9472305394a", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${profileScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "2a74dbf3-7cc2-4ce3-b8a8-0d76ce1de016", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "3a564097-bda5-4a8e-95f0-b4faeba0c4ec", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "8962a55b-e08c-4622-aee1-f44eb2fe0643", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "be263ffc-b86b-44a3-99e0-7c4cba777663", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "773af3f5-ab84-4a74-a826-41f3cf937a58", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "dd60ca24-c527-4a6f-8bb8-b3a2b17b794a", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "e7053560-87e0-41b8-a0e6-e5eb4aec3b32", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "eab1be20-be3c-4e10-83ba-891a6db4b12e", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "f76af4a2-c870-41a5-95c8-f05297637710", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "d460cbcd-6f5c-44d8-8674-1d0fd196eaa9", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "13ea86a3-7bc8-42f4-9502-f6dd604a31ec", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "d87f875d-994e-4173-9b31-5ab60757b7fa", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "84fc8a5a-4039-4908-8ca1-ab7ec0bd7a80", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "874859cf-d14c-4e0b-9903-6cde36674b9b", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "39b4c472-6a98-41e1-bf07-b8027544a764", + "name": "organization", + "description": "Additional claims about the organization a subject belongs to", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${organizationScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "298b31c6-0ce6-4642-86dd-dde3ef8ce3e4", + "name": "organization", + "protocol": "openid-connect", + "protocolMapper": "oidc-organization-membership-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "organization", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "de0a3bff-75c5-428f-83fc-a73d5c66955e", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${addressScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "37fff30a-3f13-4ee2-abb7-a1ea5b2037d9", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "5fb13ffa-6881-417f-afff-e1cd0994623b", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${phoneScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "ee83446e-b168-44a6-a993-6385c11edb92", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "8c6335ec-7fcd-4a63-8263-09644e70e7cb", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "f5745336-6306-4a6c-8b18-b3328dd5167b", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "75d96294-acd0-4466-84dd-a7c133fa0b6f", + "name": "saml_organization", + "description": "Organization Membership", + "protocol": "saml", + "attributes": { + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "a41394c3-0619-4b53-8fa1-61721fa1254f", + "name": "organization", + "protocol": "saml", + "protocolMapper": "saml-organization-membership-mapper", + "consentRequired": false, + "config": {} + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "saml_organization", + "profile", + "email", + "roles", + "web-origins", + "acr", + "basic" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt", + "organization" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": false, + "eventsListeners": [ + "jboss-logging" + ], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "29f375a8-e198-47e4-af23-e1340a2f8cef", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-sha256-pairwise-sub-mapper", + "saml-role-list-mapper", + "oidc-full-name-mapper", + "saml-user-property-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper", + "oidc-address-mapper", + "oidc-usermodel-property-mapper" + ] + } + }, + { + "id": "fbda29ee-96b0-462b-bb63-e5128cc66a12", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-property-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-address-mapper", + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-full-name-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper" + ] + } + }, + { + "id": "e52365c7-29de-470a-b964-8d5c31a5e48a", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "8162b4be-a03c-4a32-aa07-7dfd4ca6a696", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "15c15f4c-09ef-485b-ac25-cd83617d6fd6", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "866fef16-57a3-4cdf-9eed-4a28ce79b276", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "5e5cb095-4e4f-4694-b22f-e2f1baac7249", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "79b98855-1a5b-4de2-9dde-37e5351373b8", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "3b9eee33-eed4-49a0-80d3-4fe42c203bc7", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "157a4976-0cc5-4dbd-8b94-b16fdaeec9a8", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "7de0b472-46a5-44f8-8c61-4e75935c279c", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "49788259-bf16-4f61-800e-db2a848dc52b", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "authenticationFlows": [ + { + "id": "b4c66468-6bac-4b3d-97b1-5d4f8392529f", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "cc764701-67f9-4f38-a048-d72f5724cbf8", + "alias": "Browser - Conditional 2FA", + "description": "Flow to determine if any 2FA is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorConfig": "browser-conditional-credential", + "authenticator": "conditional-credential", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "webauthn-authenticator", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-recovery-authn-code-form", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "8c4bf89b-fdb4-453a-8c53-4e29ad30b829", + "alias": "Browser - Conditional Organization", + "description": "Flow to determine if the organization identity-first login is to be used", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "organization", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "20a2eb02-9826-4efa-b090-cd6fa7938668", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "41b1542d-723f-497a-ae44-b195389682c3", + "alias": "First Broker Login - Conditional Organization", + "description": "Flow to determine if the authenticator that adds organization members is to be used", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "idp-add-organization-member", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "e66732a2-dedb-49ce-8558-6560702f73aa", + "alias": "First broker login - Conditional 2FA", + "description": "Flow to determine if any 2FA is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorConfig": "first-broker-login-conditional-credential", + "authenticator": "conditional-credential", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "webauthn-authenticator", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-recovery-authn-code-form", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "b6cc607c-11f5-46b7-b74d-f7fdea788945", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "e4cabd13-c30f-4116-b8ba-d0330e3da94a", + "alias": "Organization", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional Organization", + "userSetupAllowed": false + } + ] + }, + { + "id": "e6e91876-c2ef-4ec1-a0d9-c1b86de31849", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "123409de-b2f7-4d72-b2b6-11b7afe245d3", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "5bd4573f-5c07-4129-ab86-ab6ebbdc3bef", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional 2FA", + "userSetupAllowed": false + } + ] + }, + { + "id": "2676a0bf-d27f-4d15-870e-e41091dfed1b", + "alias": "browser", + "description": "Browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 26, + "autheticatorFlow": true, + "flowAlias": "Organization", + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "10b8c6c6-8b20-40db-9320-41f0b30183a8", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "873e73c5-c593-4bc1-8106-b4153c584c1d", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "7e708db4-5f63-47f7-a01e-ad5836fce28e", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "1367c177-f350-487c-becf-5e89dab8c4b1", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 60, + "autheticatorFlow": true, + "flowAlias": "First Broker Login - Conditional Organization", + "userSetupAllowed": false + } + ] + }, + { + "id": "232be4fc-afd7-4f6d-9a43-7905db3ba584", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional 2FA", + "userSetupAllowed": false + } + ] + }, + { + "id": "3538d34f-1958-48a0-b972-26798c8a4ca5", + "alias": "registration", + "description": "Registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "4dcba375-8d6d-413a-9422-9a151dd54690", + "alias": "registration form", + "description": "Registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "d30ef736-c5e4-4d2b-931e-61d20fb15351", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "82a24ee3-6bae-4612-8a95-51b44638c616", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "a72f58d7-6f84-4091-bc85-471b383febb0", + "alias": "browser-conditional-credential", + "config": { + "credentials": "webauthn-passwordless" + } + }, + { + "id": "9e7f859f-c616-48ae-9446-5a3ca407181f", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "9bf532cd-c2c5-4251-ab34-38f24baa0794", + "alias": "first-broker-login-conditional-credential", + "config": { + "credentials": "webauthn-passwordless" + } + }, + { + "id": "4c8aebb7-5ce7-4b78-b402-8e4365e87d15", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "UPDATE_EMAIL", + "name": "Update Email", + "providerId": "UPDATE_EMAIL", + "enabled": false, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 100, + "config": {} + }, + { + "alias": "delete_credential", + "name": "Delete Credential", + "providerId": "delete_credential", + "enabled": true, + "defaultAction": false, + "priority": 110, + "config": {} + }, + { + "alias": "idp_link", + "name": "Linking Identity Provider", + "providerId": "idp_link", + "enabled": true, + "defaultAction": false, + "priority": 120, + "config": {} + }, + { + "alias": "CONFIGURE_RECOVERY_AUTHN_CODES", + "name": "Recovery Authentication Codes", + "providerId": "CONFIGURE_RECOVERY_AUTHN_CODES", + "enabled": true, + "defaultAction": false, + "priority": 130, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaAuthRequestedUserHint": "login_hint", + "clientOfflineSessionMaxLifespan": "0", + "oauth2DevicePollingInterval": "5", + "clientSessionIdleTimeout": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false", + "cibaExpiresIn": "120", + "oauth2DeviceCodeLifespan": "600", + "saml.signature.algorithm": "", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "frontendUrl": "", + "acr.loa.map": "{}" + }, + "keycloakVersion": "26.4.7", + "userManagedAccessAllowed": false, + "organizationsEnabled": false, + "verifiableCredentialsEnabled": false, + "adminPermissionsEnabled": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} \ No newline at end of file diff --git a/load-balancer/conf.d/nginx.conf b/load-balancer/conf.d/nginx.conf index 543e389..7b59a00 100644 --- a/load-balancer/conf.d/nginx.conf +++ b/load-balancer/conf.d/nginx.conf @@ -1,9 +1,15 @@ server { - listen 3000; - location / { - proxy_pass http://report-generation-service:8081; + location /api/analysis { + proxy_pass http://content-analysis-service:8081; + } + + location /api/report { + proxy_pass http://report-generation-service:8082; } + location / { + proxy_pass http://wiarygodnik-ui:80; + } } \ No newline at end of file diff --git a/report-generation-service/build.gradle.kts b/report-generation-service/build.gradle.kts index f037099..6122bb8 100644 --- a/report-generation-service/build.gradle.kts +++ b/report-generation-service/build.gradle.kts @@ -23,14 +23,15 @@ repositories { extra["springAiVersion"] = "1.1.0" dependencies { - implementation("org.springframework.boot:spring-boot-starter-amqp") - implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-web") - implementation("org.springframework.boot:spring-boot-starter-security") - implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") + implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-logging") + implementation("org.springframework.boot:spring-boot-starter-security") + implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") + implementation("org.springframework.boot:spring-boot-starter-amqp") implementation("org.springframework.ai:spring-ai-starter-model-ollama") + implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("io.github.oshai:kotlin-logging-jvm:5.1.0") diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt index 1b561b8..09f308a 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt @@ -4,6 +4,7 @@ import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.amqp.rabbit.annotation.RabbitListener import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.rgs.amqp.RabbitMQConfig.Companion.ANALYSIS_RESULTS_QUEUE +import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.service.ReportService @@ -15,7 +16,8 @@ class RabbitMQConsumer(private val reportService: ReportService) { @RabbitListener(queues = [ANALYSIS_RESULTS_QUEUE]) fun contentAnalysisServiceResultsQueue(message: AnalysisResultMessage) { log.info { "Received message: $message" } - reportService.createReport(message) + val initialReport: Report = reportService.initializeReport(message) + reportService.generateReportContent(initialReport, message) } } \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/CorsProperties.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/CorsProperties.kt new file mode 100644 index 0000000..1a9cd38 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/CorsProperties.kt @@ -0,0 +1,13 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.config + +import org.springframework.boot.context.properties.ConfigurationProperties + +@ConfigurationProperties(prefix = "cors") +data class CorsProperties( + val allowedOrigins: List = emptyList(), + val allowedMethods: List = emptyList(), + val allowedHeaders: List = emptyList(), + val exposedHeaders: List = emptyList(), + val allowCredentials: Boolean = true, + val maxAge: Long = 3600 +) \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt index b69b8e8..4169ae6 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/ReportController.kt @@ -25,7 +25,7 @@ class ReportController(val reportService: ReportService) { @GetMapping("/{requestId}") fun getMyReport(@PathVariable requestId: String): ResponseEntity { - val report: Report = reportService.findReportByRequestId(requestId) + val report: Report = reportService.findGeneratedReportByRequestId(requestId) val response = ReportContentResponse.from(report) return ResponseEntity.ok(response) } diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt index 95898d2..f4ce3aa 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/controller/dto/ReportContentResponse.kt @@ -9,8 +9,7 @@ data class ReportContentResponse( val sourceUrl: String, val title: String, val credibilityLevel: CredibilityLevel, - val content: String, - val similarSourceUrls: List + val content: String ) { companion object { fun from(report: Report): ReportContentResponse { @@ -19,8 +18,7 @@ data class ReportContentResponse( sourceUrl = report.sourceUrl, title = report.title, credibilityLevel = report.credibilityLevel, - content = report.content, - similarSourceUrls = report.similarSources.map { it.sourceUrl } + content = report.content ) } } diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt index 54f8135..3104b05 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt @@ -19,15 +19,11 @@ class Report( @Version var version: Long = 0, var requestId: String, var userId: String, - var sourceUrl: String, + @Column(columnDefinition = "TEXT") var sourceUrl: String, @Enumerated(EnumType.STRING) var status: ReportStatus, var title: String = "Not generated yet", @Enumerated(EnumType.STRING) var credibilityLevel: CredibilityLevel = CredibilityLevel.LOW, - @Lob @Column(columnDefinition = "TEXT") var content: String = "Not generated yet", - @OneToMany( - cascade = [CascadeType.ALL], - mappedBy = "report" - ) var similarSources: MutableList = ArrayList() + @Column(columnDefinition = "TEXT") var content: String = "Not generated yet" ) { companion object { @@ -38,11 +34,6 @@ class Report( sourceUrl = analysisResult.sourceUrl, status = ReportStatus.GENERATING ) - analysisResult.contentComparison?.let { contentComparison -> - initialReport.similarSources = contentComparison.sourcesFacts - .map { SimilarSource(sourceUrl = it.url, report = initialReport) } - .toMutableList() - } return initialReport } } diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt deleted file mode 100644 index 0589f4e..0000000 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/SimilarSource.kt +++ /dev/null @@ -1,14 +0,0 @@ -package pl.edu.p.lodz.wiarygodnik.rgs.model - -import jakarta.persistence.* -import jakarta.persistence.GenerationType.IDENTITY - -@Entity -class SimilarSource( - @Id @GeneratedValue(strategy = IDENTITY) var id: Long = 0, - @Version var version: Long = 0, - var sourceUrl: String = "", - @ManyToOne(fetch = FetchType.LAZY, optional = false) - @JoinColumn(name = "report_id") - var report: Report? = null, -) \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt index 1ae30ba..b9da9d0 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/repo/ReportRepository.kt @@ -8,5 +8,6 @@ import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus @Transactional interface ReportRepository : JpaRepository { fun findReportByRequestIdAndUserIdAndStatus(requestId: String, userId: String, status: ReportStatus): Report? + fun findReportByRequestIdAndUserId(requestId: String, userId: String): Report? fun findAllByUserIdAndStatus(userId: String, status: ReportStatus): List } \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt index 230ad6c..313f402 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/CorsConfig.kt @@ -1,27 +1,31 @@ package pl.edu.p.lodz.wiarygodnik.rgs.security +import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.web.cors.CorsConfiguration import org.springframework.web.cors.CorsConfigurationSource import org.springframework.web.cors.UrlBasedCorsConfigurationSource +import pl.edu.p.lodz.wiarygodnik.rgs.config.CorsProperties @Configuration -class CorsConfig { +@EnableConfigurationProperties(CorsProperties::class) +class CorsConfig(private val corsProperties: CorsProperties) { @Bean fun corsConfigurationSource(): CorsConfigurationSource { - val configuration = CorsConfiguration() - configuration.allowedOrigins = listOf("http://localhost:5173") - configuration.allowedMethods = listOf("*") - configuration.allowedHeaders = listOf("*") - configuration.exposedHeaders = listOf("*") - configuration.allowCredentials = true - configuration.maxAge = 3600L + val configuration = CorsConfiguration().apply { + allowedOrigins = corsProperties.allowedOrigins + allowedMethods = corsProperties.allowedMethods + allowedHeaders = corsProperties.allowedHeaders + exposedHeaders = corsProperties.exposedHeaders + allowCredentials = corsProperties.allowCredentials + maxAge = corsProperties.maxAge + } - val source = UrlBasedCorsConfigurationSource() - source.registerCorsConfiguration("/**", configuration) - return source + return UrlBasedCorsConfigurationSource().apply { + registerCorsConfiguration("/**", configuration) + } } } \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt index 515848e..7bfc2f2 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt @@ -2,6 +2,8 @@ package pl.edu.p.lodz.wiarygodnik.rgs.service import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Propagation.REQUIRES_NEW +import org.springframework.transaction.annotation.Transactional import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.FAILED @@ -19,29 +21,37 @@ class ReportService( private val log = KotlinLogging.logger {} - fun createReport(analysisResult: AnalysisResultMessage) { + @Transactional(propagation = REQUIRES_NEW) + fun initializeReport(analysisResult: AnalysisResultMessage): Report { val newReport = Report.fromAnalysisResult(analysisResult) val persistedReport = reportRepository.save(newReport) log.info { "Initial report persisted to database [reportId: ${persistedReport.id}, requestId: ${analysisResult.requestId}]" } + return persistedReport + } + @Transactional(propagation = REQUIRES_NEW) + fun generateReportContent(report: Report, analysisResult: AnalysisResultMessage) { try { - log.info { "Generating report... [reportId: ${persistedReport.id}, requestId: ${analysisResult.requestId}]" } + log.info { "Generating report... [reportId: ${report.id}, requestId: ${analysisResult.requestId}]" } val reportGenerationResult: ReportGenerationResult = analysisReportGenerator.generate(analysisResult) - persistedReport.fillWithGeneratedContent(reportGenerationResult) - reportRepository.save(persistedReport) - log.info { "Report generated successfully and persisted to database [reportId: ${persistedReport.id}], requestId: ${analysisResult.requestId}" } + report.fillWithGeneratedContent(reportGenerationResult) + reportRepository.save(report) + log.info { "Report generated successfully and persisted to database [reportId: ${report.id}], requestId: ${analysisResult.requestId}" } } catch (e: Exception) { log.error(e) { "Generating report failed" } - persistedReport.status = FAILED - reportRepository.save(persistedReport) + report.status = FAILED + reportRepository.save(report) } } fun getReportStatus(requestId: String): ReportStatus { - return findReportByRequestId(requestId).status + val currentUserId = PrincipalProvider.getCurrentUserId() + val report: Report = reportRepository.findReportByRequestIdAndUserId(requestId, currentUserId) + ?: throw NoSuchElementException("Report not found") + return report.status } - fun findReportByRequestId(requestId: String): Report { + fun findGeneratedReportByRequestId(requestId: String): Report { val currentUserId = PrincipalProvider.getCurrentUserId() return reportRepository.findReportByRequestIdAndUserIdAndStatus(requestId, currentUserId, GENERATED) ?: throw NoSuchElementException("Report not found") diff --git a/report-generation-service/src/main/resources/application.yml b/report-generation-service/src/main/resources/application.yml index b0d620d..6316c31 100644 --- a/report-generation-service/src/main/resources/application.yml +++ b/report-generation-service/src/main/resources/application.yml @@ -21,6 +21,12 @@ spring: jpa: hibernate: ddl-auto: create + defer-datasource-initialization: true + sql: + init: + mode: always + data-locations: + - classpath:initial-db/report.sql ai: ollama: @@ -31,6 +37,22 @@ spring: server: port: 8082 +cors: + allowed-origins: + - http://localhost:5173 + - http://localhost + allowed-methods: + - GET + - POST + - PUT + - DELETE + allowed-headers: + - "*" + exposed-headers: + - "*" + allow-credentials: true + max-age: 3600 + logging: logstash: server: "localhost:5000" diff --git a/report-generation-service/src/main/resources/initial-db/report.sql b/report-generation-service/src/main/resources/initial-db/report.sql new file mode 100644 index 0000000..94ee8e7 --- /dev/null +++ b/report-generation-service/src/main/resources/initial-db/report.sql @@ -0,0 +1,3 @@ +INSERT INTO public.report (id, version, content, credibility_level, request_id, source_url, status, title, user_id) VALUES (1, 1, 'Artykuł wykorzystuje ton negatywny, alarmistyczny oraz ironiczny, co nadaje tekstowi pesymistyczny wydźwięk. Autor stosuje perswazyjne zwroty, by przekonać czytelników o skutkach przyjmowania 325 mg aspiryny. Porównanie z innymi źródłami potwierdza większość podanych faktów, w tym codzienne przyjmowanie aspiryny i dążenie do „ładnej, rzadkiej” krwi. Jedno źródło dodatkowo wspomina, że siniaki mogą wynikać również z częstego ściskania rąk, co częściowo uzupełnia opis. Spójność treści z materiałami porównawczymi jest wysoka, a rozbieżności ograniczone do drobnych uzupełnień. Na tej podstawie można stwierdzić, że informacje w artykule są w dużej mierze wiarygodne, choć nadawany ton może wpływać na percepcję czytelnika.', 'MEDIUM', 'a313eb04-204a-419e-87e1-040c6c3f419c', 'https://www.gazeta.pl/lifestyle/7,198977,32504339,trump-wygadal-sie-dlaczego-bierze-duze-dawki-leku-wspomnial.html', 'GENERATED', 'Trump aspiryna zdrowie', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); +INSERT INTO public.report (id, version, content, credibility_level, request_id, source_url, status, title, user_id) VALUES (2, 1, 'Tekst przedstawia celebrację narodzin czwartego dziecka Anny Kournikovej i Enrique Iglesias z wyraźnym, pozytywnym tonem. Autor korzysta z wykrzykników, wielkich liter oraz zachęt typu ZOBACZ, co nadaje komunikatowi perswazyjny charakter. Analiza językowa wskazuje na dominację emocjonalnego i promocyjnego języka, lecz nie wskazuje na brak prawdziwości opisu. Porównanie z treściami z Instagramu, Facebooka oraz innych źródeł potwierdza wszystkie kluczowe fakty: narodziny dziecka, zdjęcie rodzinne oraz czasowość – tuż przed świętami. Brak rozbieżności między źródłami oraz ich zgodność w szczegółach podkreśla spójność informacji. Wobec potwierdzonych faktów i braku sprzeczności, wiarygodność przekazu można uznać za wysoką, choć językowy ton pozostaje wyraźnie pozytywny.', 'HIGH', '0e91e351-499e-4f79-8f07-38779edd6681', 'https://www.pudelek.pl/anna-kurnikowa-urodzila-enrique-iglesias-zostal-ojcem-po-raz-czwarty-i-pokazal-zdjecie-dziecka-foto-7235350816422400a', 'GENERATED', 'Narodziny czwartego dziecka', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); +INSERT INTO public.report (id, version, content, credibility_level, request_id, source_url, status, title, user_id) VALUES (5, 1, 'Tekst prezentuje w większości neutralny ton, ale zawiera elementy radości oraz agresywnego krytycyzmu, co może wpływać na odbiór informacji o związku. Język zawiera fragmenty pozytywnego wydźwięku, lecz także wyrazy oskarżeń i lekki ironiczny komentarz, co utrudnia jednoznaczną interpretację. Porównanie z innymi źródłami wskazuje na rozbieżności: większość z nich potwierdza, że Viki Gabor jest żoną Giovanniego Trojanek, co niezgodne jest z głównym stwierdzeniem o narzeczeniu. Niektóre źródła jedynie potwierdzają związek, ale z innym partnerem, co dodatkowo zwiększa niepewność. Stopień spójności treści jest niski, a kluczowa informacja o statusie małżeńskim jest podważona przez większą część porównawczych materiałów. W związku z powyższymi niezgodnościami, wnioski dotyczące wiarygodności przekazu pozostają ostrożne i sugerują potrzebę dalszych weryfikacji.', 'LOW', '4945f556-7734-4103-a2e0-7c83f8bd8d6a', 'https://www.pudelek.pl/viki-gabor-potwierdza-rozpoczecie-nowego-etapu-w-zyciu-jestem-mega-happy-7237349098839008a', 'GENERATED', 'Status związku Viki Gabor', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); diff --git a/report-generation-service/src/test/kotlin/pl/edu/p/lodz/wiarygodnik/ReportApplicationTests.kt b/report-generation-service/src/test/kotlin/pl/edu/p/lodz/wiarygodnik/ReportApplicationTests.kt index a54aac4..1767793 100644 --- a/report-generation-service/src/test/kotlin/pl/edu/p/lodz/wiarygodnik/ReportApplicationTests.kt +++ b/report-generation-service/src/test/kotlin/pl/edu/p/lodz/wiarygodnik/ReportApplicationTests.kt @@ -4,9 +4,11 @@ import org.junit.jupiter.api.Test import org.springframework.boot.test.context.SpringBootTest import pl.edu.p.lodz.wiarygodnik.rgs.ReportGenerationServiceApplication import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Disabled import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationContext +@Disabled("Application context requires external dependencies") @SpringBootTest(classes = [ReportGenerationServiceApplication::class]) class ReportApplicationTests { diff --git a/wiarygodnik_frontend/.env b/wiarygodnik_frontend/.env index f41fbd1..659f540 100644 --- a/wiarygodnik_frontend/.env +++ b/wiarygodnik_frontend/.env @@ -2,6 +2,5 @@ VITE_KEYCLOAK_URL=http://localhost:8888/ VITE_KEYCLOAK_REALM=wiarygodnik VITE_KEYCLOAK_CLIENT=wiarygodnik-ui -VITE_CONTENT_ANALYSIS_SERVICE_API_URL=http://localhost:8080/ -VITE_CREADABILITY_SCORING_SERVICE_API_URL=http://localhost:8081/ +VITE_CONTENT_ANALYSIS_SERVICE_API_URL=http://localhost:8081/ VITE_REPORT_GENERATION_SERVICE_API_URL=http://localhost:8082/ \ No newline at end of file diff --git a/wiarygodnik_frontend/.env.production b/wiarygodnik_frontend/.env.production new file mode 100644 index 0000000..ec4d866 --- /dev/null +++ b/wiarygodnik_frontend/.env.production @@ -0,0 +1 @@ +VITE_KEYCLOAK_URL=http://keycloak:8888/ \ No newline at end of file diff --git a/wiarygodnik_frontend/Dockerfile b/wiarygodnik_frontend/Dockerfile new file mode 100644 index 0000000..26191d0 --- /dev/null +++ b/wiarygodnik_frontend/Dockerfile @@ -0,0 +1,25 @@ +# ---------- Build stage ---------- +FROM node:24-alpine AS build + +WORKDIR /app + +COPY package*.json ./ +RUN npm ci + +COPY . . +RUN npm run build + +# ---------- Runtime stage ---------- +FROM nginx:alpine + +# Remove default nginx config +RUN rm /etc/nginx/conf.d/default.conf + +# Custom nginx config +COPY nginx.conf /etc/nginx/conf.d/default.conf + +# Copy build output +COPY --from=build /app/dist /usr/share/nginx/html + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/wiarygodnik_frontend/nginx.conf b/wiarygodnik_frontend/nginx.conf new file mode 100644 index 0000000..9e291d4 --- /dev/null +++ b/wiarygodnik_frontend/nginx.conf @@ -0,0 +1,10 @@ +server { + listen 80; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } +} diff --git a/wiarygodnik_frontend/package-lock.json b/wiarygodnik_frontend/package-lock.json index ad719c3..859d257 100644 --- a/wiarygodnik_frontend/package-lock.json +++ b/wiarygodnik_frontend/package-lock.json @@ -8,6 +8,9 @@ "name": "wiarygodnik_frontend", "version": "0.0.0", "dependencies": { + "axios": "^1.13.2", + "keycloak-js": "^26.2.1", + "notistack": "^3.0.2", "react": "^19.2.0", "react-dom": "^19.2.0" }, @@ -18,7 +21,7 @@ "@mui/icons-material": "^7.3.6", "@mui/material": "^7.3.6", "@types/node": "^24.10.1", - "@types/react": "^19.2.5", + "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.1", "eslint": "^9.39.1", @@ -62,6 +65,7 @@ "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -394,6 +398,7 @@ "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -440,6 +445,7 @@ "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", @@ -1172,19 +1178,6 @@ "node": ">=6.0.0" } }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1247,6 +1240,7 @@ "integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.28.4", "@mui/core-downloads-tracker": "^7.3.6", @@ -1845,6 +1839,7 @@ "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1869,6 +1864,7 @@ "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1939,6 +1935,7 @@ "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.48.1", "@typescript-eslint/types": "8.48.1", @@ -2190,6 +2187,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2247,6 +2245,23 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -2311,6 +2326,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2325,14 +2341,18 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, + "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", - "optional": true, - "peer": true + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/callsites": { "version": "3.1.0", @@ -2412,14 +2432,17 @@ "dev": true, "license": "MIT" }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, + "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", - "optional": true, - "peer": true + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } }, "node_modules/concat-map": { "version": "0.0.1", @@ -2481,8 +2504,8 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/debug": { "version": "4.4.3", @@ -2509,6 +2532,15 @@ "dev": true, "license": "MIT" }, + "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/dom-helpers": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", @@ -2520,6 +2552,20 @@ "csstype": "^3.0.2" } }, + "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/electron-to-chromium": { "version": "1.5.266", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", @@ -2537,6 +2583,51 @@ "is-arrayish": "^0.2.1" } }, + "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/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", @@ -2608,6 +2699,7 @@ "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -2883,6 +2975,42 @@ "dev": true, "license": "ISC" }, + "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/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/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2902,7 +3030,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2918,6 +3045,43 @@ "node": ">=6.9.0" } }, + "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-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/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2944,6 +3108,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "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/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2961,11 +3146,37 @@ "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", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -3172,6 +3383,15 @@ "node": ">=6" } }, + "node_modules/keycloak-js": { + "version": "26.2.2", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-26.2.2.tgz", + "integrity": "sha512-ug7pNZ1xNkd7PPkerOJCEU2VnUhS7CYStDOCFJgqCNQ64h53ppxaKrh4iXH0xM8hFu5b1W6e6lsyYWqBMvaQFg==", + "license": "Apache-2.0", + "workspaces": [ + "test" + ] + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -3249,6 +3469,36 @@ "yallist": "^3.0.2" } }, + "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/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3302,6 +3552,37 @@ "dev": true, "license": "MIT" }, + "node_modules/notistack": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.2.tgz", + "integrity": "sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==", + "license": "MIT", + "dependencies": { + "clsx": "^1.1.0", + "goober": "^2.0.33" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/notistack" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/notistack/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3444,6 +3725,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -3509,6 +3791,12 @@ "dev": true, "license": "MIT" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -3524,6 +3812,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -3533,6 +3822,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -3740,31 +4030,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3811,27 +4076,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "peer": true, - "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/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -3881,6 +4125,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3967,6 +4212,7 @@ "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -4069,24 +4315,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4106,6 +4334,7 @@ "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/wiarygodnik_frontend/package.json b/wiarygodnik_frontend/package.json index b8e074d..180f089 100644 --- a/wiarygodnik_frontend/package.json +++ b/wiarygodnik_frontend/package.json @@ -23,7 +23,7 @@ "@mui/icons-material": "^7.3.6", "@mui/material": "^7.3.6", "@types/node": "^24.10.1", - "@types/react": "^19.2.5", + "@types/react": "^19.2.7", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.1", "eslint": "^9.39.1", diff --git a/wiarygodnik_frontend/src/features/report/components/ReportList.tsx b/wiarygodnik_frontend/src/features/report/components/ReportList.tsx index b7082db..02d5428 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportList.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportList.tsx @@ -7,13 +7,15 @@ import { ReportListButton } from "./ReportListButton.tsx"; import { useReportsList } from "../hooks/useReportList.ts"; import { NewReportButton } from "./NewReportButton.tsx"; +interface ReportListProps { + reload?: boolean; +} -export const ReportList = () => { +export const ReportList = ({ reload }: ReportListProps) => { const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down("sm")); - const { reports, loading } = useReportsList(); - + const { reports, loading } = useReportsList(reload); return ( { const { getMyAnalysisStatus } = useAnalysisApi(); const { getMyReportStatus } = useReportApi(); - + const [status, setStatus] = useState(undefined); useEffect(() => { @@ -30,12 +30,19 @@ export const useAnalysisStatus = (requestId: string | undefined) => { break; } } else { - const reportRes: ReportStatusResponse = await getMyReportStatus(requestId); - setStatus(reportRes.status); - if (reportRes.status === AnalysisStatus.GENERATED) { - break; - } else if (reportRes.status === AnalysisStatus.FAILED) { - break; + try { + const reportRes: ReportStatusResponse = await getMyReportStatus(requestId); + setStatus(reportRes.status); + + if (reportRes.status === AnalysisStatus.GENERATED) { + break; + } else if (reportRes.status === AnalysisStatus.FAILED) { + break; + } + } catch (err: any) { + if (err.response?.status !== 404) { + break; + } } } diff --git a/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts index 425c411..9cca08e 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { useReportApi, type ReportListItemResponse } from '../api/report.api'; -export const useReportsList = () => { +export const useReportsList = (reload: boolean | undefined) => { const { getAllMyReports } = useReportApi(); const [reports, setReports] = useState([]); @@ -11,7 +11,7 @@ export const useReportsList = () => { getAllMyReports() .then(setReports) .finally(() => setLoading(false)); - }, []); + }, [reload]); return { reports, loading }; }; diff --git a/wiarygodnik_frontend/src/pages/Reports.tsx b/wiarygodnik_frontend/src/pages/Reports.tsx index 70e5ffc..7900bf9 100644 --- a/wiarygodnik_frontend/src/pages/Reports.tsx +++ b/wiarygodnik_frontend/src/pages/Reports.tsx @@ -35,7 +35,7 @@ function Reports() { <> - {menuActive && } + {menuActive && } {report && analysis ? : status ? : } From 072dd394ae48f9c53386926e4b5577a50d29fdc4 Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Fri, 2 Jan 2026 22:31:12 +0100 Subject: [PATCH 07/15] Remove commented config --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 12e77f5..07276d3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -118,7 +118,6 @@ services: KEYCLOAK_ADMIN: admin KC_BOOTSTRAP_ADMIN_PASSWORD: admin KC_HTTP_PORT: 8888 -# KC_HOSTNAME: keycloak command: - start-dev - --import-realm From dfa2572a11dee3d9ccd69be435044ef9ee54193c Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Sun, 4 Jan 2026 21:01:56 +0100 Subject: [PATCH 08/15] Use vite plugin for PWA & adjust application to PWA --- .gitignore | 2 + content-analysis-service/build.gradle.kts | 2 + .../wiarygodnik/cas/config/RetryConfig.kt | 8 + .../p/lodz/wiarygodnik/cas/model/Analysis.kt | 4 +- .../cas/model/ComparisonSourceFacts.kt | 3 +- .../cas/model/ComparisonSummary.kt | 3 +- .../wiarygodnik/cas/model/SentimentExample.kt | 3 +- .../cas/model/SentimentExampleQuote.kt | 3 +- .../wiarygodnik/cas/model/SentimentSummary.kt | 3 +- .../wiarygodnik/cas/model/SourceSummary.kt | 3 +- .../cas/service/agent/AbstractAgent.kt | 8 + .../src/main/resources/application.yml | 1 + .../main/resources/initial-db/analysis.sql | 2 + .../initial-db/comparison_source_facts.sql | 2 + .../initial-db/comparison_summary.sql | 2 + .../initial-db/sentiment_example.sql | 2 + .../initial-db/sentiment_example_quote.sql | 2 + .../initial-db/sentiment_summary.sql | 2 + .../resources/initial-db/source_facts.sql | 2 +- .../resources/initial-db/source_keywords.sql | 2 +- .../resources/initial-db/source_summary.sql | 2 + report-generation-service/build.gradle.kts | 2 + .../wiarygodnik/rgs/config/RetryConfig.kt | 8 + .../p/lodz/wiarygodnik/rgs/model/Report.kt | 2 +- .../rgs/service/AiAnalysisReportGenerator.kt | 8 + .../src/main/resources/application.yml | 1 + .../src/main/resources/initial-db/report.sql | 2 + wiarygodnik_frontend/index.html | 19 +- wiarygodnik_frontend/package-lock.json | 9641 ++++++++++++----- wiarygodnik_frontend/package.json | 8 +- wiarygodnik_frontend/pnpm-lock.yaml | 4955 +++++++-- .../public/apple-touch-icon.png | Bin 0 -> 6431 bytes wiarygodnik_frontend/public/favicon-96x96.png | Bin 0 -> 2431 bytes wiarygodnik_frontend/public/favicon.ico | Bin 0 -> 15086 bytes wiarygodnik_frontend/public/favicon.svg | 3 + wiarygodnik_frontend/public/manifest.json | 17 +- wiarygodnik_frontend/public/robots.txt | 2 + .../public/web-app-manifest-192x192.png | Bin 0 -> 7383 bytes .../public/web-app-manifest-512x512.png | Bin 0 -> 26823 bytes .../features/auth/context/KeycloakContext.tsx | 125 +- .../features/auth/hooks/useKeycloakProfile.ts | 7 +- .../components/ContentComparisonPart.tsx | 2 +- .../report/components/ReportContent.tsx | 2 +- .../report/components/ReportSearch.tsx | 15 +- .../src/features/report/hooks/useAnalysis.ts | 5 +- .../report/hooks/useAnalysisStatus.ts | 5 +- .../src/features/report/hooks/useReport.ts | 5 +- .../features/report/hooks/useReportList.ts | 5 +- .../report}/lib/domainExtractor.ts | 0 .../src/hooks/useOnlineStatus.ts | 20 + wiarygodnik_frontend/src/main.tsx | 6 +- .../src/pages/ConnectionRequired.tsx | 34 + wiarygodnik_frontend/src/pages/User.tsx | 40 +- .../src/routing/ProtectedRoutes.tsx | 17 +- wiarygodnik_frontend/src/service-worker.ts | 80 - .../src/serviceWorkerRegistration.ts | 142 - wiarygodnik_frontend/src/vite-env.d.ts | 2 + wiarygodnik_frontend/vite.config.ts | 47 +- 58 files changed, 11204 insertions(+), 4084 deletions(-) create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/RetryConfig.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/RetryConfig.kt create mode 100644 wiarygodnik_frontend/public/apple-touch-icon.png create mode 100644 wiarygodnik_frontend/public/favicon-96x96.png create mode 100644 wiarygodnik_frontend/public/favicon.ico create mode 100644 wiarygodnik_frontend/public/favicon.svg create mode 100644 wiarygodnik_frontend/public/robots.txt create mode 100644 wiarygodnik_frontend/public/web-app-manifest-192x192.png create mode 100644 wiarygodnik_frontend/public/web-app-manifest-512x512.png rename wiarygodnik_frontend/src/{ => features/report}/lib/domainExtractor.ts (100%) create mode 100644 wiarygodnik_frontend/src/hooks/useOnlineStatus.ts create mode 100644 wiarygodnik_frontend/src/pages/ConnectionRequired.tsx delete mode 100644 wiarygodnik_frontend/src/service-worker.ts delete mode 100644 wiarygodnik_frontend/src/serviceWorkerRegistration.ts create mode 100644 wiarygodnik_frontend/src/vite-env.d.ts diff --git a/.gitignore b/.gitignore index e282855..1836925 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ build/ !**/src/main/**/build/ !**/src/test/**/build/ +dev-dist/ + ### STS ### .apt_generated .classpath diff --git a/content-analysis-service/build.gradle.kts b/content-analysis-service/build.gradle.kts index a40bb94..1ab23a1 100644 --- a/content-analysis-service/build.gradle.kts +++ b/content-analysis-service/build.gradle.kts @@ -32,6 +32,8 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") implementation("org.springframework.boot:spring-boot-starter-amqp") + implementation("org.springframework.retry:spring-retry") + implementation("org.springframework.boot:spring-boot-starter-aop") implementation("org.springframework.ai:spring-ai-starter-model-ollama") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/RetryConfig.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/RetryConfig.kt new file mode 100644 index 0000000..0e5bd24 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/config/RetryConfig.kt @@ -0,0 +1,8 @@ +package pl.edu.p.lodz.wiarygodnik.cas.config + +import org.springframework.context.annotation.Configuration +import org.springframework.retry.annotation.EnableRetry + +@Configuration +@EnableRetry +class RetryConfig \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt index 7118606..acab594 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/Analysis.kt @@ -1,7 +1,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* -import jakarta.persistence.GenerationType.IDENTITY +import jakarta.persistence.GenerationType.SEQUENCE import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentComparison @@ -18,7 +18,7 @@ class Analysis( @OneToOne(cascade = [CascadeType.ALL]) var sourceSummary: SourceSummary? = null, @OneToOne(cascade = [CascadeType.ALL]) var sentimentSummary: SentimentSummary? = null, @OneToOne(cascade = [CascadeType.ALL]) var comparisonSummary: ComparisonSummary? = null, - @Id @GeneratedValue(strategy = IDENTITY) var id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) var id: Long? = null ) { fun fillWith(contentAnalysis: ContentAnalysis) { diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt index 10cd28e..dafcdf6 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt @@ -1,11 +1,12 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* +import jakarta.persistence.GenerationType.SEQUENCE @Entity class ComparisonSourceFacts( @ManyToOne @JoinColumn(name = "comparison_summary_id") val comparisonSummary: ComparisonSummary, @Column(columnDefinition = "TEXT") val sourceUrl: String, @ElementCollection @CollectionTable(name = "source_facts") val facts: Set = mutableSetOf(), - @Id @GeneratedValue val id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt index 7beb1f3..ba9028d 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSummary.kt @@ -1,6 +1,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* +import jakarta.persistence.GenerationType.SEQUENCE @Entity class ComparisonSummary( @@ -10,5 +11,5 @@ class ComparisonSummary( mappedBy = "comparisonSummary", cascade = [CascadeType.ALL] ) var examples: MutableList = ArrayList(), - @Id @GeneratedValue val id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt index deb4593..b033bd4 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExample.kt @@ -1,6 +1,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* +import jakarta.persistence.GenerationType.SEQUENCE import pl.edu.p.lodz.wiarygodnik.cas.model.dto.Sentiment @Entity @@ -11,5 +12,5 @@ class SentimentExample( mappedBy = "sentimentExample", cascade = [CascadeType.ALL] ) var sentimentExampleQuotes: MutableList = ArrayList(), - @Id @GeneratedValue val id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt index 330eef9..320f51d 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentExampleQuote.kt @@ -1,11 +1,12 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* +import jakarta.persistence.GenerationType.SEQUENCE @Entity class SentimentExampleQuote( @ManyToOne @JoinColumn(name = "sentiment_example_id") val sentimentExample: SentimentExample, @Column(columnDefinition = "TEXT") val quote: String, @Column(columnDefinition = "TEXT") val explanation: String, - @Id @GeneratedValue val id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt index dcbc7e0..321d744 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SentimentSummary.kt @@ -1,6 +1,7 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* +import jakarta.persistence.GenerationType.SEQUENCE @Entity class SentimentSummary( @@ -10,5 +11,5 @@ class SentimentSummary( mappedBy = "sentimentSummary", cascade = [CascadeType.ALL] ) var examples: MutableList = ArrayList(), - @Id @GeneratedValue val id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt index 52dbc80..67d5152 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/SourceSummary.kt @@ -1,11 +1,12 @@ package pl.edu.p.lodz.wiarygodnik.cas.model import jakarta.persistence.* +import jakarta.persistence.GenerationType.SEQUENCE @Entity class SourceSummary( @OneToOne(mappedBy = "sourceSummary") val analysis: Analysis, @Column(columnDefinition = "TEXT") val summary: String, @ElementCollection @CollectionTable(name = "source_keywords") val keywords: Set = mutableSetOf(), - @Id @GeneratedValue val id: Long? = null + @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt index f7bc128..3b6f4ef 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt @@ -1,7 +1,10 @@ package pl.edu.p.lodz.wiarygodnik.cas.service.agent +import com.fasterxml.jackson.core.JsonParseException import org.springframework.ai.chat.client.ChatClient import org.springframework.ai.chat.model.ChatModel +import org.springframework.retry.annotation.Backoff +import org.springframework.retry.annotation.Retryable abstract class AbstractAgent(chatModel: ChatModel, private val responseType: Class) { @@ -9,6 +12,11 @@ abstract class AbstractAgent(chatModel: ChatModel, private val responseType: protected abstract fun systemPrompt(): String + @Retryable( + value = [JsonParseException::class], + maxAttempts = 3, + backoff = Backoff(delay = 0) + ) fun work(input: String): T = chatClient.prompt() .system { system -> system.text(systemPrompt()) } .user { user -> user.text(input) } diff --git a/content-analysis-service/src/main/resources/application.yml b/content-analysis-service/src/main/resources/application.yml index ad15b12..cf40321 100644 --- a/content-analysis-service/src/main/resources/application.yml +++ b/content-analysis-service/src/main/resources/application.yml @@ -48,6 +48,7 @@ server: cors: allowed-origins: - http://localhost:5173 + - http://localhost:4173 - http://localhost allowed-methods: - GET diff --git a/content-analysis-service/src/main/resources/initial-db/analysis.sql b/content-analysis-service/src/main/resources/initial-db/analysis.sql index b2c0aa4..384004f 100644 --- a/content-analysis-service/src/main/resources/initial-db/analysis.sql +++ b/content-analysis-service/src/main/resources/initial-db/analysis.sql @@ -1,3 +1,5 @@ INSERT INTO public.analysis (comparison_summary_id, id, sentiment_summary_id, source_summary_id, request_id, source_url, status, user_id) VALUES (1, 1, 1, 1, 'a313eb04-204a-419e-87e1-040c6c3f419c', 'https://www.gazeta.pl/lifestyle/7,198977,32504339,trump-wygadal-sie-dlaczego-bierze-duze-dawki-leku-wspomnial.html', 'COMPLETED', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); INSERT INTO public.analysis (comparison_summary_id, id, sentiment_summary_id, source_summary_id, request_id, source_url, status, user_id) VALUES (2, 2, 2, 2, '0e91e351-499e-4f79-8f07-38779edd6681', 'https://www.pudelek.pl/anna-kurnikowa-urodzila-enrique-iglesias-zostal-ojcem-po-raz-czwarty-i-pokazal-zdjecie-dziecka-foto-7235350816422400a', 'COMPLETED', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); INSERT INTO public.analysis (comparison_summary_id, id, sentiment_summary_id, source_summary_id, request_id, source_url, status, user_id) VALUES (5, 6, 5, 5, '4945f556-7734-4103-a2e0-7c83f8bd8d6a', 'https://www.pudelek.pl/viki-gabor-potwierdza-rozpoczecie-nowego-etapu-w-zyciu-jestem-mega-happy-7237349098839008a', 'COMPLETED', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); + +SELECT setval('analysis_seq', (SELECT MAX(id) FROM public.analysis)); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql b/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql index f2189fb..f091e88 100644 --- a/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql +++ b/content-analysis-service/src/main/resources/initial-db/comparison_source_facts.sql @@ -9,3 +9,5 @@ INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_ur INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 16, 'https://www.instagram.com/reel/DSxwISCDItJ/'); INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 17, 'https://www.instagram.com/p/DSx6ZhKiKK8/'); INSERT INTO public.comparison_source_facts (comparison_summary_id, id, source_url) VALUES (5, 18, 'https://www.youtube.com/watch?v=BJsyIThFaFU'); + +SELECT setval('comparison_source_facts_seq', (SELECT MAX(id) FROM public.comparison_source_facts)); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql b/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql index eeb0d86..32a6755 100644 --- a/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql +++ b/content-analysis-service/src/main/resources/initial-db/comparison_summary.sql @@ -1,3 +1,5 @@ INSERT INTO public.comparison_summary (id, summary) VALUES (1, 'Większość podobnych źródeł potwierdza główne informacje z głównego źródła, zwłaszcza dotyczące codziennego przyjmowania 325 mg aspiryny i dążenia do "ładnej, rzadkiej" krwi, z jedynie jednym źródłem dodającym dodatkową przyczynę siniaków.'); INSERT INTO public.comparison_summary (id, summary) VALUES (2, 'Wszystkie podobne źródła potwierdzają ogłoszenie narodzin czwartego dziecka przez Annę Kournikovu i Enrique Iglesias, opisując rodzinne zdjęcie i celebrację. Nie ma sprzeczności, a dodatkowo podkreślają, że dziecko przyszło tuż przed świętami.'); INSERT INTO public.comparison_summary (id, summary) VALUES (5, 'Podobne źródła w większości przeczą głównemu źródłu, twierdząc, że Viki Gabor jest żoną Giovanniego Trojanek, zamiast być tylko narzeczoną, choć jedno z nich potwierdza, że jest w związku, lecz z innym partnerem.'); + +SELECT setval('comparison_summary_seq', (SELECT MAX(id) FROM public.comparison_summary)); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql b/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql index 1bf4aa6..1d04af0 100644 --- a/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql +++ b/content-analysis-service/src/main/resources/initial-db/sentiment_example.sql @@ -7,3 +7,5 @@ INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUE INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (13, 5, 'POSITIVE'); INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (14, 5, 'AGGRESSIVE'); INSERT INTO public.sentiment_example (id, sentiment_summary_id, sentiment) VALUES (15, 5, 'IRONIC'); + +SELECT setval('sentiment_example_seq', (SELECT MAX(id) FROM public.sentiment_example)); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql b/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql index cd46244..cc43845 100644 --- a/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql +++ b/content-analysis-service/src/main/resources/initial-db/sentiment_example_quote.sql @@ -10,3 +10,5 @@ INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanatio INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (16, 13, 'Wypowiedź wyraża radość i ekscytację z nowego etapu życia, co stanowi przykład nacechowania pozytywnego.', 'Tak, zaręczyłam się i jestem mega happy'); INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (17, 14, 'Twardy, krytyczny ton i bezpośrednie oskarżenie wobec komentatorów wskazują na nacechowanie agresywne.', 'NIE MACIE GUSTU!'); INSERT INTO public.sentiment_example_quote (id, sentiment_example_id, explanation, quote) VALUES (18, 15, 'Opisanie reakcji z przśmiewczą miną sugeruje lekki, satyryczny ton, co można zakwalifikować jako ironię.', 'Moja reakcja na wasze tiktoki - podpisała zdjęcie z przśmiewczą miną'); + +SELECT setval('sentiment_example_quote_seq', (SELECT MAX(id) FROM public.sentiment_example_quote)); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql b/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql index 5b1df01..34184e1 100644 --- a/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql +++ b/content-analysis-service/src/main/resources/initial-db/sentiment_summary.sql @@ -1,3 +1,5 @@ INSERT INTO public.sentiment_summary (id, summary) VALUES (1, 'Artykuł wykorzystuje negatywny, alarmistyczny oraz ironiczny ton, aby podkreślić kontrowersje dotyczące zdrowia Donalda Trumpa, jednocześnie prezentując jego własne usprawiedliwienia w sposób perswazyjny.'); INSERT INTO public.sentiment_summary (id, summary) VALUES (2, 'Artykuł zachowuje pozytywny, sensacyjny ton, celebrując narodziny nowego członka rodziny, jednocześnie wykorzystując chwytliwe wyrażenia i wywołujące ciekawość wezwania do działania, co nadaje mu perswazyjny charakter.'); INSERT INTO public.sentiment_summary (id, summary) VALUES (5, 'Tekst ma w większości neutralny wydźwięk, ale zawiera fragmenty radości (pozytywne), krytyki i szarpania (agresywne) oraz lekko ironicznego komentarza.'); + +SELECT setval('sentiment_summary_seq', (SELECT MAX(id) FROM public.sentiment_summary)); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/source_facts.sql b/content-analysis-service/src/main/resources/initial-db/source_facts.sql index 867fb72..e6f8e22 100644 --- a/content-analysis-service/src/main/resources/initial-db/source_facts.sql +++ b/content-analysis-service/src/main/resources/initial-db/source_facts.sql @@ -23,4 +23,4 @@ INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (16, INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (17, 'Viki Gabor została małżonką, ślub w stylu romskim'); INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (17, 'Twierdzi to, że artystka ma już małżeństwo, co nie zgadza się z informacją o narzeczeniu'); INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (18, 'Bogdan Trojanek opisuje wesele Viki Gabor z Giovanniem Trojanek'); -INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (18, 'Podkreśla, że para zawarła małżeństwo i „uciekła” z tradycyjnego obrzędu, co neguje stwierdzenie o narzeczeniu'); +INSERT INTO public.source_facts (comparison_source_facts_id, facts) VALUES (18, 'Podkreśla, że para zawarła małżeństwo i „uciekła” z tradycyjnego obrzędu, co neguje stwierdzenie o narzeczeniu'); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/source_keywords.sql b/content-analysis-service/src/main/resources/initial-db/source_keywords.sql index 91576f0..a090787 100644 --- a/content-analysis-service/src/main/resources/initial-db/source_keywords.sql +++ b/content-analysis-service/src/main/resources/initial-db/source_keywords.sql @@ -25,4 +25,4 @@ INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'Bog INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'narzeczony'); INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'Instagram'); INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'media'); -INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'zaślubin'); +INSERT INTO public.source_keywords (source_summary_id, keywords) VALUES (5, 'zaślubin'); \ No newline at end of file diff --git a/content-analysis-service/src/main/resources/initial-db/source_summary.sql b/content-analysis-service/src/main/resources/initial-db/source_summary.sql index f85847a..a847a51 100644 --- a/content-analysis-service/src/main/resources/initial-db/source_summary.sql +++ b/content-analysis-service/src/main/resources/initial-db/source_summary.sql @@ -1,3 +1,5 @@ INSERT INTO public.source_summary (id, summary) VALUES (1, 'Donald Trump w wywiadzie udzielonym „Wall Street Journal” oświadczył, że codziennie przyjmuje 325 mg aspiryny ze względu na genetyczne predyspozycje do gęstej krwi i dąży do utrzymania „ładnej, rzadkiej” krwi. Wskazał, że lekarze zalecają obniżenie dawki, lecz on nie planuje zmian. Trump przyznał się również do występowania siniaków na dłoniach, które ma ukrywać makijażem, i wyjaśnił, że są wynikiem wrażliwości skóry i częstego brania aspiryny.'); INSERT INTO public.source_summary (id, summary) VALUES (2, 'Anna Kournikova i Enrique Iglesias ogłosili narodziny czwartego dziecka. Para, znana z utrzymywania prywatności, potwierdziła nowy członek rodziny na Instagramie. Wcześniej mają dzieci Lucy, Nicholas (bliźniaki) oraz Mary. Pomimo wcześniejszych spekulacji o kolejnej ciąży, oboje nie komentowali sytuacji przed ogłoszeniem.'); INSERT INTO public.source_summary (id, summary) VALUES (5, 'Viki Gabor potwierdziła na swoim Instagramie, że oficjalnie ma narzeczonego i jest szczęśliwa. Artystka zareagowała na rozpowszechnione w mediach informacje o jej zaślubinach z 19‑letnim Bogdanem Trojanem, które wywołały duże poruszenie. Gabor zakomentowała również komentarze publiczne i wyraziła zadowolenie z nowego etapu życia.'); + +SELECT setval('source_summary_seq', (SELECT MAX(id) FROM public.source_summary)); \ No newline at end of file diff --git a/report-generation-service/build.gradle.kts b/report-generation-service/build.gradle.kts index 6122bb8..91435e2 100644 --- a/report-generation-service/build.gradle.kts +++ b/report-generation-service/build.gradle.kts @@ -30,6 +30,8 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") implementation("org.springframework.boot:spring-boot-starter-amqp") + implementation("org.springframework.retry:spring-retry") + implementation("org.springframework.boot:spring-boot-starter-aop") implementation("org.springframework.ai:spring-ai-starter-model-ollama") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/RetryConfig.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/RetryConfig.kt new file mode 100644 index 0000000..453ca41 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/config/RetryConfig.kt @@ -0,0 +1,8 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.config + +import org.springframework.context.annotation.Configuration +import org.springframework.retry.annotation.EnableRetry + +@Configuration +@EnableRetry +class RetryConfig diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt index 3104b05..e35dde1 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt @@ -15,7 +15,7 @@ enum class CredibilityLevel { @Entity class Report( - @Id @GeneratedValue(strategy = IDENTITY) var id: Long = 0, + @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) var id: Long = 0, @Version var version: Long = 0, var requestId: String, var userId: String, diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt index 596a6eb..0b28e71 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt @@ -1,8 +1,11 @@ package pl.edu.p.lodz.wiarygodnik.rgs.service +import com.fasterxml.jackson.core.JsonParseException import org.springframework.ai.chat.client.ChatClient import org.springframework.ai.chat.model.ChatModel import org.springframework.core.io.ResourceLoader +import org.springframework.retry.annotation.Backoff +import org.springframework.retry.annotation.Retryable import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult @@ -12,6 +15,11 @@ class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader private val chatClient = ChatClient.create(chatModel) + @Retryable( + value = [JsonParseException::class], + maxAttempts = 3, + backoff = Backoff(delay = 0) + ) fun generate(input: AnalysisResultMessage): ReportGenerationResult { val analysisReportGenerationPrompt: String = prepareAnalysisReportGenerationPrompt(input) return callChatGeneration(analysisReportGenerationPrompt) diff --git a/report-generation-service/src/main/resources/application.yml b/report-generation-service/src/main/resources/application.yml index 6316c31..df51af9 100644 --- a/report-generation-service/src/main/resources/application.yml +++ b/report-generation-service/src/main/resources/application.yml @@ -40,6 +40,7 @@ server: cors: allowed-origins: - http://localhost:5173 + - http://localhost:4173 - http://localhost allowed-methods: - GET diff --git a/report-generation-service/src/main/resources/initial-db/report.sql b/report-generation-service/src/main/resources/initial-db/report.sql index 94ee8e7..062a60c 100644 --- a/report-generation-service/src/main/resources/initial-db/report.sql +++ b/report-generation-service/src/main/resources/initial-db/report.sql @@ -1,3 +1,5 @@ INSERT INTO public.report (id, version, content, credibility_level, request_id, source_url, status, title, user_id) VALUES (1, 1, 'Artykuł wykorzystuje ton negatywny, alarmistyczny oraz ironiczny, co nadaje tekstowi pesymistyczny wydźwięk. Autor stosuje perswazyjne zwroty, by przekonać czytelników o skutkach przyjmowania 325 mg aspiryny. Porównanie z innymi źródłami potwierdza większość podanych faktów, w tym codzienne przyjmowanie aspiryny i dążenie do „ładnej, rzadkiej” krwi. Jedno źródło dodatkowo wspomina, że siniaki mogą wynikać również z częstego ściskania rąk, co częściowo uzupełnia opis. Spójność treści z materiałami porównawczymi jest wysoka, a rozbieżności ograniczone do drobnych uzupełnień. Na tej podstawie można stwierdzić, że informacje w artykule są w dużej mierze wiarygodne, choć nadawany ton może wpływać na percepcję czytelnika.', 'MEDIUM', 'a313eb04-204a-419e-87e1-040c6c3f419c', 'https://www.gazeta.pl/lifestyle/7,198977,32504339,trump-wygadal-sie-dlaczego-bierze-duze-dawki-leku-wspomnial.html', 'GENERATED', 'Trump aspiryna zdrowie', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); INSERT INTO public.report (id, version, content, credibility_level, request_id, source_url, status, title, user_id) VALUES (2, 1, 'Tekst przedstawia celebrację narodzin czwartego dziecka Anny Kournikovej i Enrique Iglesias z wyraźnym, pozytywnym tonem. Autor korzysta z wykrzykników, wielkich liter oraz zachęt typu ZOBACZ, co nadaje komunikatowi perswazyjny charakter. Analiza językowa wskazuje na dominację emocjonalnego i promocyjnego języka, lecz nie wskazuje na brak prawdziwości opisu. Porównanie z treściami z Instagramu, Facebooka oraz innych źródeł potwierdza wszystkie kluczowe fakty: narodziny dziecka, zdjęcie rodzinne oraz czasowość – tuż przed świętami. Brak rozbieżności między źródłami oraz ich zgodność w szczegółach podkreśla spójność informacji. Wobec potwierdzonych faktów i braku sprzeczności, wiarygodność przekazu można uznać za wysoką, choć językowy ton pozostaje wyraźnie pozytywny.', 'HIGH', '0e91e351-499e-4f79-8f07-38779edd6681', 'https://www.pudelek.pl/anna-kurnikowa-urodzila-enrique-iglesias-zostal-ojcem-po-raz-czwarty-i-pokazal-zdjecie-dziecka-foto-7235350816422400a', 'GENERATED', 'Narodziny czwartego dziecka', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); INSERT INTO public.report (id, version, content, credibility_level, request_id, source_url, status, title, user_id) VALUES (5, 1, 'Tekst prezentuje w większości neutralny ton, ale zawiera elementy radości oraz agresywnego krytycyzmu, co może wpływać na odbiór informacji o związku. Język zawiera fragmenty pozytywnego wydźwięku, lecz także wyrazy oskarżeń i lekki ironiczny komentarz, co utrudnia jednoznaczną interpretację. Porównanie z innymi źródłami wskazuje na rozbieżności: większość z nich potwierdza, że Viki Gabor jest żoną Giovanniego Trojanek, co niezgodne jest z głównym stwierdzeniem o narzeczeniu. Niektóre źródła jedynie potwierdzają związek, ale z innym partnerem, co dodatkowo zwiększa niepewność. Stopień spójności treści jest niski, a kluczowa informacja o statusie małżeńskim jest podważona przez większą część porównawczych materiałów. W związku z powyższymi niezgodnościami, wnioski dotyczące wiarygodności przekazu pozostają ostrożne i sugerują potrzebę dalszych weryfikacji.', 'LOW', '4945f556-7734-4103-a2e0-7c83f8bd8d6a', 'https://www.pudelek.pl/viki-gabor-potwierdza-rozpoczecie-nowego-etapu-w-zyciu-jestem-mega-happy-7237349098839008a', 'GENERATED', 'Status związku Viki Gabor', 'c01f6e22-d152-4723-8600-8e31e0e33ec9'); + +SELECT setval('report_seq', (SELECT MAX(id) FROM public.report)); \ No newline at end of file diff --git a/wiarygodnik_frontend/index.html b/wiarygodnik_frontend/index.html index 92748c0..ca05e22 100644 --- a/wiarygodnik_frontend/index.html +++ b/wiarygodnik_frontend/index.html @@ -1,12 +1,19 @@ - - - - - - + + + + + + + + + + + + + Wiarygodnik diff --git a/wiarygodnik_frontend/package-lock.json b/wiarygodnik_frontend/package-lock.json index 859d257..1f9e664 100644 --- a/wiarygodnik_frontend/package-lock.json +++ b/wiarygodnik_frontend/package-lock.json @@ -31,7 +31,13 @@ "react-router-dom": "^6.30.2", "typescript": "~5.9.3", "typescript-eslint": "^8.46.4", - "vite": "^7.2.4" + "vite": "^7.2.4", + "vite-plugin-pwa": "^1.2.0", + "workbox-background-sync": "^7.4.0", + "workbox-core": "^7.4.0", + "workbox-precaching": "^7.4.0", + "workbox-routing": "^7.4.0", + "workbox-strategies": "^7.4.0" } }, "node_modules/@babel/code-frame": { @@ -108,6 +114,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", @@ -125,6 +144,63 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dev": true, + "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.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "dev": true, + "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-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -135,6 +211,20 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "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.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", @@ -167,6 +257,19 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", @@ -177,6 +280,56 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, + "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.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "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", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -207,6 +360,21 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helpers": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", @@ -237,26 +405,27 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", "dependencies": { @@ -266,1294 +435,1357 @@ "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.13.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", - "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/serialize": "^1.3.3", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@emotion/cache": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", - "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", "dependencies": { - "@emotion/memoize": "^0.9.0", - "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "stylis": "4.2.0" + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", - "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", "dev": true, "license": "MIT", "dependencies": { - "@emotion/memoize": "^0.9.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@emotion/react": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", - "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.13.5", - "@emotion/cache": "^11.14.0", - "@emotion/serialize": "^1.3.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "hoist-non-react-statics": "^3.3.1" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" }, - "peerDependencies": { - "react": ">=16.8.0" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/serialize": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", - "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", "dev": true, "license": "MIT", "dependencies": { - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.2", - "csstype": "^3.0.2" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/sheet": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", - "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@emotion/styled": { - "version": "11.14.1", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", - "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", + "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.13.5", - "@emotion/is-prop-valid": "^1.3.0", - "@emotion/serialize": "^1.3.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", - "@emotion/utils": "^1.4.2" + "@babel/helper-plugin-utils": "^7.27.1" }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/unitless": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", - "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", - "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", "dev": true, "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": { - "react": ">=16.8.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@emotion/utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", - "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } }, - "node_modules/@emotion/weak-memoize": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", - "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", "dev": true, - "license": "MIT" + "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/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", + "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", + "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", + "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", + "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.2" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@eslint/core": "^0.17.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@types/json-schema": "^7.0.15" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "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.2", - "strip-json-comments": "^3.1.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@eslint/js": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", - "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=18.18.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, "engines": { - "node": ">=12.22" + "node": ">=6.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18.18" + "node": ">=6.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@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/@mui/core-downloads-tracker": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.6.tgz", - "integrity": "sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==", + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", "dev": true, "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "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/@mui/icons-material": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.3.6.tgz", - "integrity": "sha512-0FfkXEj22ysIq5pa41A2NbcAhJSvmcZQ/vcTIbjDsd6hlslG82k5BEBqqS0ZJprxwIL3B45qpJ+bPHwJPlF7uQ==", + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.4" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@mui/material": "^7.3.6", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0" } }, - "node_modules/@mui/material": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz", - "integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==", + "node_modules/@babel/preset-env": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz", + "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@babel/runtime": "^7.28.4", - "@mui/core-downloads-tracker": "^7.3.6", - "@mui/system": "^7.3.6", - "@mui/types": "^7.4.9", - "@mui/utils": "^7.3.6", - "@popperjs/core": "^2.11.8", - "@types/react-transition-group": "^4.4.12", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "prop-types": "^15.8.1", - "react-is": "^19.2.0", - "react-transition-group": "^4.4.5" + "@babel/compat-data": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.5", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.4", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.28.5", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.28.5", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.4", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.4", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" }, "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^7.3.6", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@mui/material-pigment-css": { - "optional": true - }, - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/private-theming": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.6.tgz", - "integrity": "sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==", + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.4", - "@mui/utils": "^7.3.6", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, - "node_modules/@mui/styled-engine": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.6.tgz", - "integrity": "sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==", + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.28.4", - "@emotion/cache": "^11.14.0", - "@emotion/serialize": "^1.3.3", - "@emotion/sheet": "^1.4.0", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" - }, "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@mui/system": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.6.tgz", - "integrity": "sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==", + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.4", - "@mui/private-theming": "^7.3.6", - "@mui/styled-engine": "^7.3.6", - "@mui/types": "^7.4.9", - "@mui/utils": "^7.3.6", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@mui/types": { - "version": "7.4.9", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.9.tgz", - "integrity": "sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==", + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.4" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@mui/utils": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.6.tgz", - "integrity": "sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==", + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.28.4", - "@mui/types": "^7.4.9", - "@types/prop-types": "^15.7.15", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^19.2.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "node": ">=6.9.0" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", "dev": true, "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@remix-run/router": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.1.tgz", - "integrity": "sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==", + "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=14.0.0" + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" } }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.47", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz", - "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==", + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", "dev": true, "license": "MIT" }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], + "node_modules/@emotion/is-prop-valid": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz", + "integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "dependencies": { + "@emotion/memoize": "^0.9.0" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "license": "MIT" }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.1", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz", + "integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "peer": true, + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ - "x64" + "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "freebsd" - ] + "aix" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], @@ -1561,41 +1793,50 @@ "license": "MIT", "optional": true, "os": [ - "linux" - ] + "android" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "android" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "android" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], @@ -1603,69 +1844,186 @@ "license": "MIT", "optional": true, "os": [ - "linux" - ] + "darwin" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ - "loong64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "darwin" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ - "riscv64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ - "riscv64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], @@ -1674,12 +2032,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" ], @@ -1688,12 +2049,32 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" ], @@ -1701,1456 +2082,5012 @@ "license": "MIT", "optional": true, "os": [ - "linux" - ] + "netbsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "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.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.6.tgz", + "integrity": "sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.3.6.tgz", + "integrity": "sha512-0FfkXEj22ysIq5pa41A2NbcAhJSvmcZQ/vcTIbjDsd6hlslG82k5BEBqqS0ZJprxwIL3B45qpJ+bPHwJPlF7uQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.3.6", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz", + "integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/core-downloads-tracker": "^7.3.6", + "@mui/system": "^7.3.6", + "@mui/types": "^7.4.9", + "@mui/utils": "^7.3.6", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.2.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.3.6", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/private-theming": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.6.tgz", + "integrity": "sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/utils": "^7.3.6", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.6.tgz", + "integrity": "sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.6.tgz", + "integrity": "sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/private-theming": "^7.3.6", + "@mui/styled-engine": "^7.3.6", + "@mui/types": "^7.4.9", + "@mui/utils": "^7.3.6", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.9.tgz", + "integrity": "sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.6.tgz", + "integrity": "sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.28.4", + "@mui/types": "^7.4.9", + "@types/prop-types": "^15.7.15", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.1.tgz", + "integrity": "sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.47", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.47.tgz", + "integrity": "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", + "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", + "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz", + "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/type-utils": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.48.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz", + "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", + "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", + "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", + "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", + "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", + "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", + "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.48.1", + "@typescript-eslint/tsconfig-utils": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", + "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", + "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz", + "integrity": "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.5", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.47", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/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/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "dev": true, + "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.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz", + "integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "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/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "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/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT", + "peer": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "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/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.266", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", + "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", + "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.24.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", + "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-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/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@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.12.4", + "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.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz", + "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/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/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "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-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true, + "license": "ISC" + }, + "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/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/goober": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", + "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", + "license": "MIT", + "peerDependencies": { + "csstype": "^3.0.10" + } + }, + "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", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.0.0" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true, "license": "MIT" }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "undici-types": "~7.16.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/@types/react": { - "version": "19.2.7", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", - "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", "dev": true, "license": "MIT", - "peer": true, - "dependencies": { - "csstype": "^3.2.2" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "^19.2.0" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "*" + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz", - "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==", + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/type-utils": "8.48.1", - "@typescript-eslint/utils": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.48.1", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, "engines": { - "node": ">= 4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/parser": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz", - "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "debug": "^4.3.4" + "which-typed-array": "^1.1.16" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", - "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.48.1", - "@typescript-eslint/types": "^8.48.1", - "debug": "^4.3.4" + "call-bound": "^1.0.3" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", - "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", - "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "20 || >=22" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", - "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/utils": "8.48.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/@typescript-eslint/types": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", - "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=0.10.0" + } + }, + "node_modules/keycloak-js": { + "version": "26.2.2", + "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-26.2.2.tgz", + "integrity": "sha512-ug7pNZ1xNkd7PPkerOJCEU2VnUhS7CYStDOCFJgqCNQ64h53ppxaKrh4iXH0xM8hFu5b1W6e6lsyYWqBMvaQFg==", + "license": "Apache-2.0", + "workspaces": [ + "test" + ] + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", - "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.48.1", - "@typescript-eslint/tsconfig-utils": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/visitor-keys": "8.48.1", - "debug": "^4.3.4", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "yallist": "^3.0.2" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "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": ">=10" + "node": ">= 0.4" } }, - "node_modules/@typescript-eslint/utils": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", - "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", - "dev": true, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.48.1", - "@typescript-eslint/types": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1" - }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "node": ">= 0.6" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", - "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.48.1", - "eslint-visitor-keys": "^4.2.1" + "mime-db": "1.52.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">= 0.6" } }, - "node_modules/@vitejs/plugin-react": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz", - "integrity": "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA==", + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@babel/core": "^7.28.5", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.47", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + "node": "*" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, + "license": "ISC", "engines": { - "node": ">=0.4.0" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "license": "MIT" }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "bin": { + "nanoid": "bin/nanoid.cjs" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, + "license": "MIT" + }, + "node_modules/notistack": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.2.tgz", + "integrity": "sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "clsx": "^1.1.0", + "goober": "^2.0.33" }, "engines": { - "node": ">=8" + "node": ">=12.0.0", + "npm": ">=6.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/notistack" + }, + "peerDependencies": { + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, - "node_modules/axios": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", - "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "node_modules/notistack/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" + "engines": { + "node": ">=6" } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, "engines": { - "node": ">=10", - "npm": ">=6" + "node": ">=0.10.0" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.4.tgz", - "integrity": "sha512-ZCQ9GEWl73BVm8bu5Fts8nt7MHdbt5vY9bP6WGnUh+r3l8M7CgfyTlwsgCbMC66BNxPr6Xoce3j66Ms5YUQTNA==", + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" + "license": "MIT", + "engines": { + "node": ">= 0.4" } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "peer": true, "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" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "node": ">= 0.8.0" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { + "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, "engines": { "node": ">=6" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, - "license": "MIT" - }, - "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": ">=8" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" }, "engines": { - "node": ">=10" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { - "node": ">= 6" + "node": "20 || >=22" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT", - "peer": true + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, "engines": { - "node": ">=6.0" + "node": ">=12" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, - "license": "MIT" - }, - "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": ">= 0.4" } }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", "dev": true, + "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": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, - "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" + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12 || >=14" } }, - "node_modules/electron-to-chromium": { - "version": "1.5.266", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", - "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", - "dev": true, - "license": "ISC" - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/pretty-bytes": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" } }, - "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==", + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=6" } }, - "node_modules/es-set-tostringtag": { + "node_modules/randombytes": { "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==", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" + "safe-buffer": "^5.1.0" } }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "dev": true, - "hasInstallScript": true, + "node_modules/react": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", + "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "peer": true, "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "node": ">=0.10.0" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, + "node_modules/react-dom": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", + "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "license": "MIT", - "engines": { - "node": ">=6" + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.1" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/react-is": { + "version": "19.2.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz", + "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/eslint": { - "version": "9.39.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", - "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "node_modules/react-router": { + "version": "6.30.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.2.tgz", + "integrity": "sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.1", - "@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.12.4", - "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.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" + "@remix-run/router": "1.23.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" + "node": ">=14.0.0" }, "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } + "react": ">=16.8" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", - "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "node_modules/react-router-dom": { + "version": "6.30.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.2.tgz", + "integrity": "sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" + "@remix-run/router": "1.23.1", + "react-router": "6.30.2" }, "engines": { - "node": ">=18" + "node": ">=14.0.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" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz", - "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==", + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, "peerDependencies": { - "eslint": ">=8.40" + "react": ">=16.6.0", + "react-dom": ">=16.6.0" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } + "license": "MIT" }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" + "regenerate": "^1.4.2" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=4" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "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.0" + "node": ">=4" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12.0.0" + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "peerDependencies": { - "picomatch": "^3 || ^4" + "bin": { + "resolve": "bin/resolve" }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, "engines": { - "node": ">=16.0.0" + "node": ">=4" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true, - "license": "MIT" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10" + "node": ">=18.0.0", + "npm": ">=8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" }, "engines": { - "node": ">=16" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, - "license": "ISC" - }, - "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" + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" }, "engines": { - "node": ">= 6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, "engines": { - "node": ">=6.9.0" + "node": ">= 0.4" } }, - "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==", + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", + "define-data-property": "^1.1.4", "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" + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=8" } }, - "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/goober": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz", - "integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==", - "license": "MIT", - "peerDependencies": { - "csstype": "^3.0.10" - } - }, - "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": ">=8" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, "engines": { "node": ">= 0.4" }, @@ -3158,13 +7095,17 @@ "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==", + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" @@ -3173,579 +7114,720 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", "dev": true, "license": "MIT" }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { - "hermes-estree": "0.25.1" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", "dev": true, "license": "MIT" }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, "engines": { - "node": ">= 4" + "node": ">= 0.4" } }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, "engines": { - "node": ">=0.8.19" + "node": ">=8" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/keycloak-js": { - "version": "26.2.2", - "resolved": "https://registry.npmjs.org/keycloak-js/-/keycloak-js-26.2.2.tgz", - "integrity": "sha512-ug7pNZ1xNkd7PPkerOJCEU2VnUhS7CYStDOCFJgqCNQ64h53ppxaKrh4iXH0xM8hFu5b1W6e6lsyYWqBMvaQFg==", - "license": "Apache-2.0", - "workspaces": [ - "test" - ] - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 0.8.0" + "node": ">=8" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, "engines": { "node": ">=10" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", "dev": true, "license": "MIT" }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" + "has-flag": "^4.0.0" }, - "bin": { - "loose-envify": "cli.js" + "engines": { + "node": ">=8" } }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, "license": "MIT", "dependencies": { - "mime-db": "1.52.0" + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", "dev": true, - "license": "ISC", + "license": "BSD-2-Clause", + "peer": true, "dependencies": { - "brace-expansion": "^1.1.7" + "@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": "*" + "node": ">=10" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } }, - "node_modules/notistack": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/notistack/-/notistack-3.0.2.tgz", - "integrity": "sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "license": "MIT", "dependencies": { - "clsx": "^1.1.0", - "goober": "^2.0.33" + "prelude-ls": "^1.2.1" }, "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/notistack" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, - "peerDependencies": { - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + "engines": { + "node": ">= 0.4" } }, - "node_modules/notistack/node_modules/clsx": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", - "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "license": "MIT", "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" + "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" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz", + "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "@typescript-eslint/eslint-plugin": "8.48.1", + "@typescript-eslint/parser": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1" }, "engines": { - "node": ">=10" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^3.0.2" + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", "dev": true, "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=4", + "yarn": "*" } }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", "dev": true, "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" + "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", @@ -3754,558 +7836,737 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", + "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-pwa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.2.0.tgz", + "integrity": "sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.6", + "pretty-bytes": "^6.1.1", + "tinyglobby": "^0.2.10", + "workbox-build": "^7.4.0", + "workbox-window": "^7.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vite-pwa/assets-generator": "^1.0.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "workbox-build": "^7.4.0", + "workbox-window": "^7.4.0" + }, + "peerDependenciesMeta": { + "@vite-pwa/assets-generator": { + "optional": true + } + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prelude-ls": { + "node_modules/which-builtin-type": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "license": "MIT", "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "license": "MIT", + "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" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/react": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", - "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/react-dom": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", - "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", + "node_modules/workbox-background-sync": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.4.0.tgz", + "integrity": "sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.1" + "idb": "^7.0.1", + "workbox-core": "7.4.0" } }, - "node_modules/react-is": { - "version": "19.2.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.1.tgz", - "integrity": "sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==", - "dev": true, - "license": "MIT" - }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "node_modules/workbox-broadcast-update": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-7.4.0.tgz", + "integrity": "sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "workbox-core": "7.4.0" } }, - "node_modules/react-router": { - "version": "6.30.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.2.tgz", - "integrity": "sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==", + "node_modules/workbox-build": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-7.4.0.tgz", + "integrity": "sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==", "dev": true, "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.1" + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-replace": "^2.4.1", + "@rollup/plugin-terser": "^0.4.3", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^11.0.1", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.79.2", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "7.4.0", + "workbox-broadcast-update": "7.4.0", + "workbox-cacheable-response": "7.4.0", + "workbox-core": "7.4.0", + "workbox-expiration": "7.4.0", + "workbox-google-analytics": "7.4.0", + "workbox-navigation-preload": "7.4.0", + "workbox-precaching": "7.4.0", + "workbox-range-requests": "7.4.0", + "workbox-recipes": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0", + "workbox-streams": "7.4.0", + "workbox-sw": "7.4.0", + "workbox-window": "7.4.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=10" }, "peerDependencies": { - "react": ">=16.8" + "ajv": ">=8" } }, - "node_modules/react-router-dom": { - "version": "6.30.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.2.tgz", - "integrity": "sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==", + "node_modules/workbox-build/node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", "dev": true, "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.1", - "react-router": "6.30.2" + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" }, "engines": { - "node": ">=14.0.0" + "node": ">= 10.0.0" }, "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } } }, - "node_modules/react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "node_modules/workbox-build/node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" }, "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" + "rollup": "^1.20.0 || ^2.0.0" } }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "node_modules/workbox-build/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", "dev": true, "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" + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" }, "engines": { - "node": ">= 0.4" + "node": ">= 8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "node_modules/workbox-build/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "node_modules/workbox-build/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true, "license": "MIT" }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "node_modules/workbox-build/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, "engines": { - "node": ">=8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "node_modules/workbox-build/node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "node_modules/workbox-build/node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "peer": true, + "bin": { + "rollup": "dist/bin/rollup" + }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "deprecated": "The work that was done in this beta branch won't be included in future versions", "dev": true, "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/workbox-cacheable-response": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-7.4.0.tgz", + "integrity": "sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "workbox-core": "7.4.0" } }, - "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "node_modules/workbox-core": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-7.4.0.tgz", + "integrity": "sha512-6BMfd8tYEnN4baG4emG9U0hdXM4gGuDU3ectXuVHnj71vwxTFI7WOpQJC4siTOlVtGqCUtj0ZQNsrvi6kZZTAQ==", "dev": true, "license": "MIT" }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/workbox-expiration": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-7.4.0.tgz", + "integrity": "sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "idb": "^7.0.1", + "workbox-core": "7.4.0" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "node_modules/workbox-google-analytics": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-7.4.0.tgz", + "integrity": "sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "workbox-background-sync": "7.4.0", + "workbox-core": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0" } }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "node_modules/workbox-navigation-preload": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-7.4.0.tgz", + "integrity": "sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" + "workbox-core": "7.4.0" } }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "node_modules/workbox-precaching": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-7.4.0.tgz", + "integrity": "sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" + "dependencies": { + "workbox-core": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0" } }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "node_modules/workbox-range-requests": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-7.4.0.tgz", + "integrity": "sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" + "workbox-core": "7.4.0" } }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "node_modules/workbox-recipes": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-7.4.0.tgz", + "integrity": "sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==", "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" + "license": "MIT", + "dependencies": { + "workbox-cacheable-response": "7.4.0", + "workbox-core": "7.4.0", + "workbox-expiration": "7.4.0", + "workbox-precaching": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0" } }, - "node_modules/typescript-eslint": { - "version": "8.48.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz", - "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==", + "node_modules/workbox-routing": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-7.4.0.tgz", + "integrity": "sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.48.1", - "@typescript-eslint/parser": "8.48.1", - "@typescript-eslint/typescript-estree": "8.48.1", - "@typescript-eslint/utils": "8.48.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" + "workbox-core": "7.4.0" } }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "node_modules/workbox-strategies": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-7.4.0.tgz", + "integrity": "sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } }, - "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "node_modules/workbox-streams": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-7.4.0.tgz", + "integrity": "sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "workbox-core": "7.4.0", + "workbox-routing": "7.4.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "node_modules/workbox-sw": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.4.0.tgz", + "integrity": "sha512-ltU+Kr3qWR6BtbdlMnCjobZKzeV1hN+S6UvDywBrwM19TTyqA03X66dzw1tEIdJvQ4lYKkBFox6IAEhoSEZ8Xw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/workbox-window": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-7.4.0.tgz", + "integrity": "sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==", + "dev": true, + "license": "MIT", "dependencies": { - "punycode": "^2.1.0" + "@types/trusted-types": "^2.0.2", + "workbox-core": "7.4.0" } }, - "node_modules/vite": { - "version": "7.2.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.6.tgz", - "integrity": "sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==", + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": "^20.19.0 || >=22.12.0" + "node": ">=12" }, "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" + "engines": { + "node": ">=10" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "license": "ISC", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" }, - "bin": { - "node-which": "bin/node-which" + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" }, "engines": { - "node": ">= 8" + "node": ">=8" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/yallist": { diff --git a/wiarygodnik_frontend/package.json b/wiarygodnik_frontend/package.json index 180f089..eaba588 100644 --- a/wiarygodnik_frontend/package.json +++ b/wiarygodnik_frontend/package.json @@ -33,6 +33,12 @@ "react-router-dom": "^6.30.2", "typescript": "~5.9.3", "typescript-eslint": "^8.46.4", - "vite": "^7.2.4" + "vite": "^7.2.4", + "vite-plugin-pwa": "^1.2.0", + "workbox-background-sync": "^7.4.0", + "workbox-core": "^7.4.0", + "workbox-precaching": "^7.4.0", + "workbox-routing": "^7.4.0", + "workbox-strategies": "^7.4.0" } } diff --git a/wiarygodnik_frontend/pnpm-lock.yaml b/wiarygodnik_frontend/pnpm-lock.yaml index 6f74b42..b9f5956 100644 --- a/wiarygodnik_frontend/pnpm-lock.yaml +++ b/wiarygodnik_frontend/pnpm-lock.yaml @@ -43,14 +43,14 @@ importers: specifier: ^24.10.1 version: 24.10.1 '@types/react': - specifier: ^19.2.5 + specifier: ^19.2.7 version: 19.2.7 '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.7) '@vitejs/plugin-react': specifier: ^5.1.1 - version: 5.1.2(vite@7.2.7(@types/node@24.10.1)) + version: 5.1.2(vite@7.2.7(@types/node@24.10.1)(terser@5.44.1)) eslint: specifier: ^9.39.1 version: 9.39.1 @@ -74,10 +74,34 @@ importers: version: 8.48.1(eslint@9.39.1)(typescript@5.9.3) vite: specifier: ^7.2.4 - version: 7.2.7(@types/node@24.10.1) + version: 7.2.7(@types/node@24.10.1)(terser@5.44.1) + vite-plugin-pwa: + specifier: ^1.2.0 + version: 1.2.0(vite@7.2.7(@types/node@24.10.1)(terser@5.44.1))(workbox-build@7.4.0(@types/babel__core@7.20.5))(workbox-window@7.4.0) + workbox-background-sync: + specifier: ^7.4.0 + version: 7.4.0 + workbox-core: + specifier: ^7.4.0 + version: 7.4.0 + workbox-precaching: + specifier: ^7.4.0 + version: 7.4.0 + workbox-routing: + specifier: ^7.4.0 + version: 7.4.0 + workbox-strategies: + specifier: ^7.4.0 + version: 7.4.0 packages: + '@apideck/better-ajv-errors@0.3.6': + resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} + engines: {node: '>=10'} + peerDependencies: + ajv: '>=8' + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -94,14 +118,39 @@ packages: resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} + '@babel/helper-create-class-features-plugin@7.28.5': + resolution: {integrity: sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.5': + resolution: {integrity: sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} engines: {node: '>=6.9.0'} @@ -112,10 +161,30 @@ packages: peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -128,6 +197,10 @@ packages: resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} engines: {node: '>=6.9.0'} + '@babel/helper-wrap-function@7.28.3': + resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} + engines: {node: '>=6.9.0'} + '@babel/helpers@7.28.4': resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} engines: {node: '>=6.9.0'} @@ -137,1447 +210,3156 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.0.0 - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} engines: {node: '>=6.9.0'} peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/core': ^7.0.0 - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 - '@babel/traverse@7.28.5': - resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3': + resolution: {integrity: sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@babel/types@7.28.5': - resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/babel-plugin@11.13.5': - resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + '@babel/plugin-syntax-import-assertions@7.27.1': + resolution: {integrity: sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/cache@11.14.0': - resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/hash@0.9.2': - resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@emotion/is-prop-valid@1.4.0': - resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/memoize@0.9.0': - resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + '@babel/plugin-transform-async-generator-functions@7.28.0': + resolution: {integrity: sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/react@11.14.0': - resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} + '@babel/plugin-transform-async-to-generator@7.27.1': + resolution: {integrity: sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==} + engines: {node: '>=6.9.0'} peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true + '@babel/core': ^7.0.0-0 - '@emotion/serialize@1.3.3': - resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/sheet@1.4.0': - resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + '@babel/plugin-transform-block-scoping@7.28.5': + resolution: {integrity: sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/styled@11.14.1': - resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==} + '@babel/plugin-transform-class-properties@7.27.1': + resolution: {integrity: sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==} + engines: {node: '>=6.9.0'} peerDependencies: - '@emotion/react': ^11.0.0-rc.0 - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true + '@babel/core': ^7.0.0-0 - '@emotion/unitless@0.10.0': - resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} + '@babel/plugin-transform-class-static-block@7.28.3': + resolution: {integrity: sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 - '@emotion/use-insertion-effect-with-fallbacks@1.2.0': - resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} + '@babel/plugin-transform-classes@7.28.4': + resolution: {integrity: sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==} + engines: {node: '>=6.9.0'} peerDependencies: - react: '>=16.8.0' + '@babel/core': ^7.0.0-0 - '@emotion/utils@1.4.2': - resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} + '@babel/plugin-transform-computed-properties@7.27.1': + resolution: {integrity: sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@emotion/weak-memoize@0.4.0': - resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] + '@babel/plugin-transform-dotall-regex@7.27.1': + resolution: {integrity: sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] + '@babel/plugin-transform-explicit-resource-management@7.28.0': + resolution: {integrity: sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] + '@babel/plugin-transform-exponentiation-operator@7.28.5': + resolution: {integrity: sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] + '@babel/plugin-transform-json-strings@7.27.1': + resolution: {integrity: sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] + '@babel/plugin-transform-logical-assignment-operators@7.28.5': + resolution: {integrity: sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] + '@babel/plugin-transform-modules-systemjs@7.28.5': + resolution: {integrity: sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1': + resolution: {integrity: sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1': + resolution: {integrity: sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] + '@babel/plugin-transform-numeric-separator@7.27.1': + resolution: {integrity: sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] + '@babel/plugin-transform-object-rest-spread@7.28.4': + resolution: {integrity: sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] + '@babel/plugin-transform-optional-catch-binding@7.27.1': + resolution: {integrity: sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] + '@babel/plugin-transform-optional-chaining@7.28.5': + resolution: {integrity: sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@babel/plugin-transform-private-methods@7.27.1': + resolution: {integrity: sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==} + engines: {node: '>=6.9.0'} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@babel/core': ^7.0.0-0 - '@eslint-community/regexpp@4.12.2': - resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@babel/plugin-transform-private-property-in-object@7.27.1': + resolution: {integrity: sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint/config-helpers@0.4.2': - resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint/core@0.17.0': - resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint/eslintrc@3.3.3': - resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-regenerator@7.28.4': + resolution: {integrity: sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-regexp-modifiers@7.27.1': + resolution: {integrity: sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@eslint/object-schema@2.1.7': - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@eslint/plugin-kit@0.4.1': - resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} + '@babel/plugin-transform-spread@7.27.1': + resolution: {integrity: sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} - engines: {node: '>=18.18.0'} + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@humanwhocodes/retry@0.4.3': - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} - engines: {node: '>=18.18'} + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@babel/plugin-transform-unicode-property-regex@7.27.1': + resolution: {integrity: sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@babel/plugin-transform-unicode-sets-regex@7.27.1': + resolution: {integrity: sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@babel/preset-env@7.28.5': + resolution: {integrity: sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 - '@mui/core-downloads-tracker@7.3.6': - resolution: {integrity: sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==} + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - '@mui/icons-material@7.3.6': - resolution: {integrity: sha512-0FfkXEj22ysIq5pa41A2NbcAhJSvmcZQ/vcTIbjDsd6hlslG82k5BEBqqS0ZJprxwIL3B45qpJ+bPHwJPlF7uQ==} - engines: {node: '>=14.0.0'} + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + + '@emotion/babel-plugin@11.13.5': + resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + + '@emotion/cache@11.14.0': + resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + + '@emotion/is-prop-valid@1.4.0': + resolution: {integrity: sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==} + + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + + '@emotion/react@11.14.0': + resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} peerDependencies: - '@mui/material': ^7.3.6 - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 + '@types/react': '*' + react: '>=16.8.0' peerDependenciesMeta: '@types/react': optional: true - '@mui/material@7.3.6': - resolution: {integrity: sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==} - engines: {node: '>=14.0.0'} + '@emotion/serialize@1.3.3': + resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + + '@emotion/sheet@1.4.0': + resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + + '@emotion/styled@11.14.1': + resolution: {integrity: sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==} peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@mui/material-pigment-css': ^7.3.6 - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + '@emotion/react': ^11.0.0-rc.0 + '@types/react': '*' + react: '>=16.8.0' peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@mui/material-pigment-css': - optional: true - '@types/react': - optional: true - - '@mui/private-theming@7.3.6': - resolution: {integrity: sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - '@mui/styled-engine@7.3.6': - resolution: {integrity: sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@emotion/react': ^11.4.1 - '@emotion/styled': ^11.3.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': + '@types/react': optional: true - '@mui/system@7.3.6': - resolution: {integrity: sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true + '@emotion/unitless@0.10.0': + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} - '@mui/types@7.4.9': - resolution: {integrity: sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==} + '@emotion/use-insertion-effect-with-fallbacks@1.2.0': + resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true + react: '>=16.8.0' - '@mui/utils@7.3.6': - resolution: {integrity: sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==} - engines: {node: '>=14.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true + '@emotion/utils@1.4.2': + resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} - '@popperjs/core@2.11.8': - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@emotion/weak-memoize@0.4.0': + resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@remix-run/router@1.23.1': - resolution: {integrity: sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==} - engines: {node: '>=14.0.0'} + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] - '@rolldown/pluginutils@1.0.0-beta.53': - resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] - '@rollup/rollup-android-arm-eabi@4.53.3': - resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.3': - resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} - cpu: [arm64] + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.3': - resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.3': - resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.3': - resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.3': - resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': - resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} - cpu: [arm] + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.53.3': - resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.53.3': - resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.53.3': - resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} - cpu: [arm64] + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.53.3': - resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.53.3': - resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} - cpu: [ppc64] + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.53.3': - resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} - cpu: [riscv64] + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.53.3': - resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.53.3': - resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.53.3': - resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.53.3': - resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} cpu: [x64] - os: [linux] + os: [netbsd] - '@rollup/rollup-openharmony-arm64@4.53.3': - resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.3': - resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.3': - resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.3': - resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.53.3': - resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} cpu: [x64] os: [win32] - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + '@eslint/config-array@0.21.1': + resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@types/babel__traverse@7.28.0': - resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@types/json-schema@7.0.15': + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.1': + resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@mui/core-downloads-tracker@7.3.6': + resolution: {integrity: sha512-QaYtTHlr8kDFN5mE1wbvVARRKH7Fdw1ZuOjBJcFdVpfNfRYKF3QLT4rt+WaB6CKJvpqxRsmEo0kpYinhH5GeHg==} + + '@mui/icons-material@7.3.6': + resolution: {integrity: sha512-0FfkXEj22ysIq5pa41A2NbcAhJSvmcZQ/vcTIbjDsd6hlslG82k5BEBqqS0ZJprxwIL3B45qpJ+bPHwJPlF7uQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@mui/material': ^7.3.6 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@mui/material@7.3.6': + resolution: {integrity: sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@mui/material-pigment-css': ^7.3.6 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@mui/material-pigment-css': + optional: true + '@types/react': + optional: true + + '@mui/private-theming@7.3.6': + resolution: {integrity: sha512-Ws9wZpqM+FlnbZXaY/7yvyvWQo1+02Tbx50mVdNmzWEi51C51y56KAbaDCYyulOOBL6BJxuaqG8rNNuj7ivVyw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@mui/styled-engine@7.3.6': + resolution: {integrity: sha512-+wiYbtvj+zyUkmDB+ysH6zRjuQIJ+CM56w0fEXV+VDNdvOuSywG+/8kpjddvvlfMLsaWdQe5oTuYGBcodmqGzQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.4.1 + '@emotion/styled': ^11.3.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + + '@mui/system@7.3.6': + resolution: {integrity: sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@emotion/react': ^11.5.0 + '@emotion/styled': ^11.3.0 + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/react': + optional: true + '@emotion/styled': + optional: true + '@types/react': + optional: true + + '@mui/types@7.4.9': + resolution: {integrity: sha512-dNO8Z9T2cujkSIaCnWwprfeKmTWh97cnjkgmpFJ2sbfXLx8SMZijCYHOtP/y5nnUb/Rm2omxbDMmtUoSaUtKaw==} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@mui/utils@7.3.6': + resolution: {integrity: sha512-jn+Ba02O6PiFs7nKva8R2aJJ9kJC+3kQ2R0BbKNY3KQQ36Qng98GnPRFTlbwYTdMD6hLEBKaMLUktyg/rTfd2w==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17.0.0 || ^18.0.0 || ^19.0.0 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + '@remix-run/router@1.23.1': + resolution: {integrity: sha512-vDbaOzF7yT2Qs4vO6XV1MHcJv+3dgR1sT+l3B8xxOVhUC336prMvqrvsLL/9Dnw2xr6Qhz4J0dmS0llNAbnUmQ==} + engines: {node: '>=14.0.0'} + + '@rolldown/pluginutils@1.0.0-beta.53': + resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + + '@rollup/plugin-babel@5.3.1': + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + + '@rollup/plugin-node-resolve@15.3.1': + resolution: {integrity: sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.78.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/plugin-replace@2.4.2': + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + + '@rollup/plugin-terser@0.4.4': + resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/pluginutils@3.1.0': + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.53.3': + resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.53.3': + resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.53.3': + resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.53.3': + resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.53.3': + resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.53.3': + resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.53.3': + resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.53.3': + resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.53.3': + resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.53.3': + resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.53.3': + resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.53.3': + resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.53.3': + resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.53.3': + resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.53.3': + resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.53.3': + resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openharmony-arm64@4.53.3': + resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.53.3': + resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.53.3': + resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.53.3': + resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.53.3': + resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + cpu: [x64] + os: [win32] + + '@surma/rollup-plugin-off-main-thread@2.2.3': + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + + '@types/estree@0.0.39': + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@24.10.1': - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react-transition-group@4.4.12': + resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} + peerDependencies: + '@types/react': '*' + + '@types/react@19.2.7': + resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} + + '@types/resolve@1.20.2': + resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@typescript-eslint/eslint-plugin@8.48.1': + resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.48.1 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.48.1': + resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.48.1': + resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.48.1': + resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.48.1': + resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.48.1': + resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.48.1': + resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.48.1': + resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.48.1': + resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.48.1': + resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@vitejs/plugin-react@5.1.2': + resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axios@1.13.2: + resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + + babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + + babel-plugin-polyfill-corejs2@0.4.14: + resolution: {integrity: sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.5: + resolution: {integrity: sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + baseline-browser-mapping@2.9.5: + resolution: {integrity: sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==} + hasBin: true + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001759: + resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + clsx@1.2.1: + resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} + engines: {node: '>=6'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-js-compat@3.47.0: + resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dom-helpers@5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.266: + resolution: {integrity: sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-abstract@1.24.1: + resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-plugin-react-hooks@7.0.1: + resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react-refresh@0.4.24: + resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==} + peerDependencies: + eslint: '>=8.40' + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.39.1: + resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + hasBin: true + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.5.0: + resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + goober@2.1.18: + resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} + peerDependencies: + csstype: ^3.0.10 + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} + + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + keycloak-js@26.2.1: + resolution: {integrity: sha512-bZt6fQj/TLBAmivXSxSlqAJxBx/knNZDQGJIW4ensGYGN4N6tUKV8Zj3Y7/LOV8eIpvWsvqV70fbACihK8Ze0Q==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@11.2.4: + resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@10.1.1: + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + notistack@3.0.2: + resolution: {integrity: sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==} + engines: {node: '>=12.0.0', npm: '>=6.0.0'} + peerDependencies: + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} - '@types/parse-json@4.0.2': - resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} - '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} - peerDependencies: - '@types/react': ^19.2.0 + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - '@types/react-transition-group@4.4.12': - resolution: {integrity: sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==} - peerDependencies: - '@types/react': '*' + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} - '@types/react@19.2.7': - resolution: {integrity: sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==} + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} - '@typescript-eslint/eslint-plugin@8.48.1': - resolution: {integrity: sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.48.1 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} - '@typescript-eslint/parser@8.48.1': - resolution: {integrity: sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} - '@typescript-eslint/project-service@8.48.1': - resolution: {integrity: sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - '@typescript-eslint/scope-manager@8.48.1': - resolution: {integrity: sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + path-scurry@2.0.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} - '@typescript-eslint/tsconfig-utils@8.48.1': - resolution: {integrity: sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} - '@typescript-eslint/type-utils@8.48.1': - resolution: {integrity: sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - '@typescript-eslint/types@8.48.1': - resolution: {integrity: sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} - '@typescript-eslint/typescript-estree@8.48.1': - resolution: {integrity: sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.0.0' + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} - '@typescript-eslint/utils@8.48.1': - resolution: {integrity: sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + + pretty-bytes@6.1.1: + resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} + engines: {node: ^14.13.1 || >=16.0.0} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + react-dom@19.2.1: + resolution: {integrity: sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + react: ^19.2.1 - '@typescript-eslint/visitor-keys@8.48.1': - resolution: {integrity: sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - '@vitejs/plugin-react@5.1.2': - resolution: {integrity: sha512-EcA07pHJouywpzsoTUqNh5NwGayl2PPVEJKUSinGGSxFGYn+shYbqMGBg6FXDqgXum9Ou/ecb+411ssw8HImJQ==} - engines: {node: ^20.19.0 || >=22.12.0} + react-is@19.2.1: + resolution: {integrity: sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==} + + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + + react-router-dom@6.30.2: + resolution: {integrity: sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==} + engines: {node: '>=14.0.0'} peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + react: '>=16.8' + react-dom: '>=16.8' - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + react-router@6.30.2: + resolution: {integrity: sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==} + engines: {node: '>=14.0.0'} peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + react: '>=16.8' - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true + react-transition-group@4.4.5: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + react@19.2.1: + resolution: {integrity: sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==} + engines: {node: '>=0.10.0'} - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - axios@1.13.2: - resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} - babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} - baseline-browser-mapping@2.9.5: - resolution: {integrity: sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==} + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} hasBin: true - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} hasBin: true - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + + rollup@4.53.3: + resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} - caniuse-lite@1.0.30001759: - resolution: {integrity: sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==} + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} + hasBin: true - clsx@1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} - convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} - cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} + smob@1.5.0: + resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} - dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} - electron-to-chromium@1.5.266: - resolution: {integrity: sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} - error-ex@1.3.4: - resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} - es-define-property@1.0.1: - resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} - es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} engines: {node: '>= 0.4'} - es-object-atoms@1.1.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} engines: {node: '>= 0.4'} - es-set-tostringtag@2.1.0: - resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true + stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + strip-ansi@7.1.2: + resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + engines: {node: '>=12'} + + strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} engines: {node: '>=10'} - eslint-plugin-react-hooks@7.0.1: - resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==} - engines: {node: '>=18'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} - eslint-plugin-react-refresh@0.4.24: - resolution: {integrity: sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==} - peerDependencies: - eslint: '>=8.40' + stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - eslint-scope@8.4.0: - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} - eslint-visitor-keys@4.2.1: - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + + terser@5.44.1: + resolution: {integrity: sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==} + engines: {node: '>=10'} hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - espree@10.4.0: - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typescript-eslint@8.48.1: + resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true - find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} - follow-redirects@1.15.11: - resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} - form-data@4.0.5: - resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} - engines: {node: '>= 6'} + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} + upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} - get-intrinsic@1.3.0: - resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} - engines: {node: '>= 0.4'} + update-browserslist-db@1.2.2: + resolution: {integrity: sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' - get-proto@1.0.1: - resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} - engines: {node: '>= 0.4'} + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + vite-plugin-pwa@1.2.0: + resolution: {integrity: sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@vite-pwa/assets-generator': ^1.0.0 + vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + workbox-build: ^7.4.0 + workbox-window: ^7.4.0 + peerDependenciesMeta: + '@vite-pwa/assets-generator': + optional: true - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} + vite@7.2.7: + resolution: {integrity: sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true - globals@16.5.0: - resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} - engines: {node: '>=18'} + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} - goober@2.1.18: - resolution: {integrity: sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==} - peerDependencies: - csstype: ^3.0.10 + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} - gopd@1.2.0: - resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} engines: {node: '>= 0.4'} - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - - has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} engines: {node: '>= 0.4'} - has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} engines: {node: '>= 0.4'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + which-typed-array@1.1.19: + resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} engines: {node: '>= 0.4'} - hermes-estree@0.25.1: - resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} - - hermes-parser@0.25.1: - resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} - engines: {node: '>= 4'} - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} + workbox-background-sync@7.4.0: + resolution: {integrity: sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==} - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + workbox-broadcast-update@7.4.0: + resolution: {integrity: sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==} - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + workbox-build@7.4.0: + resolution: {integrity: sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==} + engines: {node: '>=20.0.0'} - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + workbox-cacheable-response@7.4.0: + resolution: {integrity: sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==} - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + workbox-core@7.4.0: + resolution: {integrity: sha512-6BMfd8tYEnN4baG4emG9U0hdXM4gGuDU3ectXuVHnj71vwxTFI7WOpQJC4siTOlVtGqCUtj0ZQNsrvi6kZZTAQ==} - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true + workbox-expiration@7.4.0: + resolution: {integrity: sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==} - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true + workbox-google-analytics@7.4.0: + resolution: {integrity: sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==} - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + workbox-navigation-preload@7.4.0: + resolution: {integrity: sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==} - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + workbox-precaching@7.4.0: + resolution: {integrity: sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==} - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + workbox-range-requests@7.4.0: + resolution: {integrity: sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==} - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + workbox-recipes@7.4.0: + resolution: {integrity: sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==} - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true + workbox-routing@7.4.0: + resolution: {integrity: sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==} - keycloak-js@26.2.1: - resolution: {integrity: sha512-bZt6fQj/TLBAmivXSxSlqAJxBx/knNZDQGJIW4ensGYGN4N6tUKV8Zj3Y7/LOV8eIpvWsvqV70fbACihK8Ze0Q==} + workbox-strategies@7.4.0: + resolution: {integrity: sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==} - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + workbox-streams@7.4.0: + resolution: {integrity: sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==} - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} + workbox-sw@7.4.0: + resolution: {integrity: sha512-ltU+Kr3qWR6BtbdlMnCjobZKzeV1hN+S6UvDywBrwM19TTyqA03X66dzw1tEIdJvQ4lYKkBFox6IAEhoSEZ8Xw==} - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + workbox-window@7.4.0: + resolution: {integrity: sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==} - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} + zod-validation-error@4.0.2: + resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.25.0 || ^4.0.0 - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + zod@4.1.13: + resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} +snapshots: - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true + '@babel/compat-data@7.28.5': {} - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + '@babel/core@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color - node-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 - notistack@3.0.2: - resolution: {integrity: sha512-0R+/arLYbK5Hh7mEfR2adt0tyXJcCC9KkA2hc56FeWik2QN6Bm/S4uW+BjzDARsJth5u06nTjelSw/VSnB1YEA==} - engines: {node: '>=12.0.0', npm: '>=6.0.0'} - peerDependencies: - react: ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.5 - object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} + '@babel/helper-create-class-features-plugin@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@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.27.1(@babel/core@7.28.5) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.5 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} + '@babel/helper-define-polyfill-provider@0.6.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} + '@babel/helper-globals@7.28.0': {} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color - path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.5 - path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} + '@babel/helper-plugin-utils@7.27.1': {} - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.3 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - postcss@8.5.6: - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} - engines: {node: ^10 || ^12 || >=14} + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} + '@babel/helper-string-parser@7.27.1': {} - prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + '@babel/helper-validator-identifier@7.28.5': {} - proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + '@babel/helper-validator-option@7.27.1': {} - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} + '@babel/helper-wrap-function@7.28.3': + dependencies: + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color - react-dom@19.2.1: - resolution: {integrity: sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==} - peerDependencies: - react: ^19.2.1 + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 - react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 - react-is@19.2.1: - resolution: {integrity: sha512-L7BnWgRbMwzMAubQcS7sXdPdNLmKlucPlopgAzx7FtYbksWZgEWiuYM5x9T6UqS2Ne0rsgQTq5kY2SGqpzUkYA==} + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - react-refresh@0.18.0: - resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} - engines: {node: '>=0.10.0'} + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - react-router-dom@6.30.2: - resolution: {integrity: sha512-l2OwHn3UUnEVUqc6/1VMmR1cvZryZ3j3NzapC2eUXO1dB0sYp5mvwdjiXhpUbRb21eFow3qSxpP8Yv6oAU824Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' - react-dom: '>=16.8' + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - react-router@6.30.2: - resolution: {integrity: sha512-H2Bm38Zu1bm8KUE5NVWRMzuIyAV8p/JrOaBJAwVmp37AXG72+CZJlEBw6pdn9i5TBgLMhNDgijS4ZlblpHyWTA==} - engines: {node: '>=14.0.0'} - peerDependencies: - react: '>=16.8' + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color - react-transition-group@4.4.5: - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - react@19.2.1: - resolution: {integrity: sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==} - engines: {node: '>=0.10.0'} + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} + '@babel/plugin-syntax-import-assertions@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} - hasBin: true + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - rollup@4.53.3: - resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true + '@babel/plugin-transform-async-generator-functions@7.28.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.5) + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} - engines: {node: '>=10'} - hasBin: true + '@babel/plugin-transform-async-to-generator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color - shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + '@babel/plugin-transform-block-scoping@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} + '@babel/plugin-transform-class-properties@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color - source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} + '@babel/plugin-transform-class-static-block@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + '@babel/plugin-transform-classes@7.28.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@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/core@7.28.5) + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + '@babel/plugin-transform-computed-properties@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/template': 7.27.2 - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} + '@babel/plugin-transform-dotall-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - typescript-eslint@8.48.1: - resolution: {integrity: sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + '@babel/plugin-transform-explicit-resource-management@7.28.0(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true + '@babel/plugin-transform-exponentiation-operator@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - update-browserslist-db@1.2.2: - resolution: {integrity: sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - vite@7.2.7: - resolution: {integrity: sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true + '@babel/plugin-transform-json-strings@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} + '@babel/plugin-transform-logical-assignment-operators@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color - zod-validation-error@4.0.2: - resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - zod: ^3.25.0 || ^4.0.0 + '@babel/plugin-transform-modules-systemjs@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color - zod@4.1.13: - resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color -snapshots: + '@babel/plugin-transform-named-capturing-groups-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/code-frame@7.27.1': + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/compat-data@7.28.5': {} + '@babel/plugin-transform-nullish-coalescing-operator@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/core@7.28.5': + '@babel/plugin-transform-numeric-separator@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-object-rest-spread@7.28.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) - '@babel/helpers': 7.28.4 - '@babel/parser': 7.28.5 - '@babel/template': 7.27.2 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.5) '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 - '@jridgewell/remapping': 2.3.5 - convert-source-map: 2.0.0 - debug: 4.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/generator@7.28.5': + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/parser': 7.28.5 - '@babel/types': 7.28.5 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color - '@babel/helper-compilation-targets@7.27.2': + '@babel/plugin-transform-optional-catch-binding@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/compat-data': 7.28.5 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-globals@7.28.0': {} + '@babel/plugin-transform-optional-chaining@7.28.5(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color - '@babel/helper-module-imports@7.27.1': + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.28.5)': dependencies: - '@babel/traverse': 7.28.5 - '@babel/types': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-private-methods@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + '@babel/plugin-transform-private-property-in-object@7.27.1(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 - '@babel/helper-module-imports': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.28.5 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.27.1': {} + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-string-parser@7.27.1': {} + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-validator-identifier@7.28.5': {} + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/helper-validator-option@7.27.1': {} + '@babel/plugin-transform-regenerator@7.28.4(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 - '@babel/helpers@7.28.4': + '@babel/plugin-transform-regexp-modifiers@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-spread@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-property-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/parser@7.28.5': + '@babel/plugin-transform-unicode-sets-regex@7.27.1(@babel/core@7.28.5)': dependencies: - '@babel/types': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.28.5) + '@babel/helper-plugin-utils': 7.27.1 - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.5)': + '@babel/preset-env@7.28.5(@babel/core@7.28.5)': dependencies: + '@babel/compat-data': 7.28.5 '@babel/core': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.3(@babel/core@7.28.5) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.28.5) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.28.5) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-async-generator-functions': 7.28.0(@babel/core@7.28.5) + '@babel/plugin-transform-async-to-generator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-block-scoping': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-class-static-block': 7.28.3(@babel/core@7.28.5) + '@babel/plugin-transform-classes': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-computed-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-dotall-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-explicit-resource-management': 7.28.0(@babel/core@7.28.5) + '@babel/plugin-transform-exponentiation-operator': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-json-strings': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-logical-assignment-operators': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-modules-systemjs': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-named-capturing-groups-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-nullish-coalescing-operator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-object-rest-spread': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-optional-catch-binding': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-optional-chaining': 7.28.5(@babel/core@7.28.5) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.28.5) + '@babel/plugin-transform-private-methods': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-private-property-in-object': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-regenerator': 7.28.4(@babel/core@7.28.5) + '@babel/plugin-transform-regexp-modifiers': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-spread': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-property-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.28.5) + '@babel/plugin-transform-unicode-sets-regex': 7.27.1(@babel/core@7.28.5) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.28.5) + babel-plugin-polyfill-corejs2: 0.4.14(@babel/core@7.28.5) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.28.5) + babel-plugin-polyfill-regenerator: 0.6.5(@babel/core@7.28.5) + core-js-compat: 3.47.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.5)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.28.5)': dependencies: '@babel/core': 7.28.5 '@babel/helper-plugin-utils': 7.27.1 + '@babel/types': 7.28.5 + esutils: 2.0.3 '@babel/runtime@7.28.4': {} @@ -1822,6 +3604,21 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -1834,6 +3631,11 @@ snapshots: '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/sourcemap-codec@1.5.5': {} '@jridgewell/trace-mapping@0.3.31': @@ -1934,6 +3736,56 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.53': {} + '@rollup/plugin-babel@5.3.1(@babel/core@7.28.5)(@types/babel__core@7.20.5)(rollup@2.79.2)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 + optionalDependencies: + '@types/babel__core': 7.20.5 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-node-resolve@15.3.1(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@2.79.2) + '@types/resolve': 1.20.2 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.11 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + + '@rollup/plugin-terser@0.4.4(rollup@2.79.2)': + dependencies: + serialize-javascript: 6.0.2 + smob: 1.5.0 + terser: 5.44.1 + optionalDependencies: + rollup: 2.79.2 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + + '@rollup/pluginutils@5.3.0(rollup@2.79.2)': + dependencies: + '@types/estree': 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.3 + optionalDependencies: + rollup: 2.79.2 + '@rollup/rollup-android-arm-eabi@4.53.3': optional: true @@ -2000,6 +3852,13 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.53.3': optional: true + '@surma/rollup-plugin-off-main-thread@2.2.3': + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.12 + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.5 @@ -2021,6 +3880,8 @@ snapshots: dependencies: '@babel/types': 7.28.5 + '@types/estree@0.0.39': {} + '@types/estree@1.0.8': {} '@types/json-schema@7.0.15': {} @@ -2045,6 +3906,10 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/resolve@1.20.2': {} + + '@types/trusted-types@2.0.7': {} + '@typescript-eslint/eslint-plugin@8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -2137,7 +4002,7 @@ snapshots: '@typescript-eslint/types': 8.48.1 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@5.1.2(vite@7.2.7(@types/node@24.10.1))': + '@vitejs/plugin-react@5.1.2(vite@7.2.7(@types/node@24.10.1)(terser@5.44.1))': dependencies: '@babel/core': 7.28.5 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.5) @@ -2145,7 +4010,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.53 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.2.7(@types/node@24.10.1) + vite: 7.2.7(@types/node@24.10.1)(terser@5.44.1) transitivePeerDependencies: - supports-color @@ -2162,14 +4027,52 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.3: {} + argparse@2.0.1: {} + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + async-function@1.0.0: {} + + async@3.2.6: {} + asynckit@0.4.0: {} + at-least-node@1.0.0: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + axios@1.13.2: dependencies: follow-redirects: 1.15.11 @@ -2184,6 +4087,30 @@ snapshots: cosmiconfig: 7.1.0 resolve: 1.22.11 + babel-plugin-polyfill-corejs2@0.4.14(@babel/core@7.28.5): + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + core-js-compat: 3.47.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.5(@babel/core@7.28.5): + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-define-polyfill-provider': 0.6.5(@babel/core@7.28.5) + transitivePeerDependencies: + - supports-color + balanced-match@1.0.2: {} baseline-browser-mapping@2.9.5: {} @@ -2205,11 +4132,25 @@ snapshots: node-releases: 2.0.27 update-browserslist-db: 1.2.2(browserslist@4.28.1) + buffer-from@1.1.2: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + callsites@3.1.0: {} caniuse-lite@1.0.30001759: {} @@ -2233,12 +4174,20 @@ snapshots: dependencies: delayed-stream: 1.0.0 + commander@2.20.3: {} + + common-tags@1.8.2: {} + concat-map@0.0.1: {} convert-source-map@1.9.0: {} convert-source-map@2.0.0: {} + core-js-compat@3.47.0: + dependencies: + browserslist: 4.28.1 + cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.2 @@ -2253,14 +4202,48 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-random-string@2.0.0: {} + csstype@3.2.3: {} + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + debug@4.4.3: dependencies: ms: 2.1.3 deep-is@0.1.4: {} + deepmerge@4.3.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + delayed-stream@1.0.0: {} dom-helpers@5.2.1: @@ -2274,12 +4257,79 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + electron-to-chromium@1.5.266: {} + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 + 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 + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -2295,6 +4345,12 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -2407,6 +4463,10 @@ snapshots: estraverse@5.3.0: {} + estree-walker@1.0.1: {} + + estree-walker@2.0.2: {} + esutils@2.0.3: {} fast-deep-equal@3.1.3: {} @@ -2415,6 +4475,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-uri@3.1.0: {} + fdir@6.5.0(picomatch@4.0.3): optionalDependencies: picomatch: 4.0.3 @@ -2423,6 +4485,10 @@ snapshots: dependencies: flat-cache: 4.0.1 + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + find-root@1.1.0: {} find-up@5.0.0: @@ -2439,6 +4505,15 @@ snapshots: follow-redirects@1.15.11: {} + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -2447,11 +4522,31 @@ snapshots: hasown: 2.0.2 mime-types: 2.1.35 + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + fsevents@2.3.3: optional: true function-bind@1.1.2: {} + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} get-intrinsic@1.3.0: @@ -2467,29 +4562,63 @@ snapshots: hasown: 2.0.2 math-intrinsics: 1.1.0 + get-own-enumerable-property-symbols@3.0.2: {} + get-proto@1.0.1: dependencies: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.1 + minimatch: 10.1.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.1 + globals@14.0.0: {} globals@16.5.0: {} + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + goober@2.1.18(csstype@3.2.3): dependencies: csstype: 3.2.3 gopd@1.2.0: {} + graceful-fs@4.2.11: {} + graphemer@1.4.0: {} + has-bigints@1.1.0: {} + has-flag@4.0.0: {} + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + has-symbols@1.1.0: {} has-tostringtag@1.0.2: @@ -2500,40 +4629,166 @@ snapshots: dependencies: function-bind: 1.1.2 - hermes-estree@0.25.1: {} + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + idb@7.1.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-module@1.0.0: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-obj@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-regexp@1.0.0: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@2.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 - hermes-parser@0.25.1: + is-symbol@1.1.1: dependencies: - hermes-estree: 0.25.1 + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 - hoist-non-react-statics@3.3.2: + is-typed-array@1.1.15: dependencies: - react-is: 16.13.1 + which-typed-array: 1.1.19 - ignore@5.3.2: {} + is-weakmap@2.0.2: {} - ignore@7.0.5: {} + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 - import-fresh@3.3.1: + is-weakset@2.0.4: dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 - imurmurhash@0.1.4: {} + isarray@2.0.5: {} - is-arrayish@0.2.1: {} + isexe@2.0.0: {} - is-core-module@2.16.1: + jackspeak@4.1.1: dependencies: - hasown: 2.0.2 + '@isaacs/cliui': 8.0.2 - is-extglob@2.1.1: {} - - is-glob@4.0.3: + jake@10.9.4: dependencies: - is-extglob: 2.1.1 - - isexe@2.0.0: {} + async: 3.2.6 + filelist: 1.0.4 + picocolors: 1.1.1 js-tokens@4.0.0: {} @@ -2549,16 +4804,30 @@ snapshots: json-schema-traverse@0.4.1: {} + json-schema-traverse@1.0.0: {} + + json-schema@0.4.0: {} + json-stable-stringify-without-jsonify@1.0.1: {} json5@2.2.3: {} + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonpointer@5.0.1: {} + keycloak-js@26.2.1: {} keyv@4.5.4: dependencies: json-buffer: 3.0.1 + leven@3.1.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -2570,16 +4839,28 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash.debounce@4.0.8: {} + lodash.merge@4.6.2: {} + lodash.sortby@4.7.0: {} + + lodash@4.17.21: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 + lru-cache@11.2.4: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + math-intrinsics@1.1.0: {} mime-db@1.52.0: {} @@ -2588,14 +4869,24 @@ snapshots: dependencies: mime-db: 1.52.0 + minimatch@10.1.1: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.2 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 + minipass@7.1.2: {} + ms@2.1.3: {} nanoid@3.3.11: {} @@ -2615,6 +4906,19 @@ snapshots: object-assign@4.1.1: {} + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -2624,6 +4928,12 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 @@ -2632,6 +4942,8 @@ snapshots: dependencies: p-limit: 3.1.0 + package-json-from-dist@1.0.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -2649,12 +4961,21 @@ snapshots: path-parse@1.0.7: {} + path-scurry@2.0.1: + dependencies: + lru-cache: 11.2.4 + minipass: 7.1.2 + path-type@4.0.0: {} picocolors@1.1.1: {} + picomatch@2.3.1: {} + picomatch@4.0.3: {} + possible-typed-array-names@1.1.0: {} + postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -2663,6 +4984,10 @@ snapshots: prelude-ls@1.2.1: {} + pretty-bytes@5.6.0: {} + + pretty-bytes@6.1.1: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -2673,6 +4998,10 @@ snapshots: punycode@2.3.1: {} + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + react-dom@19.2.1(react@19.2.1): dependencies: react: 19.2.1 @@ -2707,6 +5036,49 @@ snapshots: react@19.2.1: {} + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + 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 + + 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 + + regjsgen@0.8.0: {} + + regjsparser@0.13.0: + dependencies: + jsesc: 3.1.0 + + require-from-string@2.0.2: {} + resolve-from@4.0.0: {} resolve@1.22.11: @@ -2715,6 +5087,10 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 + rollup@2.79.2: + optionalDependencies: + fsevents: 2.3.3 + rollup@4.53.3: dependencies: '@types/estree': 1.0.8 @@ -2743,22 +5119,186 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.53.3 fsevents: 2.3.3 + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + scheduler@0.27.0: {} semver@6.3.1: {} semver@7.7.3: {} + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + 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.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + 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 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@4.1.0: {} + + smob@1.5.0: {} + source-map-js@1.2.1: {} + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + source-map@0.5.7: {} + source-map@0.6.1: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.2 + + string.prototype.matchall@4.0.12: + 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-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.1 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + stringify-object@3.3.0: + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.2: + dependencies: + ansi-regex: 6.2.2 + + strip-comments@2.0.1: {} + strip-json-comments@3.1.1: {} stylis@4.2.0: {} @@ -2769,11 +5309,31 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + temp-dir@2.0.0: {} + + tempy@0.6.0: + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + terser@5.44.1: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.15.0 + commander: 2.20.3 + source-map-support: 0.5.21 + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + ts-api-utils@2.1.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -2782,6 +5342,41 @@ snapshots: dependencies: prelude-ls: 1.2.1 + type-fest@0.16.0: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + typescript-eslint@8.48.1(eslint@9.39.1)(typescript@5.9.3): dependencies: '@typescript-eslint/eslint-plugin': 8.48.1(@typescript-eslint/parser@8.48.1(eslint@9.39.1)(typescript@5.9.3))(eslint@9.39.1)(typescript@5.9.3) @@ -2795,8 +5390,34 @@ snapshots: typescript@5.9.3: {} + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + undici-types@7.16.0: {} + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + + universalify@2.0.1: {} + + upath@1.2.0: {} + update-browserslist-db@1.2.2(browserslist@4.28.1): dependencies: browserslist: 4.28.1 @@ -2807,7 +5428,18 @@ snapshots: dependencies: punycode: 2.3.1 - vite@7.2.7(@types/node@24.10.1): + vite-plugin-pwa@1.2.0(vite@7.2.7(@types/node@24.10.1)(terser@5.44.1))(workbox-build@7.4.0(@types/babel__core@7.20.5))(workbox-window@7.4.0): + dependencies: + debug: 4.4.3 + pretty-bytes: 6.1.1 + tinyglobby: 0.2.15 + vite: 7.2.7(@types/node@24.10.1)(terser@5.44.1) + workbox-build: 7.4.0(@types/babel__core@7.20.5) + workbox-window: 7.4.0 + transitivePeerDependencies: + - supports-color + + vite@7.2.7(@types/node@24.10.1)(terser@5.44.1): dependencies: esbuild: 0.25.12 fdir: 6.5.0(picomatch@4.0.3) @@ -2818,6 +5450,56 @@ snapshots: optionalDependencies: '@types/node': 24.10.1 fsevents: 2.3.3 + terser: 5.44.1 + + webidl-conversions@4.0.2: {} + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.19 + + 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.4 + + which-typed-array@1.1.19: + 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 which@2.0.2: dependencies: @@ -2825,6 +5507,131 @@ snapshots: word-wrap@1.2.5: {} + workbox-background-sync@7.4.0: + dependencies: + idb: 7.1.1 + workbox-core: 7.4.0 + + workbox-broadcast-update@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-build@7.4.0(@types/babel__core@7.20.5): + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.28.5 + '@babel/preset-env': 7.28.5(@babel/core@7.28.5) + '@babel/runtime': 7.28.4 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.28.5)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 15.3.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@rollup/plugin-terser': 0.4.4(rollup@2.79.2) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.17.1 + common-tags: 1.8.2 + fast-json-stable-stringify: 2.1.0 + fs-extra: 9.1.0 + glob: 11.1.0 + lodash: 4.17.21 + pretty-bytes: 5.6.0 + rollup: 2.79.2 + source-map: 0.8.0-beta.0 + stringify-object: 3.3.0 + strip-comments: 2.0.1 + tempy: 0.6.0 + upath: 1.2.0 + workbox-background-sync: 7.4.0 + workbox-broadcast-update: 7.4.0 + workbox-cacheable-response: 7.4.0 + workbox-core: 7.4.0 + workbox-expiration: 7.4.0 + workbox-google-analytics: 7.4.0 + workbox-navigation-preload: 7.4.0 + workbox-precaching: 7.4.0 + workbox-range-requests: 7.4.0 + workbox-recipes: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + workbox-streams: 7.4.0 + workbox-sw: 7.4.0 + workbox-window: 7.4.0 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-cacheable-response@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-core@7.4.0: {} + + workbox-expiration@7.4.0: + dependencies: + idb: 7.1.1 + workbox-core: 7.4.0 + + workbox-google-analytics@7.4.0: + dependencies: + workbox-background-sync: 7.4.0 + workbox-core: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + + workbox-navigation-preload@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-precaching@7.4.0: + dependencies: + workbox-core: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + + workbox-range-requests@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-recipes@7.4.0: + dependencies: + workbox-cacheable-response: 7.4.0 + workbox-core: 7.4.0 + workbox-expiration: 7.4.0 + workbox-precaching: 7.4.0 + workbox-routing: 7.4.0 + workbox-strategies: 7.4.0 + + workbox-routing@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-strategies@7.4.0: + dependencies: + workbox-core: 7.4.0 + + workbox-streams@7.4.0: + dependencies: + workbox-core: 7.4.0 + workbox-routing: 7.4.0 + + workbox-sw@7.4.0: {} + + workbox-window@7.4.0: + dependencies: + '@types/trusted-types': 2.0.7 + workbox-core: 7.4.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.2 + yallist@3.1.1: {} yaml@1.10.2: {} diff --git a/wiarygodnik_frontend/public/apple-touch-icon.png b/wiarygodnik_frontend/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..08cead1223d6842d0d272813b38e0374e6896672 GIT binary patch literal 6431 zcmZ{JXEbuCAyB4!7 zNEIDtoK89MDOmVF;>F;D8Lc@Y>7SG0gC9Sk`}qh99c83t5eGna!}27b0GvyF?bF+P*< zJ(An`GgcEC+Ss>kuK9?O1WnET78d!pE3DPq(aD8b7b5h;Zvfx#;vju{+x9B~JucdN zF9_SyPCG($+0W#!ljjav2cLx5Li|19`aW>!(e+*ER5*vg3fA(Q9eAB5N#@0TJgdyu z!X!w-YzeDXBVDk@dX1^3zC7RX_qZ1HeEyvOygYp!pt@fpcjZN}b8)z6F>jFcI<1_Kz9H` zslyR$iZOH{1i6y_Sn!O7r^X4tqneVN!dd}dn`v%;j_2S_hZ!@XY;1(CFk1YZoS*#ymzzzzDP^3pT<#KZf4_ao1b5!$~M(%0?r-( ztl=HYFSWAD;}{$F&3Fvf>GKC~H^szTeFX{=?{qjwAcFpREC$0#8E;6fd&{Qw&1a6R z4X@P`?7Ur%NmiEzAMY*9Bo&rFSz8K(Xpjnq4+nyiV2!o4VZC^|BfoOOHu_>|6EsZs zqT)Xa2m2>~V*o9OyV`0*&a(!0dw1o^lf>Sy*Vy~a3FFyIo-s>&weVR-5?z5%#t~Ni zp?TD6sF{vTQ3b`%AHFHZdW`vBEc);49QG@w>LlBfpz$t_qQ(o=hb~01TJn9ho3Hk5 z=2|yjbep{?-qzGO;gHr)d9@n8sI5r<4%HYLA&`+;?a=V=p%>tN4BNiC(t z(6n=%7oE;KO4!lZ5*|ufN#%l%`z@HDi+AvaJ7osJY+-tyT8Gdz-#C4Yc2cOEBmWc zUq#pjI`Dnm`k4}05tps8kt5{`j3R==%m!tXe%E_lbh5uNtYe>ef12h=!VG*^zT+5V z&>8p!Gi`x}?LOv;+~i?5&1W9eN;3CBmus%TW4)`S%pG)sS$}{D7dD2jS1G9coJHdD- zEr4tTw9nDdowoV>r-~-_B1!FdtrchY%(3oUf!-5iY;?z?fbN}-dBdYW5P8!_+38!S zkIl)`kp;)ImR=q%$2fO20&Bw_f$83;j+*2@=+q!BEOnao)C1 zXBwH;uHl(HY^UdiJ^gAfa<}9d<}K89C#caXl&r-?JknM zyrp`TjH(9l&P|m+a_TbE7;;%RMtX4!XMs}x=K;XLO7y2RJ@SIRuxB;FjfPy&f2I7K zWSFf~{~_c->eYsy_nubHNNC|S#}>>U9xbmAIGiYz()i4x+~GG+vekF>#roS&rAv%K zz}0*BgStGNQS^gN>}+SVpN(JAgg)m8Q$u$?Awobop%6@@RPXO&-bSpmkY1>k{K4dt zF~C)$U>xM(=QQHxXVr0f>#*_mBa@8b-kBFy@oPk(wOf<@ma5vwUVei-saawczgB<; zmU`>ETvI8{+6Cm=cbmMPe!{s z^M!6NyIO2DziVL|?m`6?jh0)}LGQ34)?qo~Vua$pXWw#+)-O!RM6wQ-lZ{%!<2=G+ ze2&xv3lql3_AiJZ6$%Poj+KaD$FIX|mo9h3v`KyuM3WS#v`)CJZ{l7aXU2bhd@#cp z6^Wx8!S_rkR^fp-Z+k`}e;ZJFDf1;w&70qebmA$U><9XN*<4c5*kVFzsOB6m(kr69 zu92;}a#}71>)M;5Ed2*r**`|EwAtwi<;%`XFV{yx#q}$%CTm@lyy5+=hv*ySa2&E2 ztX9JbrJ6J(9Kit{A(OHZ=WQ$cSCiuXtRGjyGfN_rd{xHt!ve!Whl)BD8kr;5J0pRR z7}Us%@1qm+qB@vuiJsU=(T~`*NwY=CwXlO%a@fG3Q>Vv>un4J!z1Gd4hwxKiv{9)N zJ@uX3FSbx0sexQGBM*-g_73E^`-6s+ZdWIeOq%CI)cJ#-QKO5i$kXoLN|1k4as2$g z%nPdV@k_xG`Rd^qEOD2=q;Fz>fYFKM55jfJr{-c0IM5u3{$GKlp0Hp7qTwdeFv)a4s=Y1CWnD#MW&%igzo4)3Rjuub? z07+QRB>9>w9B=HBrC?CT8hD05KAD6@Mvn+E?S5_zeQ{P6ziZq$ORq<_sDtx_C}AND zf!GLrfUpyaWP~OR2Tivb|NVX%jD>z#DL4ct)!fCU0q1g-njWhDOa&!;gP~?k;?@c| zGA5)dUsax1bchoP6mocWnghLpdVKI%2UD<=CA2F~xCnR73yu^`ZGsqjM|j!bB$cN% zBILZowA9=Qa$;O(ksdWrtQ74UTnH7KvOgYorRr=-PO81Nr*O!CXxEn~X=q%ng&&M} zb<;Devn{XrmuapckoEP+5SRS*xlKM5j&S4S913Q|LzU?O>d6>TH(i@QZ@a<1$zD1Y z?v6=;;BIDt92YPBKfYYdPPRN#Zh%5xGp{#&=`j5ua2Y_y9IfLa?6vjNb#=N*J* ztUxSb^+)l$eZKCY33$LLqiFy4S@(m;iBdc?UH&?ZMfi^{9ff4VJXGv(z65U!u;EmY zVed4PQg8}UoUOGIy;XDZwGUveyYKVl6je?o4)8oHv(aNhU)lKt_9!{xucZo>z`%3A57OSXP|~T<6o8?nR6ppFKX!#eDJ| z1G{8LGN6@{ac`$#)Ia=hf%i+Q2e`q(lwV`xVxn?IxK_;d$~4smOL6VFro>n!{Q&UH z3D)qh9*KqLmJ*~vPpzLGkihQxE8%*NgvDtBp;pz-G=xmAvB!n#-YF3E4H;G7!B@1( zv?CK=>P@SZVa;dj-TsTpTi0F=H|N0`$&VPLsR?)XA5d8ug{FX9r}S`yt28b`C=j|m zK`^a*{o#3Evg;6$G=Gb89vGej&rs}^zu}JHr%6vfc1XNpDvLkn(2n=TOOxbEoHMXe zk?eU+k!sG1wA>AHgYI-gT_`=ao3%$-rqwWbf;m{2lR1Wl_ve9Uw9=~r^543)VjToX z5BG3?Pg{QN8x-8Qpt;4{+Lv~dDHbrF*U22zW%=}PxS>4sIGVMclyOFV=pmmsZS=s8 zncy8ZdMEcCB%P|QzHU5;Q+qHXw)|;z!E#Xj%iZAS^eK+#_k}}U(GEg8u|w(%3V3of zkA$5>)I-dq1J39&8r&Z7khxHmK?(&A=E%7nxP2~{rRUu3 z2`Ta)19xq$$uVq$Z3t*YR;80Ke#_L9(=zsEdGX}!BUe#u;5#aGGoVcs*Hb@=Xgig* zQnB2pVE=%5smdlhUMAezDOEM+p(o9zNQ3r2Ou7z3sWJ^}acZ|6G_m-{(xL4D*1wsi zmolQFh{D6}Zq#x_@7Xr^kcfv%*mD4!cy%IammApO2qZ`2Lp#Xkxr=|W14j3?C`f=A^N0XGf-GP|0i#AB5GYT~zBW&;@5w>ICfAMo!^-#I4(C~OqR zyIMn?^}eV06eydgN4&Q6S&=(l)^LB&w8f}F)IpJO^Y8HltB1$ufoUrRoD3{salg@n z>OA7XsBPJ_9+{AJD!+?i4@1W4j<@u-zp{Q#8r1MFbUlHq&LrR#hMOJ&M}Q2)Ew)o^ zHBIG1&LfZsK?}&)Oqq+~-gGH(eUWz9-c-4Jz13(tU0Rp9fM~FiUV$n&KVP)Mn4m%C zR@685R~m>m46x`^7WSAauocmAx^}ud@sLD%*oej&OWa-Z)n(fvfXq zjs%|pd}_dn1>H>1Aae~6xoz%oq`@KX8<0DAakKhezP!%3sjvyJVpHzopo8bZN|vn)iKtUi6;BP> zQz?WK_;+w+1YR(11nx!BF>x{oJD7z;b+B|e-)C=?fc#mH%1W=`W@^jF-A@m*CuS9| zgzoh}Pe>vD#?@hXX-M#+Cr}kKA@C#(o$OKP#yVwswDT-Nn#WkO8vVw&Ly=if;(Hv- z0+78jiXrjl2Rm+aYw42N!6)k+bfOl72Qmq~s?O}S{VUas$vh}kiM9ZsG>ai4Jtpqh zj|Rc=a=2iO&awHlpn1R^fI&N+%{w{Jk2w}#pP9&q(AQ43ZuuhC#MuNr>K|Ord*dr$NZva+@aE2 zL+Le+=kbZw=P#}GVIlrsq}je}2j5)DPdxv;soI9zHDtV8-^M4kz(^Lj6&7hN*< z>#_*v^WEQ9axr{`kWzu&n~&O8({gW#cfx7tyO!S>kLu+zmm`xpUK}a8YnSVfYvgYPeyB2GZ% z3H1h!y)b3|<2xRu)@zuzIh92estsG|$ofwo$iL^&+Z zn_PpO9iSt-k91NwnbMV96tL;}n08C)ei93H$*3GZTPOpSBoT&@c$Jcgj9eP_FJVRbwsSK9P%V!1NFs0vU2 ztKDI`i;JVN73CAlVQf!m>vanN`8g$4S!XD9b8HClN;$`Hy3WKmuZ2~ALni{sfuRVoio^9)=VjhU? zHh3&7xGn+vArc;ar;C<&l!ZcUfT#^EM9d=Qtn(I=N2%6Rf z?Z;rx2-p_2O_4L6F{CYn)}%EEN3y;36jB_+0<_m(tQdVlXBk5P6i(kq3Ne6u*r0Q* z@RX(XAS^VE8CEByALC7w=dyNNt9SVRjO(B561jP71hq#6$JA#AdfecE^Gy*PsQn&V zh4p`fNii{wp;(`mA8B%O%hdBwV;~}A8P&{%#9$+mPb(tN*F&!DwZvy8d8NEIC}55J zf4(v;FL$z37}EDT<7+IHS*^rnN^?*VfVtQ7iFY@bl5pERKrW+vkF%S~u@U}(dJ)%t z(HWLF&ntcuC}JkhdYM~}uIf1dnfWwJ)y*yd63EboV-LqhG&HgijudwWV>qq{xxpbk zqcJMFpr9s21z@CJp7-ayCCxA{Mm%bUpZ4F~peG06nbItnApQMxl*Q`=eKJ~4Prn_{ zR74Ew+WmoW8pi{WP})6p*||C!b2HSds-&Z%OD-lUpYU?6(x2Ff!T_y)kHZd(6quUS zYzQkgrgJRA!GzcI@|`)!!RMJzN#s@PL3h@pS7a=mXv zRP`Ik``%aGd~`7qc@XmllYsTN!7nQHO4$lHINY+KPM4$q34B%JhF=N5^?pOJcIJh^ z9s^xYw}y&WDSN>um`IFl{zta>&9GGQOH?Ty`F-KgZNiMH^4sY7=7IL}LNYbCdaUE3 zlg~!Z6tK4o8w||apC)gsa2zqEpcgLrPU2AUv_vO{bDXB$|d zK+|;FF?cbB)&5-;S@86+DW7a9T`jvkq!SSoX!Z3vEtxo6lx?!!kQlsWG|Q zHnMv0pPb5_GWy##ZoH5T8_~j>>`twj&4iOJ5#TO_ZgT=;i3g`-cHUzCGPQg8$ydvi z$F^;Mo^bSP;2``f5~z2&X*}MoMBw%HarS)F(UH`Tt8M=E){IT} z#k^!7ix{X>HRK7P@}n`l-0LW7cXf}AFVqdHCk$PrD*u@DzYg4!*C(#lB1-G3PHSi_ zU0kZzv@kjUQHgr{l5_c)(+Y6s#<0ec1oLjV0rmC(qp%h!)H5IaA({Uy87gDIFQpEc zpKaEiY{h^{FgNY>RowG}%eCOhKvqI9ck3p~fJGq@OKzAQXR+P?@w}fG&6p1=IzoWw z2cT$8UIuTaD*M3}eL~4;VR>fYwmINFMMQ08KlPp$7t)KV1~~c|#^q(;VR)ry1Dy&n zrc6-2W+M>g$U+8tJ2GYY1cWIPR7R!t(Utjw0Y)H$*s#ezFaVOll*X!L8wmV=9NpuE Y0v)sC{YoV;g%5zLqLxCHoO$^F0pP@IP5=M^ literal 0 HcmV?d00001 diff --git a/wiarygodnik_frontend/public/favicon-96x96.png b/wiarygodnik_frontend/public/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..530243d9fe8b5d0a8cfb95540cffa18e841b0e57 GIT binary patch literal 2431 zcmV-_34r#AP) z5tGb}WoGPI5=m+9@k~8$Z};4L?tSl8?>*1cKi%KizMu0u=iIa0*Px??Z3(DBHU$h+ z0J3TSK4TSty!xvEWY%8=paPIv0h#lcbqr|SxDlkM?Styot8>CHyK{9TSt1Vb<($(b5+yVbKAg zmVWi}DY435A>9F9L*e%AyOQOnYeu31*tl*5I62zuT1L+C-@SVWUAp$-98Zo2q5;Ud zavBT_4CJU&S)QFN?PSfLBy&*!T+7TL$-B%Z`$i57_WO)APFU!42pHkV39O5|Cp>!m zgf(rs3SjPewB>ws#9L^XCgr5CA9Blc7eA*txTxM*nG){GcHsiBWA zHM6;ipV?%bI0OwE)K@$Nod7VkeiHGKI);Wd;L3#)oB^N+H>j!XAcmQ1Hy0Q_%$N9$_ul;n(7T@xt2fAv_UvXKwKa#txF}Y`wd=P4`lAcD#*(lv8A8LtS<@ENfER#0(Gk$8)5nsws!;*{ z5H>4>Q43s)7Q`u0ns^x&xlx{z8?lLOLXS3v>|Lv^Ig{q&<>07*Y`g1%O_- z(2JMYfvH9Nj~EA6v#wVt0xpidQ$KkA{Ds&>#-`61K&@IvaPe%qtgWdoHK?AW23K65 z^8y@zh#k?ec*)Aj1Hj6%3qR13D0(9bUhF z4c%?sDi45&ZR^3NhjoPllPo(3T}xc6zIX3F^zJ{XTz1o@20`E#V`cSRy39FuLAXli zK79&~E(3(tm@&Om$5NnS!w-l=wYTdDTQ{vDvX!zDf&sWsy$rcyUWUY~5ZZCh!fbzP zcZa5?t>Hl8?kWs`TBUSnS)~*M1kNM10hpUp=aS;-&m~DYc4=$C*#mH=9iBaV4!xZF zi=i=Nnxp_+oE>2Onq`&W1JPv9|w3nMNpFajQYu2pb0Z(#s!O7J_a?dTzkaHJ=_HEJrEnSeKCE40^hwWR}Rw#~k zS#Y437V)H@!WjT66s|J;J%+&DzyFb<+~x9EvuX*ryE>Kq&)UWr-n=O+XM-yogt^h}Py7$+Fhi8&>dlQ)2o z!~I}R*bLfw-@1JVJiNr)m?3SQW~ObZDRT_1xm@op+J)f_fXxfK_Hc&6!tyf_QsIQM zW7@bu7dQ|Exr0ssdma9#GhGlt4Ffe0B?O%Suz7)8<3ZZNcxYkVT#*e! z&@KoiR=ajBxNznuwz5+9wXre3K*vuyV9T>@`%YN8VvQ0S|NAoN>;Wi|T@jnW+S-z_ zQc`qBs3D*R!4#w@2N$}606-a%T*~W1Z4>@WZ5Ik1nAWE>^HQ4lf_Xq`B}vZt3;p(q zrkQBE$rh9-zTf~z2IW$rii?W@Et(Y-6|-qa`y74lplQ<&iQ-yVI{?a0i9xU~NV9Sz zo}ewps4;y#Qq0e~vYc5h4yL6q9mc+Nxe*V-) zoPMYOh?5bu7kr7@6D|#Tc`w1%p%34z1dS&tfYOp5Jg^r`TD26UA~yEDAwNGKo7RN! zqv6ZoNwm+EFhKR!QSOAY2(yHT}*a%4*2?yCWgl}BU3_`B|89OC3zSw zTKFw^4`e>CdMNb>1c%J#k-9KZsx*Kjsfp0MSyNV}YrK*~ zl+z0UT)HA;E9H2gHvqUmD5NgI<3&iY-^csK?Am}{+w(rVm_8yNOKL!`~fx7lO<>Ko-0Hg-f z9b#>@h5r2-6~O-rlN_xqg(2ipg$h8UiIXl}3ppsO05ky9t6LY&o=zj`<8!EQQ2Pk* z4QdsDmfYw*F}hbw5*%FzKyL0+5>u>=3V=o$DZ3&S0H$q91wjRX0noCgF{CDwZDpQ3 zbp|E`1@r2PQ~(UJ#YAm~E}c6P32W!j7hdG$5!q@QsQ_3c6T2%?0T8rVQV7M=#cvCa zzu>0=AOO(S$^s&HY$mYezM-!IAd(f}D0R%S8No3}uFDiE073wyOV=s@4uWzuML$l8 z7VU6>&yQEA9>9@8hxY9tE_P>ySi2%);QK|(Ii@D@6(!E4Q*eZYy}Q7~q!m1)etSTd xF9xd~ATwkYfC@ln1!T@%^#B!s%nHby{eO?GcMeaK$*lkY002ovPDHLkV1f{nV1)nx literal 0 HcmV?d00001 diff --git a/wiarygodnik_frontend/public/favicon.ico b/wiarygodnik_frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..46ffe542ee0353101321ccc491c78b96782b3c55 GIT binary patch literal 15086 zcmeHOYfDr?7@nvf;7`~uK{s_Z@3$;cG%7GcNFp@)kRkLT=qL0O!YB)pZqSzqimpa| zDI&E#6oIT*kQ!#_f(WMD%;tM|c6R36cFs8+-GS|W=e<17Gvgd>&z@y$3){+)Nycr0 z-QCVu4Pz{kSf7_Lmg2DzZbkm=HpVXTf*rhux3FIR5^>$AE!~+ZzKVOW(at~y#`||~ zV|B(?S64y(KQ}HvpZesUJnbS77yT;nan}BGb~YA!zqqiV+WJ^%7w1DY;(Tu6tbJu= zB^KxA#Ab0_sT=VgK@ZKhXyYz<;OvL+|Rs9|GCq>k)50I(GSYA zK*6q#wmfZ=BOArJA#S&Jc4j(f9sPZ$GL4mGIk7O-k(!urD_L0=hDIHSQVqnATc;eqFwmdZF4qJ(@9XI{!Y_jasTr|N@|wg#jXFOFKE%}Vnu;S= zUD+<>b?TK1F@^87-%CAmdFgYi4GI@|)9EzQ_}-_kj5j`);_NKY1*d z<;-PGn3Qut%#m+xZ7uIQz&!eHYJ<=#V-DZAhO#o^y2cvu{~{cp#>aBW);yK5$h+?kUnkUsRk z8%Tbzp*B>0Vr@l3RQhfkUS;s5o+8JU_5$_8r$P{Gj$%hl~8WnxNv39zL+> zUp{+kbnOuh(mj@KhEvMmCGMq>f@z6k?0+4)$1@76F) zU1?Y05`ZeFiedfn!yPmYh5!4vsT{svb934G($Z4F{8N)DTMWDpPy0e*XzthA;oQG- zo6=c3GyTKTNeREa)JHhNQcPHR^mHAy@|eROzdqsNGoQj2L&l_9RZgz;GIzqgeq|6# z@^pFO($(e=*i3Z&CgPo~OJszvZG% om6!Xe20vqU(@Qv668;a(sh4muuJZ|ltlfJQ9fp^9p}(a50-;nA82|tP literal 0 HcmV?d00001 diff --git a/wiarygodnik_frontend/public/favicon.svg b/wiarygodnik_frontend/public/favicon.svg new file mode 100644 index 0000000..e8264a1 --- /dev/null +++ b/wiarygodnik_frontend/public/favicon.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/wiarygodnik_frontend/public/manifest.json b/wiarygodnik_frontend/public/manifest.json index 4d87731..4a5fb01 100644 --- a/wiarygodnik_frontend/public/manifest.json +++ b/wiarygodnik_frontend/public/manifest.json @@ -1,20 +1,33 @@ { "name": "Wiarygodnik", "short_name": "Wiarygodnik", + "description": "Wiarygodnik - sprawdzaj wiarygodność informacji w internecie", "start_url": ".", "display": "standalone", "background_color": "#ffffff", "theme_color": "#000000", "icons": [ { - "src": "/logo_small_192.png", + "src": "/web-app-manifest-192x192.png", "sizes": "192x192", "type": "image/png" }, { - "src": "/logo_small_512.png", + "src": "/web-app-manifest-512x512.png", "sizes": "512x512", "type": "image/png" + }, + { + "src": "/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" } ] } diff --git a/wiarygodnik_frontend/public/robots.txt b/wiarygodnik_frontend/public/robots.txt new file mode 100644 index 0000000..14267e9 --- /dev/null +++ b/wiarygodnik_frontend/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / \ No newline at end of file diff --git a/wiarygodnik_frontend/public/web-app-manifest-192x192.png b/wiarygodnik_frontend/public/web-app-manifest-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..3ebd1c23332343e2f2927b06d650b1b6f20005db GIT binary patch literal 7383 zcmV;|94O<7P)M4?QBlTgAP6dos93PYe3lry z##lfM8pZPMy#L|<2$7e&_wMaG=j3os+?kzy_CD{uyE{9R;fD%NpMVQTz@!Ld-~=$~ z%=2Me5a0yh4}z%?-~=%B^z*@U0`OpZ@H>FEK>Cz=3C;9)` zvt@%US+c-iiHY#nUy1Pe(POxI>o(lHc?&N8a@F$x5)xj)+qZ8`{b1>3@SFf-rd;be zgHPWcP`Gd*$elYEAPJ<(>(_4}E-oITPo9RwOIO147jaTea(x*PFeL%%)UE-|yc&ah z16RnDDU%Gae%|E0dkT|%*ril<((RU>o;yfi&mZF?#9&ibx(jIMG8Z}`V~-={57I{`t%9r zFI)zz*9I7Ic&d*{w*uXSV5LKNF-66+k^JNe)7Oy zyLN+VA9ya&q;W&bxrBX%a!hR}8^c|q#!cJ6-Fx?Cv2S#vnkT@XotxpiZ%Z?s2aLlx z7kd%<_V**75J^mJTQla~us%7V9tL^y%E++vEsG23frVT%n@9By(V@b0u zekS-&o@oh1){+z<_YamVnhigE{~Z&zaGTWGwK2TlcMk;PsYwD%nlKt#c{dY02x|>P zLc?L$h;dA8$z|kwLV$pEDki-Zs{)EC3j>H1DYd1*UlYa#IS*q;eG%9 z1GqNuf@ja4OSYwi0o+L%J8B5DZ`Vq4cet>xTBE*XJ7zGTDFWc7mC)dwl5yXo47vStW?7tJr7kCKErKJYzy4}jA# z=S15nSRg<2@7EK&nl=Jka>#`TO^+Wxfm`I_``PmsAm+?@%UcES`{Dta9FmE=4GsqH zfa1l9N-{see>w#1+$+h3(UmnrfWXabpn`Q{YJvbQn>U3ilg0{u@KQI7i;oBA zdY+Pgkwf-xhmv1?DcT2A#Ltf9E7rgzLJC$gcwk@X-LtD`b9lL?Y7JM>`bJk&odCAB zS>fF2ND^BkE)@wb_;A-l%J;s9yBo}#J%#C9 zR3|{l{vh(pTSC;_ym|8ms@HA^xb-JRu3kFDBo|O>A8?JZe!~`+yI`pl_bj@D2lgXx zf-a)%l&e@n(vO7bjy0~RDgiKHZ0n}gq9DSDzDjjh$qzq^#dmrGKwn3V@rQ$95$QFx z`tP%5OtQoliILlP?t-URTQRDJ)=`xJr=!CmXO0}A0B+c*B|LceNR)0$rNV^@!jbTO zlI;jFfc~~<)zNb4U95zX-Jvf_6c?r5q**)o{q`MEx<*w}jR2UHZT{S8qHy&cI0BAD z9v7vXS_w15UAYj=#Fh{v7?0G?cNj#SI4Pw0zuMq|*~N3m$z6oZ)cSAVzJp3tovHPV zte^@3@Ji#^Q->iNNi<6<7cO3gA4w7^mh$W6(=5#ivW52zhL4&csBP*-7#)jIvSOqU ziGYndaY~G;A$3$CKo!SIuyNgTYC!Q@x}swpYQ6Ln8o1Sih4ZGT*NpkU?pMUuPNRld;0VlwVn|b6emE1@?}Y^%UWtIZ;<@^&Aor5 z)}v8aG=B!T)pwy$Vbb#J!2CWD7ZwC*uXh2_R;{dHT#b=-$&;%=64l2Ww{JAX~P$ZQ8R(7t#Ci z)*KS^eV!+GZiqe}N$3#+3Qa!h(@Z`^@ z)Ouw>K=E5aLt1`iG+%nAD5M@H^72L^xM%webPfa#ohq+<;%gg zEp!oydOf+Uj#4`^(`w%1VNjSBArCNejS1w-wwQJEWY%w_RI;l}+R#Aiim_YWz*<(}~ zKP5-@bq#W4zhm2aC@Zo$Wzfz&Fu{L@AnfY9I>X`xvjnwGZe;dM(~1zlrEYClws;QJ z#BAKO4Q9+*K&7MQ##qmw0J(5aE4U!8RJE?)dk?g4TC=YM6d}M+KVRt4ts~XkSFYv) zfB&uT&!3b7#;|LQff7@Ne)hb@ux`Du=ucV#U@`&w%C)KH#z>77A%K{J8Y3>w?Cr@; z*e1H2u;hnLC?0cWO@_uE4XB<`r&?}`gqct|rBGu<2!P-JxDF61xc^aKhD8w@9+)4#WX`BX8lDvdPoXaNr&J*H7HOj|_=K>J#bJaz*54;W?` zkW&r>w?|{o9HTDhdhyZ~=+LQGx|rZP1J@fg(xrQUID0OZM#V5~HA#RKE7!rIC3L@H zdYTcu$buJIXhq0p5T=eobU^vYj>aOiC7f({h4Yg_C z4Su=$pLEAcd*SFPIc)SHhmK|x*$II0F&8Owe&VYhU-?Fsk;4Z=mrm`dhIo}c{H+NI z(vz6z2ur;(p>qGhLvU~GEws6z+R07;F}Ic)G$M<#hsIu%<;s;4PDLG}dYJG+5boHd zC&!NjQ-xsQSwne;n(3J}K0F3{^I3OCSS;rmXUmCyip_tDgM{+*$CY|#Uj6o_) zs?X4fko5(PJ-xJ*od8bNs=&I{OQ`S=GRag1HQLy3Fv;xDoi4M3n|pJ3^!N{}BMJ}Q z4aJHUp&B(O02N%q8;ePSf+-JQo8Z1G=Knu*aF=i}NlUB{kMTR!BqD4N6eYLSXoM4h z1}%!VSO9M4_Kg%8V5xv^hC*+)wzg!;GLj0L!0o%he~R^hx1%K0VPnMODPXwaf) zE9O_uvsqiXefus&FZyjtdrE$rF{!90(4B5u?TBDb+h0G)VxX-374rkc1u}>CV5T zOLuPVdmR&aVd7yLnK@@6Y}mM!M#V5~HAw(DGC*r}#`f>o3Z+YZP34|70^r*O-zqfH zvUO*;cKrs8iecI+LIBKMh8fI+%7+ghp+Y5doJ{%+BxeCVg`Wjnzj2ck*+~0)y%DK* zHkY#A8D^+{^5jpU(_^T1iV$GM(s|%qhwgzk%eEYCfeuU%jERENk|1*bxE$sEW24=^ zqhY8b1nAkl6AT&bL*o~ishrQO8U7^KsC&BjV1h7A6lP6mHykkQ24>$dt0+PM%v*`q zB55T0)EVg2XCRG=uG=0uxSLdlPdj|!)n6nKj+BG7CfT!RBMaaoR5;*GFuW0FR#Aii zV$K4DOt_II4KZr%-5e&4|92kLZ9%(W>a@A(rcQ6))*Hr+rHkudyKWQAnNJt1WhmT# zsNnQTi2>2Rn$ah-ghZsqKVROwB$~4z#Kp(Mqes>Q-%{#^>?76gOVU-l$Lcf*uU;wf z2xzhoMcx27@+p&kf|kwc@=zN6Y9#9?Ld=hhSvDKe!dfu`lqgXQ!h&~F&$-zrNGM=~ z2a!thq;Lm~;PpzpW@%L{FckY6xS6egBQMzL<^W8VFdk1~FqY5PPE^SS+be+*z14Ri? z=DX5lqJ*XRONpbIGnWZ@p72fq-YuXJOgo7OU}hIZ34maWxd&_Zy=rR@Y1Jx~VZ+*G z)X%Y*Le8y$qc{P^|1<*HwP{H`VNIL2gImAfq1H3H!f8@0J141LNhA2#<4~mz`TU_P z&P~&YUfL>7fLu9AI*=1|=|B+7Bywx1qDgNprS&lV*r7Fy9W|8tSvz_9EcEO>fLhOp z3W^f|K@1HhG4LhmV&GA4$@0~(jQqz1AlnyTK+MSq>RmO&jxT=y_XMdzfFdMk&0&(e zMvRyxV?=t`96S&NUwv63y=MRV_cLc>p=%HNyrk3}=|n*l0w6YGG8dp;Lc%Lc2~jgk zI}-CVo-*bq8LzsoP2lOXXJ&@)A7fXI00r`sG~P$((s(C(9v%@1gNBSUqQIRvc_wTRqPzMhsv`|4+1O-(GbfJ#{-u>q zpFUaMoS0vf%l{Bil>phZk@)q~bn)vcC$DXX?r`OoUrjTgxaiGcCp_zON?`UM2!)Yj zCYlB-p#xQw0O+Jo|6btJw}()F|IrSA)x27?H^uqDuAl(;zRb6xaQgf2x8&59zATfd z&UB`vIsp(bDZgx}-?TZB;I_`77v^rpj2Qvr{Ap9Cq_oZh3e(0~69m9CewfZrtl*mf zGbP-(X}pT(k)+;NK@s(Zld+6Bdmg&=pu3MPb{_PorwIZeaDxW)g+9HyO2QB;s$*q! zBZw`js)=dNY0@U99`~C!Z%9Fn27tAIxqKc0%@6?HqfP4ixgmvwhQqKC<8(dW-;^!| zdv|RXRa86Wz|DH4lxFfZMSv`%p4d6ED};ZgNPPTDsPEnkFy)8dlHHy> zbvA4bq`!eDxnrFf&=dg>yJDnhL^x&9h_o=Dzi=6>T0>WxK&|=1@DNODMU&P%Eng3X zABDj~N2@gyUG=Lu0w8)W&b46KlDSNPeEaq-H23ZZckkV2Vvn^EES&8>VHC7zMwc)k zEkEwvdjK9yq`yH}k5jAmG)VvitC?40m_B7ZGu*J?hIiY}fP3Ov5#Rp3$-=*jsEE$b zjUg^B-jYfNcg45}LqM|xK==Fi=>fhzy@ZWKV5{q-7{pH#rvcX7RYP!nGk}b#d)JQC zg|e;ro0#|-YC5}H?oDtJj)0~KfWz?V*VFPJYx(%`6HJ*l8$v=ONQ7wuYxDoGhlg31 zuxi<&Ig$>v(sB|bWNW*4knPS7vW~-u#x+j>1ig7PPnb4YzOBs{adB|$STxL>y^v{^ zw5Fc!guK0=c=4i4f9+E~h|iuq2N#ks7fUB`p+`U$1i)dr)^mm>3$0g2q#yq0HE1oAO7b4Q zkg>#GxCEWL_T}IFLcmI+jcy2l{^K=Dtf(UOoInCzno&I%b{K{ZAFCOE^y-MN2!J5l z*w|PugyhL1yyA>rCnqhx`}z!l<54G#HY`=fqdNj5qcqgd2YPffS7}e&=JfPx1Mx5A zU9_w6B&yV@ZV7;R6)IQ&f=Q@wwrpRh1fO!s^(6ryWCqOc~xpL)%mCNQsg$m^~4Y*L}@HBTkIk4Ng zd%sW>-cAGph9N-m*o%=mTU!EFLxKGHM8KiG3dZhl+rAs7&7hBk%9t?&RIB0$OBT-| ziL?HhEO#4;44uDdIlmO2YKjdAQ>*qqvJ=ar+77KBoBfTt^Pp@RL>ViY)^Q9(t z-M$?ujyFblal8u`ufUI;*~VB&gh4fR!xJDSvQ-=_!BkSK3_}xe@vN34CME(NWKHm& zF8LH!Y}D+^H5*{T!sTi~pqYM6MSx_~@h}auEDZDWrLJHvcIMu_dk0vODDv0|ctQ5_ zS;^H)r$m$a$IiXs!o|z1T+yW+QxYKcOkqq&@Y)mdS%a}e z=VLEH)QMB@;Nc@#9*&LcmIJ=k#7Yuba66Ec^Jcz3zzHDW=_y*Y2$U{W(vp=eM-Ds4 zN-{PizD|UMm#+Y;*Zg+tHsCM3l7gRbmt#*zzD)D@k0;>f-rTe#-~>?esb$y~rb~%B z8p6b)p6*UF8E^_CoB*s5RmdJLD>4pMn2suzY$Hw$-L}3z#@=B=cVDlUN+~rqwqq%O*sMdJ9ie(rKXloYxuDjE*UG`tEZAq>qv2Thy#x z4OXvQ#N1Dxfy3cwWE69|S~AE9przT6;LC=!%PpZCtffx9#_;_43)W^eV~-O+GgBem zk?7;0kS90WY#A?J#98u<8dW#}3^cQtr0W$QH@yQ1klJtuykYF<~3k1Lvnyx&K?jK&+aY*%Q1_!#R(u5 zIgRUGID5^h=5@P5>$BX;`;7DK&M7QK_kv!;Cl_2?PB`X?Wyx zu5kj;;iaqAojSIK(Ifnr``o@`Pq=jX7v^@=Fvtm@2I>m-d0_80DD`zo<~>%f=0eI% z>8}cBY9KfPm_HiYGKke_@aiP~Whr>ixnZN0EKRCnixWT<*p=mmL=CA*`4z1dD(fH^;?;a9w>%|gf(b?%%~yIu|pfCo?&)5*9KnjIbVhBw7;BNpXFzVBYOWoSAj8v0hEi-1#hmD&8S(}x`9w&e-u>2*x+1Q<_ z!?+%BAyK1xDD1}xz;x>MY3$Sql3*(*+XP#PM0tmrnm-@l1kmR*%hc;HNI|{xF_BDd zqOoJgqoJSgQ08`78sr3EiKdQiHSu(ZS=0TQk6^^832-1JjJaJ_1~~y(A!z_Rn>Vb4 zN|o%HkEBMOhVb%b0&}}83~~anK+zyJFjOMuWCUc-X1&xZ?QpT$y`z&0t(qe3IRO-b zSwEe~m1^-oa2SjjJwbCoZ~|y9l z0L-V>cm{*_1;W=QzhXMDq@?#yova7msGM4b6M*To8q*lA2hPPDg)EsfGaX=DTs+jO z>%r6}tuamjTEtA+zC`h25EinN`RIRMwH_8OUcub1P=lNRLXqO_VAv2}=-#y>b0j>y z+QRKScbVH2VvrL+2ui%o|0586Jd9MK$;A|rq@*OMQoSDFxdUoedMX|k*UastQ-uX&8; z&Xo(IkB0)1ft9>^^_S%Wjhw;>ASb#ev+d#T2J>c5VLIxHj&;ZhaS~ITDUERg$Of%B z4X;|U5Ng$QVmA1yHR_Wql!?sjr8dL~ARDyiHH=kgFoc?gV7m2p@7}R6^;sL70J1@A zUc-e76@;Ut9+_0Z%kx!hxJor+Ri6_;R(Q>8yi4cyFml)+NdPF3Ta*(((iCxJYX}5x zSql})mlX|CS^Mgub%iQ&0tiKlx1&ZNGr2;ERqDlvQbqST0mRG>*Aa|B(ISN*JajkJ z`GAsX6gdF|PbF_C7J&i<@J4JMqSoUCpoWYqh(Q3urpJsN z0&QA1|E&7eU#~%r-UA>Z;guNkqIEa{L_^0F#Uk+4mnAHDM>COh?Dy_J0DSn>5>5cM zkmvns0s&3{O-uuKLM;S10n|dC_p1p6H~};<4crN}5a0w*3whqJCJ^8R(8M%wC)7fK z6F@EGdB2)KfD=Fy)4-ij3jt05wUFoiY61aH08LB-cS0=${tGP2ib&6(6Jh`W002ov JPDHLkV1k)U_<{fc literal 0 HcmV?d00001 diff --git a/wiarygodnik_frontend/public/web-app-manifest-512x512.png b/wiarygodnik_frontend/public/web-app-manifest-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..278689fbe7c00b29807ead64dec11e3772c8eab8 GIT binary patch literal 26823 zcmeFZWmHyM)HVz^-O}A4-6dVp(%ncXjevBkfYOb0cST^z4zK{&A8?@ueradsmNiVlAyxCz+foIztn(%fq?%)V2}~PKj)s4w=ghN zFbXdvwLDD@GLXJ1>(2B(MVQDbmS1KYE>3Vl}FY!3F!#uBi@+Gb1sMxvq?XL8%&)CwUZzLyhhkJ1har8qGRn3c2M@#oTfv6F|1&;mclZMYR;%Rfjmv)AWo zUY^igWro3|e8j%P@{bl>Iqa>s3&2H#Ue%-w7QRs2G|CD&^EYXm+Zm2W%OYg@j3s{G z!8*~<;CdRZG+Vzfd@x&Y=p*$`YvJp4-}LFI7jQ2Nlxi5xB#!!K1*)6|(ss|&T*jOS z-&9)CT)F7&?L?zXAxKUCyOp+&vn>~-2a{otBg$1jDG1#OGkD1s23A_Cw5u=z_Rn$j zVjiOF(Kz&BR&6il-s#OsA1qYi!x^^yoIVtOcf8!*i_Zi$rwzJNr=6Aa-K|r9ltZ}o zp=A0xxqHEz948mV%`Q_D?DCarVxP-{kM`{O;LWa|gU7U`cueFaU0vf3CQD8YY#A%N zGfv}PD=qLgxi87G8nz8gg$IHqtr|i-U8hYsQm5^ZklhGos!Zp--$GHb!fMGS-fG8B z%4$|izJ`EWv}j6koe6bs8358c!cTEwnJTsgV}G$-LmkTjIU4D zxAaOy@y(jeN$I01<0Rmbt6@IF@S2=?L&jr@9Mxb364+tI#l_8QxL^hOs#O*kIGrBN z?=SDXNadtvfQ>G{3`BrA#;8Jm8HR@a8Y zD@=Np#S-mM&c&+JOd+w@UBb$>Tc{meum*Ajg)oYE#(g*9^0*8*<~GQx=qewq*RPdA zZB5-Gu`nlG&&vbi25VzP29=aAwQmFdIuJ!0Z(zTjC>Nj&qL5qONF4@7GunHV;p~K>bJTQU}&`68sME6X<(TLYk56R7T=4G9=x>h%gKh&xpWqytl*d#)Gwf1Xi_#_r-bKDp!6q2;6P-=ok=c63^=?$Y@3T2@o4{0X z@Wm;F6Rly`w1@`0cAsxAAZtaUu-P$zjqntof?wA(D7^cyh?`9$K{8R)nBUO`xU9T@`3Oz&=sS3y0`P1v@})9igA~R zNTxh<%e)4<|zrhtQs4@z@jS4p3(^mynF z$LCt$J&X-pfKLi8@5!dlqpCt;1n;%|47?ZSTcvW}uR{1e(Zo^Ekb-l^s|d+__QH2l zuI_jecc${;u;0o^2}C|gV3IV*Di?zTzWNZjTQ@ln@U=Y>A7eWLknaopt{abM$>pLb z81TWHeS}6HqUyOn5BK+@IzBTi#gZ{|g*MUf@2ROo;d+$6hNaXJ?&d}-f@3gI1!3dk z5qiq9fd7!%=I@J?kGbZIZHf|?2M;{LwZcTab;t^|zOwADM!5A$t-6fukcJcu4V$TTy_dN6^B_IWhrmtS9S_03n< zWwS(mLd4mPds2Ab8f*SxH-5xTerzg#5I>w5Os3{JjEuQH-H=4B!|RWy1}SQOC^-L` zN?S2sDJ>*}XbFbB7CyE9Ah0aJ*wunB85-7=z*{%x;~8IhjY$#l`NFhYwZ&yI7=(W3 zDGKNwvtT$0zl3!$xO+%39bvvw<_>BXA1_kfXGY|frKGul^IdEqx5MGzK}lAD zAsHZ424d9Cfe6KGr?C=}>2rK`ip%iL<}bhfLfha4#mdafd7(j;k2u}oxmx|^m96k? z&&S!S4Wl2gy(e@`(K1fs0xN+V?1oL~S)D}(B&#^62{3l(Nr%}ak9{K*aOm1*TQE+$ zW_+TLp_Ud(U{*&rO=6C^(xkg0=B???b9&0r`)->t@@q&!LBa``^7(Vy7_pm^CDK$0rh;Fl5xFjU>j|EO>X?Y zr0}KCL2$WIcyM^q`q>ss>GvJR0Lv?z zh(e})x@#s(-S35!k5<~FSG%d_tCMe<-1ZwLIyHqd^A+N=Z8p4%HA>PqywUo4I#i6k zn@uRyfqQlW_oVWbO)8Jccr+GntpC-ZE?b~KvQE#!Y4;mq)Q)YNK>Ww;qeN-Kah}y* zS;mJg!p~%aHKe+;7X4kJ(W9lxZx800S12$ilyIt{5Fc%=z5o5(I6arIwRmq!ZKBf~ zmO8lyT!xX3m4K%_D(4k9g%CNnqfwGz)NNOEc&|>aMoF~v>%F(VzkW%`cOZkaiOBvF z{9D!4va5U#_Zgdk7DrvN>)uc4P%isTJ&G+&2KuTCI;YI^-RT1IasLEaXVoQFRn+0s zdQumsFFs9819BjSsWF~%!@n8(KpbOXS@_{qxEOd^uGQWp*Y z%6h-W_Ds>x4k2adJN~PbS+NxKj%Q#I=s*8_*GNHav|dB+Yt|PYjAu|aI=<;u`MN&4 zeDD4{TDXltF=6z=Alvsl$C7^Kd8+gZrDR^A0~HTEG(XudJKTr}&$g$Z*-1_6$gyuKuUs!Y4)qHq$R0JA9f01a@e zkI)#^?IEpZhVlM*e%YLZ#_@6S`^wmNL(2Oh5J*C;KeGJY8V=6+c)Ob6fwR!D@Z_eh zlFMs1MzL}zYNqtG$BRNF3GRWdwKT~TeZTWNHKJJkuyMn5zKY%S8)BDiL~#0X(TgmJ zPWVTn7ukdWY?=+4NlQEB8Vq|ky}wa4yj3mwA9wvz*yd61q(QB;L+!l&($OU6cg_Bc zQ?^eP>}>1XEFqOKTutOY5m-T{(E?3FLkext%0pF@(iyz7`7kL+n+jM4f=3`(V=9j; z&E`=1(&pw!(P*Kc?m}i&5=Qb^o?LHNb!a;OZufBV>Bc#cz#F1C2Bkm21a|Dk1T`cN zi0HLFFDl{!rJ$)e2HmDfqsUzujn(I^#^V|p_W{d-uTPwm63HSI)$4Nye7IUsh4qSf zDD7iGzmfF>bdBpPP%LC7&Pj-@>`Y9ik+f8-~ZSO&koDCgQ3FrarzqU8ir( zF3h6K7KR3QTEAK;o6B17ZYjgV{3I+9uT2gNZ7o7#TU;VFj0yvO*~J&muUvKAzdn`X z!^=febd6D}0>5+yb=Jf|nOU*<4fpO!V_F4&-9UMufn?NGj*OL5yP`2|r&Sfv*81bC<**NrIE8Rf(!8Gb z+-cPhI;Esvd=d&%`~zp7Rv8W#wi^zGzj^HoMEM`EP9PMikT|3b2dUOCPC8AF6R0+6 zJ^9E#9moL#K@p6n7H3HsmX09edR4vM`X!_JGF!SRvtgD#i}N*v6(utm-oK)W(=*5 z&PTSryvH>1m0al^aMwMK=KElWhVskw9ID|2{};Ym3r636Us!f1U?f_muAVbl7#DFI zPz@$kNwo)c9j-F_(ZMbO&^U^*wU3W5T^f?PBt&8_LwT{^z8rBRiZol86%hUgW2{uh z!tX<)UbyewVv{oq0f*ri&7$9W2a#gi7TsZA6gK3jJt|c%)UC4#n0iQf9V6k8+66{Y zwc`T~plRSMR!VMz`xecwDDpuGmfK>JQoj>)GH%o}l}St*3~T;!<2Qqj@7GR6eK&~+ z;5oV*9E7RvkPcY6EEKUhI|*7L{^9|!iKWxBU#IDyt|tL@Hb}o=urk2r^LW{a*@Ex2 z(f}gXL8K!70MS>`eeFS{@x`0)Z{EY+hAnYkxLk90G_4#i{z*&T#cQ6Ne%nS7Qrp-$TuyZ% zi*BVksKE3HY6cosRIJKR><{y03ttiAKgXC^`S=I+LU2iAk9AD26}qe8n@Zm6z0o_~ zA`d?rY7xJNS1Zn)%v4%nE$~UjzUFQ9agTbp=-zq)5^9W7F^g_hqw#MOJV)*aZsU1g z#iG?u{G7#a4rLp>X$pDOgo;>!Ya!;#@;~%%iziw=1xZ^M^4)yf(5malmCgCAEI0ng zS+%b$$Qifr_1~mJ?_wV9&{yr~nd0QfMe>fN#;TDQe}suxbSwUzb5}CJ8e*HlX1o3n zyFY;|$J9p_%q=WU7ri63ow6}s_{s0nzEtiL9iZ)c!QXy)B>WjWuV?K%rMAK4>ESBg z;q|YAuas0!`cR@k?Y8%Apm~DwPPbQp19Y4fW!1WRWs?q*;!n_g?9q0;a zy}Vf2qKmW>kzT(pp2`+V^z`!gJ5-Rq07}yJU)LW7Q_h ztGmI7rIFF#HjbtcmAX-^_jRm}kL%CYgyyeoTph2?_BU3X`G-|uG?6Ovb;luxD+d~5 zqK$q7nQXO}m?>R`%kZzxgyr{l-d$ALIr7xIydK<+q!KR;8*++i7r?`LM+1&R$g1Am z%F-=7gaBpMd0 zU&8d6z=Zk0=Ql6uT0A#j{y-noN>!=|peonjXT5|X z>~X06@47%~OeHn@*vjab{-W|~jQh@r@8&U-ws@twfOh$=ec-ZdvZUJa0>>&ky2PEM zR z=cWC_X^m>?q;}pHe@sii7p94iYl`XqCi}7XmtLmPaY=RobLrjcDwbjhoAQV4-j>-qKv&?ZxlLUM+{LU_lN%a@cmMJ+8Ws^;IEK5EZ~IP<_xZ*REyuzSzb4Sr*xB zKhwC91In}>Vm0}{vt!cgxt{95A~jhonnfc&KPgNkE|4*@eb8mihz6A{3lgB4EXV}C zjRf0wpP_gvf~Z&YtM0-D@6gU+vC4KQsesV;yCQ6q|M`>451i+(0{K`zBp$Xu3o;yx zQ_=yr-ybf7snL|qaC%7Zg;VPOahhTcpa*7H@K8}^K~4@twmb=6m*I3guSPbqIiP<) z#MHfvtyGVFJCK0=xBja8Ofdw<8FDsIY!~hCd4KKvE0O4()ryI+TAsHR9Iu?wmZk%Y zX381g3tFmmWUm4m5KLZDVWaIR%S9dN)4VHiPVTFG`Z1qPnKT>6n=N)60l5H&MJcB7+(Zz++Wo@3Oq)#L{R4k=n|fI&zak_qzsD)l$k z6!D*NtNIisRtGM`D26h^nU;;;PrNny0oSIBO;v@!h|N&#u_9S#KY{Z4H5P5<%N>?M zKvK|#VvXvTdHkUe@eCYM(vq;=RX)Z$wf(okz*@s1o+JgdrMe^T;zINXgKL)Pb ztHY?y;4@OR#kKi@xkxe(%`LaU2((P`x2T(&p^DtTn=dMw*Ub}+ayjT$v4K}mtj6`m zHn-_lP2Rl`oOrOBvyIxjIF=MzZqhPAkq_+|nty~*{Do{k-$D-1gw7j_>{mfXg&61> zHqzO=n#{W23RTG#>vDmPU$yY})In>Hpb>_?hhQ?a54i*tl8G&+$wgxxAgcz}Xx@#TD# zs(@CN!PxLr569iZJwig6nr4beU5{LONbn11^Jdhb#qVO$LHAxU)P4rNSoCoXKLOtS z1z1Hk)ejL%Nv8|kA%^&S;@0pk{3HrP$PO2btf$(9$@z1#SPi(I_a z_ZJPc9Q0m+-6uu4Zn36*MJCW0nYhimrl;Zh!pD~0|K77wD%+*NrLqWKB|bdBNUA>d zf{H=49FOT&qpd2e7I7EbaHFEHK5;VplMOw={Bzi7kapg|&3%6Tpx*FaK|m+9_S4Ga z@Y+FSV)VH0XOb!AoZJRGmE9o$?9s3jn0UBN3hFb&kODwB%Z){yUD z2Vvw>e90IsQXb%d6gM^b&G9F0qgUEo zlRxcb%`;HLBbMp1YHj27e07fJvY7TA^c>~G8cfeEutZnLG2xMmo9}gJ1T$#D`92F8)l=--Qu&?yTi=x zzrI$?j&BE$DY?sZ=254UQb-cA2C&izfs|;o+e@I+92ZZ=0D_(-!I9Jw5tqRqFKCbWVy;NZUlunXZ z9SkTxBrs_*#`gY~xfHLZ7$T@+XuP=5Nyo7SYuzatc)PC zj_1fNac*%NQ#ggB$z@8&Bk50@>|>>)QM=I>n`mxaD$^Vdk-{>cq>@o68?!9I$C*vy z?S58gl^Z42Z z?>&73-lj<=c9w_JHj0AdNeVrKY}&LZOWbT!8VuR|G34$>@qf}tN^^dlm!piJ-5 zKQSPnocZ8W^-b~w^bpJGM{B%j z`=bAhgFstuQ2X<}fEDUS_M`1VN3te1fT#Q!uo!WH4FB9>dbTPg`xF24lx^&3+1YiL z6odnr*Y?>b%tHfajFd-MfP78YhCkjs$ea#0uK;CM`Zwd{d3{whN@m+ zR9*rUlL{W+2blk~0Ci*^L;VWQ9;8=Tsi@$B0rGJSvbs`MNf&{GR_0HT3?24#0pP% zCYv4vi$bJ&kx(f6IqaS$^#ik3BA~aV{D%@ED2wF!#=YL8`sP)HX+xm>+<$!dLUBLBpuokRbM>5b1TYFKR$Ej{UZK;4EO@N}KDqqH41m|}~H@<~pj?XYr` z!l$g-`9j;YK;~qJo>`(0F_m7MCAl}yUv!B3N>&&N(?9w)(m?+RiJU4(02)hhQh*wR zP`IJ8{@yV*fYo)2<#!NG(%VikOnJ)tl!+b|XZRy++Xtk`j&Um%<&QUOp_FD1w)tnTGs1GKoBwp4qv+My0Ge>e`I_XXl=|Cpixl1T!tf{o$sXa?> z4wX;Y?k(FL%;mv6vJIAfJs!Ib0Vp6H>PhQVAyv@((6g5E>Zfo!@IQZ*`r9xGUWA4! z4f0l*vP!x8ZYXbmNN=%4TkhcYQkdt}cl%eVoTxJRU$aJ=^bLI*uL5nHCjjb|0w$wW zCyRa26Yf2)L`Couo{XWrHI|ko;By0jg2P_Yd3-;T;&ULu~K?{9pi7ZKc*Rkj>KHa zhxo%~t2EPgrC2Eh(*KUC%<3kLZ+9V}c*=2945cLrz~c#pYr4_^eh)W0%;?8`kzG@we%=QwPPNWYD6AMyox$QpA7dHmvT0z&U_CPv z-`h->U7+r-Obw?rBGa~$RIRs4W!cMSdrcr(FV%d}Fd5t<5Zp2k8Or2>^>W$a?V2QY z5b-`o7IY!leg&gcE3x4O^8czJ@f;VcaA-vmMJuBDg~8vqC5Gezhx@8jvgf;c?QfXk z=#_HY&ya1=^}iGN-C}%Moys(xu22%5EHR#_4M*2wi;NkXzcUNG)7mowzL3cvP_4sv zelR_DriC==_=z$)qk0ibXcZmeQYxd;SWJ_XBS4*IlqKS2-lW7=rYoCeVvOF1n;Det zJ$%x&mbb>Xkrf}f2ewE=ZW++GlV!MO-VhT$z)&X@b*N*?Yo;d-Zqot|Vc-{i+PY;` z_?QM&yE~3q*aZXZk1Mi3zWp|SA)`MG{~#sLsDm=>k0(|o>lAR4e?I^w;+j_%dqSvi zZ%^2*L@C?z8x4{8o3GrM>}dLt{%{dj44|1-{rXU2aD#%!k^9Y1s?&GM_nG zkcriyx!4aVrU?0A_Nb=6DL|_`G=pILnUXESv>hr+Ha@KpUbaptCqHB}KUK@7m5ZhY zC25{?f&ae{A0x&0L(I&z$(B=hG3*qBxrS;cr+x3NlPS6byyWp}3=y?t?c z5>5L}f$&410+66(@6FS(E`ljfN)5trKDbuZX_maheEv+(#qwbG$Mjjo>4)ppoUY=T z>foHZGTn;L{(e7*ZM(>~Qfjt%?q~Ca{oi4rv_OHsEUnVEYBil_(w2v8H*?SnzwPoZ z|54btxVuZWJP=#0Zz6q2SQJ#cZR;^keXj}H?^v@7LVynZ%+KnFyH9*|`*e{U6IRRD#6PfuQCP5`oXOOUfS@KPxrhJDy#DCr{P_&t! z8q_7Ssm@A`=dCf1gtGlRGH9>Yo3Ld|JPe(JIt$)C$QCc`e~*D50_287o>8%x*sBcQ zdGuwcdi8ug{d>1Vr@@D8xZey^D`8s;-==U{tOXIV?glsow1|O2LF9`;jTJ8N*E zy!-@Rh{3lJG>cBXec_XSb!tKGm(;L%C|V^(6mWMJob#`mZX=hGiwE|j04!Twr%dkL z`iVei1{DmE9D)|H`N3|^8<&8J3K4|1jtav@wyTerFR}vbT9YnkbOs|w)iyb_z>}NW zdpYa04q$+B)zJ~KX*`SXiLMjLKnU|iNlB2UhUG!_%_B#81=0XT zHLL#8X^JjuUlN(0L}$zaGrg4>I;t}59ltp zNm7A!(O1!~+l?yR=gPeaHnkW*CO;+#iTKR3seg#7-|A=PHhCPkF(kiZLm^TD!XMsW zAO{i+5{z(>xqBiq>sEa<^%o>x=6)1J*_EPF&;2ypx?yMh-Yd_td!T-I$?3BI^RlNy z_n8%^rJ9rUd!Jn1{UU_ZU2I`k@6HIjNT?peB3;bSpxmIX!*hO3uXrI_5YsQ<7ZgMt zKbx&}r3Ji{nN7zX7Maw?o(hapYQ}2BA07@)pB+6C#e6Q&vn+@Ak6bEgVJD#6yIMdD zGku#$;}Gwz6Zd3;w1E9m!^FS$(yKE=tg#xlx9NE6FB*=T2#0Z+qaEI3JyxDW{bNb{ z7SIGBySaM^&cp`VfD~d~jC*~z(d;CUg7}~ua*II}VnscjHQYc3PtFM87Db0fws_F5XWMd^kN=6KiC$4<^uu^OszZ z!+Bmg5JcD_4GLiggk8L}DjSR6O`cAc@DyvY$sdmvN5i*(Sh6bE*}CEw(jMSj737@< z6@d}mOnEwKofzPpe3mei0J(B`EYB`NFP-Ojr^)9k^Qd$y;bXdcwMN9^hMAR7okIXL zt?sD(L({TYE!`^b&gW$%vX3@IW5@J9oso3da@pc+|H1z$pUfXwu;#E_Lw+cHQ8$T1 z!VokAMTF^!C-=mCnZxtLYN65hpXc4u&Q$2ZW`nwxl&3I?XLvacop=gvW3#NpQQP5D%Eb$JOs=tXZWPXbMfwZ^_?^c_8a*qbQoi!I}%5VP!h=8@u@;Q>Eh zbcb9fMc`fZGPKNY(l&5|LFG^OUOTfElVixge3x5fc7W8JC_H!-Ro4vL-HTHbz z?eE3_l3I~N&VQuB=P$2+>{2lC>u2E;lTgvvsxrXMHOj`8< zE9>|-ht&Y%FPGApp#}j7tNDJRcHyjd8ulJMWAoNUf-J^|(HvtXQEgfIWb7&dnoVR5 znjl?ZmY$e&J8$Q>oG$SOot_CIGWNnU(U~CzeL}ha_BQ!Kxf-(1+Y_7D>xSV4fFz@C zLqeqxZ7!=v+j^7Vj>=2+Ej~IkD04n?`dldqet}7A~#r(vxmmd zK#W@`- zqUff09On8RvgmMe+v4N!eYSHo4oLHEyN>@G>(>^lN-T>^H(=mTcuBawgai`jK$3OI3wkRf0AKtR@9bYL9ORA1$k&)MwbgshhpsaT?EvCFQBQT z^Fwk$OxCO~dpRaV@6DI=yX4*{m-c-o?nm7o7(+JJ&5GYJhoPVq-NEuHpRKe`uHL|) z?&uRBj`a=^5AU7@d7iGD4-d$A9xr*IN8kSZh*WG;feHGpk{*U^seCU1FXJ||U(y+w z){tY7Y?5ixb3tbYMW0pK6g;+^ib;%b3?R#veV;SNl8|JO5*VnChj&I&AYKuU34H>O z>`S-iT|I0eU%v|5al32{z5eW|nh=%7i9hjX=wcJ6k{(tQy2}V2wa+icfRsx!{zS-P z$6q+Q2ESZ9)=Ust$V?~*u;&&By3*L9-n>f=gP~7Aa9HiRhq~kz-U;Ygi{r*LHm6bM=yp1h2EEY1*12W0lsdnL9-}$_o zT1Xyv(*(q_=1bliZ?O6l5CzA~>g97ZtNW6h{6F4#mj6aLYzNsoPxVMcf(#Yu?+YP*}`i%a>QovOePB5c z0(x9vFm|K9`lT=0NVw#`EXYP-_dC;|q7=Ve{iwxs`V)yM_Jw-q6ED{7UDp1!^g=C- zgws^3$KIKK45`@LnteF1x&pZK>D5JjBb#T>pr zGiX|!0)l^HZ_1=^?Pbv{ zJj|b3ULqKMcbUp4Fp`EOfhN)k;{7<5*~$^yX9Bj;0u-DL)p`u=alBnHbHH{Lj0sKp zTFldtBu?cduD2WL&_~6|r7%9vfYpv+ns{T;nZL)}BtatQUTy;9xH| zdr*3zC2>}q#^Oj$pcq0MpDMT0Rr(}31jVw8_&!(UFY^j*MPfN=#QuO*HS)_ZI0%Mq zCa@{`*&pP0xo?R(PFuZR@hhoKX0Aj^cJ1R}| z6B-`-mhGYpHEc6*=vCQ5OUl3lBsED2asLRM`B;fe9vy1Z^PkL+o4;E<5hWYt+)v`} zGXbr{#y>8!dnkpZAV<*a5DSuqNhSTYuqpU7=yA`xm?39t95R8-<3Egb?VsKxGarp& z;k*k6m|TFfpX~h{dU05vrd3)BX}Lg;u_~ zwExogM{48K0JXvZWa8#pe>w={=@Hm@lV0$)zQ5{#<_<@#L^Aoh_RZ4F?y@V)gfyf9 z+L#+on8GZNqA(V2`aXYcb>@(#mBJi@D2a!2f)4@2dUvPSL;|Wnu?f%pyX#^Nu`yzt zccEa39*j12fTs#KUYMbljUaL~d3|5ADl^FCIjh@4nu~y=_Nk*~PBZ3j?Ln9)+`a!J zWFVm`=<|FA6HJ`6_$ua7dJZCp)u`H*yWq?IM z#$!*Q)O=p5eWJJ$FqfbN`T@|!spRx#TBt9ax_-)M0zFsGF5#B*!)@f}(p5J)GbUh+6zjSrd?#o#qyl!~Kv{6YiNnqSd-qJu zhI0nZ*090NC8Bgi&;%_|BfgIiwE`nSXk3Nhra&@Z5 z_&Eb)(-I~a{y-)Bzxu@Gbwt(+4AA0N|IH!v^51?o)3=>{9;<=RR^e~tPHZ>Wo81qc zDg-289G8ALq+{DY2jcm@`^dyWLK=g*VnoBUR}UYNu+++5$^Zr7#er1ib65mm6(=-I z+%Yc^ZNzdoUS*RUyxD=Sbtsz`{ z|7V=k)M@^Y%=?xE_;P9}?1g54$kRr>#2)eS%d2RmdIM)Xg2VZ&Y;#^4WyVnZlxfUMhoefb@UIarQ$dkh1 z#6FbHzpTX8W8{C`7hP=FE=USb{4v?U?KxGXzfLHt#CX2K`{{#Lp_FFzQhRM^$o8?C zlz@bRFpw=xvkj2R&310?t5j~>GihqrL=@x+FW@Ga_O?4$t%$gN>;8WVm2o%b z-;4okneUnH<_dY-{q8a_V>J*^h@}4~j&cpOPLdE@J}Vf|dL7TkA$aC;0bX>JiQ!)i zE9f>}SVba;qsNv_(Tlhro;d%WCWgU7W#}uvO8?a(&U*UypG1P*A5_LPFi?u60Y9Vi z4~S%)x`h-^*PP3E7O7-NN~l@%3BCadSc*!&h7MVu8|(4$RNHy)>4v)dZ?aX{>0*1_ zT#n{4)J@rbCRb95WD_!LvzFz_`e{2X)?sA)xa_HYJ94i5%7N|~EaaPcHxQppoPahy zcGG;i(tl;rFqbR~of$W9S0RXM0wXnlrC}6+So_7=rrMxl?V3H+Jl9rqpj)MeP08bO z9OASRcu;u3eOhInC?Vp1Kijq2ln#FY<(PhZ*)CRN&Nn*b)av+6VSurV@Z`!-U8efj zKqPpr^x~V+J7vSV-XqaFk)Cuh zs8-BMU@xr;Ie|?Rrwj2)+r74YHA(LAY}eETR!zR6A9_{7k^<1r0UUs6Gb2|~hX(Wo z^eT_Oij={VQV=II#PJNi!GOJGBJaOJBUCR@bPz#C)0|fol7o0d4HBtaU>6y+ zJm|=Hfz(=(a!R-IF<9s#)p;OA>_y2IJ|t_qFN9dLmj;A+#oE}7Zx|$vok1VP84npU zXkq^o7}}l7Yf=gBq>CE9fvecfyPdCZuNQ@NIN6_by=BZNz!^o}97ur!G?f&XQ%l&v zu5n?zJtxg=$$B3He-523;)rt^jc0ctVKwC@bP)+h zB&GKj0bl+ew?9eFh4E2mJTcO(vVgt&8ndUvMv^B}8}eN5Z21?^N{u#o2}7sOfZMIs z!b2f#SID_c0;9V9&urt+BdFG$&9@+)E}IZonRl#jIK_?JyRrK{zyai;Ot%O)@BB8d zbDYukA-rw98Yup`gFIPmLfq>8Ucx2v0%r}*{?taU}p+f9e2kJy#rQg z_NVMxF(O`P@IcPo3Ha<+G%tDF8J+>T$xM7D$p3TC6Tq~M?3S%$Ol~qXse`M(5Lf9G zK!8HWF<0hTnGM|}B!{-=U0}==BY6ci2$n?o7+uVUKk^;c6KDkFg&$nbdp8T*d5;VO(TQeZpPtd)}!&{hDvT*CyD>cf>;XFMS$XfVuTa(J7o|_9wOSFf2h98jeGhlAq31u&dnhfZ^u*ihbUGbam7l(RQ%k_KoVe%)X8LvkCFqo*@_3qTy}(DH8VNA*%m zE;P~4O?x1-OGGcjQIo?nwMnmbVTpGXzlMX3&ln<#zFD*!`pUPG)HY#*Gnxhhdg~YO zY*j=AHXwoqqLba9+J9IRbs?>H=$)XwFzFnYNhBo^b=^<<2E7V&kr!E4Z|hKRK`XG^q+Tw+N5y$4+a>*Z2f%Mny)Df0wCclIbb^}~eS zRC#HP9JZ?rKO!cv7-CwZee_p|i4`$yiXk?h9(jc!|F^^D$K7KjF(VqK%1}Z?I z026$KDt?F`$g3Tz3sH#y^B&Ii*pFMu6Dr8Pr(B!E@e}p^9EWl?WZ3(4#I9V9omz6g zI;sBGNDC2{x!F;NQJ6k~LasOA0A*c}=&Q=dke+z&4X8jX=pieSL~b3r$%0`1(*k&e^~D$U49~xF57xvPc!3T@$eeY{Oi8Cd z(Y94S-qRk^#SRDk3{SQ=x|f0SoAFY$%B(<&s@`rwWovhQYwP@!KLB)UI{2vnTe%;r52 zHgVd2hth=}$}ZPdpv*b<2qRl;U?d3mY9d~H6Mp%JC|@JMWFFIz&9B9Hp82vF`;PMO zXwE<$imlmMwya2HHGo%4u12n1rt@x5;E^y$i84&+BCVE>?}nVAiN|0Q4G@STXQ$FB}6vAK0$AuCa+R~4I__`8V zbTde3HfUg_p_T_<_NeIUpG2C6jSRGTE_4;t|0CbblD z0U|$Xjh*_GCyUi%0r=9Y)WZa07w;yc9vhdU2-)w05S0zqfO;Kuss25HsZjLd=dyKn zZsCBwA7QgW{+;W@p`kBu}BK$zM^H)aj<}VYk<2-?Yl(Zk0Z_g{p52%iuRM8c`|M$_{1Op8~P}?Lr zL-P-JSI$7YYrs`ad3QCK_FeiPPY-pevnvP@gY5j%E`HR$g z>*xiKqnEqhCNIH2GgRAT?<>%9wcK1O3hSa3bH)(_V1TohkIV@e*Eeo|1ls5Y5$ez6 z!UUVYLVZVf`ZA|3d>FFsPtG%!zPSp3aYi_%Tj*TYG6(~!qS8uyeW5*Ht3qb|?aS1k zS&%p<%jWD(zM%nn7aR@|-|Cp%9~N7_kj_YpdQY;xJ$%^c4Q+3~|8+NV98c#p!Z!nkQ7tR6Zs_LY zNlgP1j!lwah@bPBPkQPGAVa6C+n|YYa6-c&k_0}-Z-F4n@zxw+wYoYK84b-frLExN zYryGd2S*Jh2-kDuGiw&|IHm^5;~wG;LC zyNls|4~I!FZtaAj$Cb=|MV2HtA&qz`dulGT*c@0UF98b~l+v*njZu#oPJ?dNzn?j% zDwwy@H0ZjmhxT`m*c*9qc_}D@kmf1EVd3P=0PDWSwv`3GA+igV#i~$g>(EZDhF~1+ z&u6Gm!%iW~|1ESU_g)>UdaLak`4|(J2d%u{dq0t;zxqNdlAUbF%L)`S)Yagt1n5K} zA2cbo6_6jmw@X-Id>NO{6tmqc{_M`S;YXL>s4Z)wUo^O<*R)^unHGvd<9<2#m_-N4 zQIbL8YbhW~HbZ-@RJ+>T16BNishxLmS;xze2qSE8GdzV)bB@10Q!HK3QDwiucYMZ6 z+7>+@AL+lr@T$87L5bC_>mYBJnExL+3JhgCSIyhO2v|QKD&^EkF_jN%qzV$hFR%6l zCeN4!i?RUJsa2`K7}Q&Lw!(((3^*S3H$PVOyy`r|x4W)baqQ1) z|8FecU0h<0l(RYjYlg@G6~$A@Y^PFmUbcPBcjlN)-b59G2prVxnO<{gqI2C;UC9Rr z13vIgkbve8$#yonle-%-Xz3MfGRlh*BjE`w?moVv{u}H2zFh_Rm1X zys#$!4of6+C&qXT4zCN8rd6mUQ zC|pPW$gBuZ&}hE8u~vx|#W#!Ivw4|4Q%;9lBj}i{ow3&cY46M5sqUh;&pGCy%#|ra z=17_12&a@OokT=bLK7+(Bf~k!5RNI5dB~VKLqe1ubD2pQj$|f7#xlI?qv!cP&-cCF zKjH1CuFLk>d#}CM+H0?U-!~j42Z@rGHEh3!o;a0foWd9@mm376!+VF?rgAbVNlA)< zkh+RjzPk2yq%Y5a;bUyKi^@=+=?l~W#fL9u4AD^BK(Z+VnLF2cmQE)ZD%>c%?t^U% zR|$HY*j|!InFxIMEt)| zTS@hK-MS>JRzh+umsnc0*UI3D*{E>BQmcSPe!*=~^k1th{RQNrZ z0cfEKvzv{PkNYJl3a{o8{>>aMr<`pJau3;!H5=ycxCPC8-A?klTJ(v9NlG(>i(|Bb zQT_UyVh+6wK#+qukDE|knxvq6h@e6m8XpqNDXs3~dUKy&(3v@6oS{qiiDzM7R$O1p z#%i9ai+NY{oMNhcRroni=ScLHTe9`oQuAvm#;-2ZQ`6jl^Q}ZYuRK_(^_pvZoZ9_+ zmtKyv1?`h@l6_XE_f{bupt|eMYgcW1RhMgehD^VXuA!Nju{_mtrlMr0 z*ZF(-R!x*w!aJdo(PPQexyHw$7{`2jMFk4)88p(-1FZxp`czsq(`-HUTK+lS6e#$Z z;dagVDbT@i4?DFk(6X^i@kQfp!etlLjcDolwFD8_%n(i0JjIJ9lnycD9XT_;4T1vL~M$_!80tTyZiB)xKpiD8>H>$YU)mG+N!Z(z6Meh-p z+})*^g=mxQiDJHFAlc-LO0%;TQb6Q$Ze;b?IaO}7ei)zi8ROGci-3gH`<$@`-r$uG8Vp> zb1PuG;v7zaJ!9jjd}sQW)^F|6SYxp>?HP%_YvydtMubwg)s1Ni72g%1vE&Q|NuOD1$6blJgh{S<3TD~Ib# z>`e%AyRZIKU+C&^Q$&?N6!a1GrN+b5ht7Q!SPN{Q3FAwS4@96vmW+$dD=W}xF^E<=R-TvhQswFfY44Iy@={$-U=+d4pWiY349l?sEN zkU*)gFbQf(pj09mqukRo@s3U~QzhqO0dPxp1|@X_&>XPy^aL2-F-?o?Me8e>;E!D7 z896x{g(4|n-RY5axAOJ`<&I4?Oeac<3$3L6YYz|UM$087aiMw(O9&IT@h9HkF?f-q zkLoGEHzjmk5YR~q04P}rKC}iaafI6PJQ7QuA9p(k0ysy3Wd~0!UmiSYmh{h&pZ*3# zFj7zmx*v&NkH&(AA_#5Fw}(p5m&!~g${#w`?hB!W=D8Uq|B)!%ZJmUYiM+T?BIYvD<|p}w)U8!8vL!GU&J)&*Bg zskPCWf`bV>9|ayR+A|)U9=OCy!Y6+8u|%8yr0n!ywUa?}Hf?^4F3s;~#Ye-d!}YJL z3HZI?MdFA6m$!DxSwz-AxV_ru5hya*$wdIjA!s3j7$(EI3b;gIr&@x600h~_Cil)Y}x&(sJ+T&C;mj-{=NB~ znly05B@={XC|T{Wh=>zqTM`L)WDgv(&L^p!>Do89I5B1OK-M(UqjuF3mhTqDfD z)1*2T-RiLUl7NT{*q8Dnz_uZ_KR6D*Z|U}saH`Nfl`vsU)7;x@kRI`7??G&^Ux?{Q z;Oc4E_!>xrW;dA@1|c5bS~9v?FWbUI-SOoM#{u8$7$BYM9O>Ba4~@u$zA`*8I3jYN zM;M}!BBg2S9w0t6EpHphx0lb!F`n@g0#(noJl_I?V-X5N>V772+z_oplc^t>Il~E* zr-tJN0iY89y5&wIFwAF(D~{1%J1XKdu!645=aXob=6+NoB@8&x$JdQHlPeJWwZ!#; z{TzjkS{QphmAay@8DgEog>`2HLbqX;lG_baWIxAYv3OAa0XhWY5ls5&j&h7sdx61f zz@xk!nKo)=Hx6!We&qh;Lul6a=eUgXs?PFsPq^fBKE?LvyMV~R#q0|-Exk}Qm@f71BfCg2F9|u}+MjUcAc7Yh zhx>9y7^@5A!5_=;d)MeFb{S3)A;*3q}rrRn{4vkzbys+dxAQ0^0Iq@uwH)X%@a>MojJr^|2OwLDjkEw%|*Y%1y zCFs`ai4eHotWv-eaASwSFg)Y-SohWeklqDZ;sY?};1QiX_~Je`u`o3zkT=@nDoD24 znEEbFo7;5&Xp;8!F~J`Z7$YM=Ckh%`Gf#G>aBy|M%=43_b~^^82*Ba?;utQ@orXs7 zF^2VU;Ux=_A;X0_iXgm)l0*c3yf2r}Jh|`eJ~OGv8UN?z7x@LI%6R!ZwU;#Vuh(3U*2@l_4 ziseLTHqWU~0U>=4Eu;z!c|{H!NC^-JQLbx;{QjMGB2XYXrkXe!zoKLol&|2s5C3kTN@82L8sV*n5{Nc#7`3 z?L45Q#Nc)8(mJBLqx#IAS{Eb4PuZD%&PO=t<{^O3lc??g^-D)&g&kl`PTZdO)88xBfyl z%U$ z0$hf*XK#zF%@1pq5`G~NR?UVcvN3Am;I0B_IoRuV_o|^;3R~Q?N7AD+s(fRU9>`cH4J!)QV65HFAOr zH68eQ)hYhs)j2PyLNzAL$Tqy18YpE_upRieuEk?TVbfK1T)y9!u&+h5&9+($~Jv4@OqFQ@(f-_z@5_Vv~cc zU=t?d10}G@eO57()C2XwT(j%snw=5a>EpI=sY$}B8eL-wqaqXxql1%R)$U@pemiTH zN^lHZz2EmZGNaXZQ!gHoY<%^zWfBJGD8vkqElCqa1^`C%TzKh*P+_*YxZKy##eHQ3bni)S)6{IJIHtL?~ijmOj)_Bwf2o?vll6A(G z4ty@~C+_Rkt40W6HvMS(Q-p6PkTCVkKm)>*IR?2`rkM5Xix?O8erPPHw*WVRSKSAxc*k4|~0i z_CwJA{U98pxn!li=T(aLH>83_YwZgV>pXAe<#%Ucx>b~oEg%}Hg`>4<+N9g}DUO=+ z;CCw}uMxqV-mD-XIGA ztvxUa2=WL$K{rWe-^S9o{fY3uc@w12t|l0uoxL+BH!Rl_B_a}F*s>qdX^Ok|Ro7?N z8)H}Oew6>b8JjNk=ZRFr5EdF9b_WZ&I8-7am)`eF_6z~}8U>`#Yfe~67 zwA8|m$rWmcTASRRi+wu#b&Ghb9s=NhtC`(YE*07Fzm{GoAaTHsW#Q+~It1hbQ1%A4 zJ6&(N0gy7au9&cop8=J5+K|&6&B9t}LGXDEMf=~YcY*LqgHWJ--KOON zU|0Fn>PsPhM!SnKT=KmDaT6a6@L|D1JX_-e{}UAm@P(R*lfp2G5IUeEu@Fmh`V}#2 zW=Y3vRO^G|W``{Di{s%_Ee1Fmm_aWj34SqQT6!6jy!a`JYrJB;xj25 zFty^(t$4uDI&6QZhU)Q(MNz9=rW5(sYEtHCXx{^;ch!ia;5b5j_dy$|>_!59J$Pda zKB)8=j-dbKhp7leZhG7=5$voO_D_09qp`Z9&UO5{M8?OMnRUfE9F z0Vt-(w!;?G*SA*0`OOHdRGt1T2Ujl~Mw$&|cGQ}qk4!xjQ}+*j=S@zBy>$=vR-tMAq%;`XlJ>(B4mLna zjsVt>m#u3C6aIrxI-~FxJZ~sr@s(6y#Cx1+HSjT#VAxb-D9Z^iY^p}cbk^&ud&a;0 zbv8>sZSRkP3dl<4*m+>)H-g^6DXtjtPl|ZR@{v;3xw!H)&`g59k05=Y&6pHL`lbW# zq_gxN{h9ihhkG=r*6mM@h*iZaQ#K-cq^Y4uzoN|2SIzn+$zVi9Y%e%x7UySFCVpoc z`ea7>vFt(94&i%ho(z}126&;ys8WH-M_KIr&7%RkxS zdd#x|V;{hzLZ49-R_J7V=Sjrn+F1UR9Zs!(u5_FaTH#huR>d14t#5~JRixx1hbQMR|y7IXC@0VY95u5dk%4KK-I2OcaBU2Bw&IEj9!p z3W@q>TiHsYp6W6rfcPgrI@!SA2*6lnqZeAQy`}^jzLR@=4pk!tR~p>T_vc)$1qwOP zRL{UW67R>;)KsPS`Z$JX*Lyo2}u^vIm@+C8j5pt=J2_1f7A_3$YqPQVo=Ob8LPg?&tWQSutK zI`xY4i7*NpFI=5Sp1^rZv3h2>zc601h9d?EEf=X%DH`3@PT-RPd zmEngrnQQ@^vLeya&x4o@GVL9+?75Qf`HX{HY7DrT1T2_Qc;*$v%y7j)@RC*?wn#aj zL2CM%+rMey#bJ{;SJC!4;a3HpeL-aadYKk^c^jFw0T`rqqoI0S@5ehM7%UB%_Wde!)=WXfkcat_ySWOGaRsOa$8Yx z+w)<%lsnhu!}vjn%C49x)jyFj>?l#q$WQVEQZ18v`g?6Y?J~|IUU{uDZBz~m2Gn57 z@I(xFG#vM-t=Mw4ReK?br~mZJ@i^?y8Ix{WaL4P{$GKes&g?_&)fTEll1QNXLYc%H z#EBFSHUh!9!>gUPq2bO&0$i;G&sOiwn1u+BZ967i4TnHfPI9UC#4E_Y-@(njRd$m9 ztR#x(sV+$OKvQX2M2rTqEh;VY{QPaP^7(<2QPxfi4e2c;Qdag5eSt4c!brfxqkM9>#y#`A~$aEyZdxYZpa7= z>4@7Nm1&ow=oJn9gaHcLJeJ6pGdw z`5OV;3?}b&6ghRVc-=hd1+s&|tT)zM`7lPEN$nIJR!MFace zo)S`~8rgXFzMnl_o$GQNkpPsxm{ zeT)f`na~-2oj4t7x<+02gQfN)n#_g#F7pCycMgZ3YsHLks>y5XP=HIEJ!MfGe`2M2 zIzEc7!38CeR&T=$O{p+argF~)&Y4(vDC+%0ScIJHN&Ls}ZRRUwJW!w~9OINmKDbO9 z%)=txm06uG+O8hqZc=zYk($|YiW2$|I2x`6Iwrur0)B-J}=jEIQ_L>3{{qG8~`0o?mO^I?y^WGUXQoa zO#^2(oTBfx7%?61{Qd%JR;-8`%wR{v;c$dplTzK(YqKw~cRyw1Exmi6o+JB(P7__2 z_JIpAqcCOk-?1fKWCTr3CctKJCe9)HCaj4{^?l&9q< z5LzfP6cobBHc^fb-&Qw&SKBg^q@WJfd;amB*#Fq*2wUL~2J=C_+BfG3Wuy5M>*xn_$g#x9KA&dZAf>{;J8sqPlpPNbkdXIKazW5J_m zOwhfu6eYZY+T!-hpXvUu9}{EcZ5qepOFQ2fo;5^8>JLZ1-=Z|s;Zoqy$Q2yXhRi`D$wE$gKi>J(JWlcIx&jk9sE1&hTT@?)2^M-9dn!Y%*z z&x>j|D`c(OYds|>{TR80Z+Wd>I1}CMn~b`s5z>cD<_HHZ9bNd{xK~0lGVkZ9u$nH< zmY&epv|Z>&u@jn`7qQ4HrDLR01%>+zFy21in?~g3f*Nhx&}~oUn&Z@&sE6v|4!d7s z3*f`*jkm^*muI_p6=`A@4c!i3pqKwVrv?H>%E;w~p87sy_PkyI935 z^V+8$c`4$+qWFH|&l2Tcqib!sBK`4w-KN9_=yMB+l!cmAULC*W@aT~-J)!)J5+7n5 zL1Nim)0T|c9(~x$HQHN-BWP{ymW4Rim)3gpIKw9UtADmv8r#*V;AOcQZRP0@D<#j= z#{1)WIVZ(YhQckbEU?#~(Hb++7au%erJ~q4)ev|;NJ!vV|CFUsi#t2P`ug}e#2*GR zp*=4}H@-T2&lXLxv(=knsjbr#X@X}PUS&(Cy&C8&{M{i2SPnhO_M$q6VpW@TN@_|) znK8eRiinEa&kx=D`IjC$>RQ&%L}ZTo#6Y%st>zC!q_b;h7nK6}62-iRs-|A|yUR0E z)m~bvl7(&06_L_?w>#XQvAZfc)=j!^^C}`+NU$t-5#UJp+kbSS1Q^Oo_;e-`e zLY`^yi>9s+kHnnRZ%mxZ0_X4vs-r(m;uTO-wRe=?@7fka%o-0bzCI|CZCXxh>wFqD z7zS}|b7CiqHyO1)+xa~NF~}e$FY&H`Ns{|)B&(j8nIM}%S9;0Q`@hv@CDKrn+iRM; zJ0cTv{rb5RYqaZHiGj2QWlHp``@DAYWH0T^1Ok3Xp~wzPlgN{2X2 zhSRDRJL=XvQx_8UB&fjc(`}yJo*H~rIl+nPVCCYnR?c)XNb**BTx{b)d>UV4{@Y1% zvj9a!IE;Z|<7zW8=)^dhGiT1|R4U}XxYH%FRwK*I$|LzMQEhB&%wo%S_)TD2MFfMs z<5G!PwcE$cpVqDp^n~aHAsUzpbV>~;1%+g^Ap92=^9%u#d_%MeaRS%?L|7D5Q2K5= z+S@G2sN4P8_Q)^M@|*MH&_`=6#Q%KcGNl;mvU3E_pOyz`^-zq3#!voyWFPwfclZA= b<~p~*d~8Ygug_={{L?;zKb?Qd-249kMeX?+ literal 0 HcmV?d00001 diff --git a/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx b/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx index d53b6df..6de4f6f 100644 --- a/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx +++ b/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx @@ -1,58 +1,105 @@ -import React, { createContext, useEffect, useState, useRef } from 'react' -import Keycloak from 'keycloak-js' +import React, { createContext, useEffect, useRef, useState } from 'react'; +import Keycloak from 'keycloak-js'; +import { useOnlineStatus } from '../../../hooks/useOnlineStatus'; + +const STORAGE_KEYS = { + token: 'kcToken', + refreshToken: 'kcRefreshToken', + tokenParsed: 'kcTokenParsed', +}; + +const saveTokens = (kc: Keycloak) => { + if (kc.token) localStorage.setItem(STORAGE_KEYS.token, kc.token); + if (kc.refreshToken) localStorage.setItem(STORAGE_KEYS.refreshToken, kc.refreshToken); + if (kc.tokenParsed) localStorage.setItem(STORAGE_KEYS.tokenParsed, JSON.stringify(kc.tokenParsed)); +}; + +const loadStoredTokens = () => ({ + token: localStorage.getItem(STORAGE_KEYS.token), + refreshToken: localStorage.getItem(STORAGE_KEYS.refreshToken), + tokenParsed: localStorage.getItem(STORAGE_KEYS.tokenParsed), +}); + +const createKeycloak = () => + new Keycloak({ + url: import.meta.env.VITE_KEYCLOAK_URL, + realm: import.meta.env.VITE_KEYCLOAK_REALM, + clientId: import.meta.env.VITE_KEYCLOAK_CLIENT, + }); + +const restoreOfflineSession = (keycloak: Keycloak, setAuthenticated: (v: boolean) => void) => { + const { token, refreshToken, tokenParsed } = loadStoredTokens(); + + if (!token || !refreshToken) return; + + keycloak.token = token; + keycloak.refreshToken = refreshToken; + keycloak.tokenParsed = tokenParsed ? JSON.parse(tokenParsed) : undefined; + keycloak.realmAccess = { roles: keycloak.tokenParsed?.realm_access?.roles || [] } + + setAuthenticated(true); +}; + +const initOnline = async (keycloak: Keycloak, setAuthenticated: (v: boolean) => void) => { + const authenticated = await keycloak.init({ onLoad: 'check-sso', checkLoginIframe: false, pkceMethod: 'S256' }); + setAuthenticated(authenticated); + saveTokens(keycloak); +}; + +const logout = (keycloak: Keycloak, redirectUri: string) => { + localStorage.removeItem(STORAGE_KEYS.token); + localStorage.removeItem(STORAGE_KEYS.refreshToken); + localStorage.removeItem(STORAGE_KEYS.tokenParsed); + keycloak.logout({ redirectUri: redirectUri }) +}; interface KeycloakContextProps { keycloak: Keycloak | null; authenticated: boolean; + logout: (keycloak: Keycloak, redirectUri: string) => void; } -const KeycloakContext = createContext(undefined); - interface KeycloakProviderProps { - children: React.ReactNode + children: React.ReactNode; } -const KeycloakProvider: React.FC = ({ children }) => { - const isRun = useRef(false); +export const KeycloakContext = createContext(undefined); + +export const KeycloakProvider: React.FC = ({ children }) => { + const online = useOnlineStatus(); + const initialized = useRef(false); + const [keycloak, setKeycloak] = useState(null); - const [authenticated, setAuthenticated] = useState(false); + const [authenticated, setAuthenticated] = useState(false); useEffect(() => { - if (isRun.current) return; - isRun.current = true; - - const initKeycloak = async () => { - const keycloackConfig = { - url: import.meta.env.VITE_KEYCLOAK_URL as string, - realm: import.meta.env.VITE_KEYCLOAK_REALM as string, - clientId: import.meta.env.VITE_KEYCLOAK_CLIENT as string - }; - const keycloakInstance: Keycloak = new Keycloak(keycloackConfig); - - keycloakInstance - .init({ onLoad: 'check-sso' }) - .then((authenticated: boolean) => { - setAuthenticated(authenticated); - localStorage.setItem('token', keycloakInstance.token || ''); - }) - .catch((error) => { - console.error('Keycloak initialization failed:', error); - setAuthenticated(false); - }) - .finally(() => { - setKeycloak(keycloakInstance); - console.log('Keycloak instance object', keycloakInstance); - }); - }; - - initKeycloak(); + if (initialized.current) return; + initialized.current = true; + + const keycloak = createKeycloak(); + + restoreOfflineSession(keycloak, setAuthenticated); + + if (navigator.onLine) { + initOnline(keycloak, setAuthenticated) + .catch(() => setAuthenticated(false)); + } + + setKeycloak(keycloak); }, []); + useEffect(() => { + if (!keycloak || !online) return; + + console.log(online); + + initOnline(keycloak, setAuthenticated) + .catch(() => setAuthenticated(false)); + }, [online]); + return ( - + {children} ); }; - -export { KeycloakProvider, KeycloakContext }; \ No newline at end of file diff --git a/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts b/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts index a027da2..9711c16 100644 --- a/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts +++ b/wiarygodnik_frontend/src/features/auth/hooks/useKeycloakProfile.ts @@ -1,18 +1,21 @@ import { useEffect, useState } from 'react' import type Keycloak from 'keycloak-js' import type { KeycloakProfile } from 'keycloak-js' +import { useOnlineStatus } from '../../../hooks/useOnlineStatus'; export function useKeycloakProfile(keycloak: Keycloak | null, authenticated: boolean) { + const online = useOnlineStatus() + const [profile, setProfile] = useState(null); useEffect(() => { if (!keycloak || !authenticated) return; - + keycloak .loadUserProfile() .then(setProfile); - }, [keycloak, authenticated]) + }, [keycloak, authenticated, online]) return profile; } diff --git a/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx b/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx index 510e00b..4bec173 100644 --- a/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ContentComparisonPart.tsx @@ -1,6 +1,6 @@ import { Box, Typography, Link } from "@mui/material"; import type { ContentComparison } from "../api/analysis.api"; -import { getDomain } from "../../../lib/domainExtractor"; +import { getDomain } from "../lib/domainExtractor"; interface ContentComparisonPartProps { contentComparison: ContentComparison; diff --git a/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx index 3628d40..b50058a 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportContent.tsx @@ -4,7 +4,7 @@ import useMediaQuery from "@mui/material/useMediaQuery"; import LightbulbIcon from '@mui/icons-material/Lightbulb'; import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'; import CircleIcon from '@mui/icons-material/Circle'; -import { getDomain } from "../../../lib/domainExtractor.ts"; +import { getDomain } from "../lib/domainExtractor.ts"; import { sourceDot, sourceLink } from "../../../Style.tsx"; import type { ReportContentResponse } from "../api/report.api.ts"; import { ReportCredability } from "./ReportCredability.tsx"; diff --git a/wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx b/wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx index 0bdf7bd..e00a9f1 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportSearch.tsx @@ -4,8 +4,11 @@ import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined'; import { useState } from "react"; import { useNavigate } from "react-router-dom"; import { useAnalyseSource } from "../hooks/useAnalyseSource.ts"; +import { useOnlineStatus } from "../../../hooks/useOnlineStatus.ts"; +import { enqueueSnackbar } from "notistack"; export const ReportSearch = () => { + const online = useOnlineStatus() const navigate = useNavigate(); const { startAnalysis } = useAnalyseSource(); @@ -14,8 +17,16 @@ export const ReportSearch = () => { const handleSearch = async () => { navigator.vibrate?.(200); - const requestId = await startAnalysis(sourceUrl); - navigate(`/reports/${requestId}`); + try { + const requestId = await startAnalysis(sourceUrl); + navigate(`/reports/${requestId}`); + } catch (e) { + if (!online) { + enqueueSnackbar("Brak połączenia z internetem. Analiza zostanie rozpoczęta automatycznie po przywróceniu połączenia.", { variant: 'success' }); + return; + } + return; + } }; return ( diff --git a/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts b/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts index 6eae283..b7c7677 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useAnalysis.ts @@ -1,8 +1,11 @@ import { useEffect, useState } from 'react'; import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; import { useAnalysisApi, type AnalysisData } from '../api/analysis.api.ts'; +import { useOnlineStatus } from '../../../hooks/useOnlineStatus.ts'; export const useAnalysis = (requestId: string | undefined, status: string | undefined) => { + const online = useOnlineStatus() + const { getMyAnalysis } = useAnalysisApi(); const [analysis, setAnalysis] = useState(undefined); @@ -14,7 +17,7 @@ export const useAnalysis = (requestId: string | undefined, status: string | unde } getMyAnalysis(requestId).then(setAnalysis); - }, [requestId, status]); + }, [requestId, status, online]); return analysis; }; diff --git a/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts b/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts index 967441c..9c61d5a 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useAnalysisStatus.ts @@ -2,8 +2,11 @@ import { useEffect, useState } from 'react'; import { useAnalysisApi, type AnalysisStatusResponse } from '../api/analysis.api'; import { useReportApi, type ReportStatusResponse } from '../api/report.api'; import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; +import { useOnlineStatus } from '../../../hooks/useOnlineStatus.ts'; export const useAnalysisStatus = (requestId: string | undefined) => { + const online = useOnlineStatus() + const { getMyAnalysisStatus } = useAnalysisApi(); const { getMyReportStatus } = useReportApi(); @@ -58,7 +61,7 @@ export const useAnalysisStatus = (requestId: string | undefined) => { return () => { active = false; }; - }, [requestId]); + }, [requestId, online]); return status; }; diff --git a/wiarygodnik_frontend/src/features/report/hooks/useReport.ts b/wiarygodnik_frontend/src/features/report/hooks/useReport.ts index d17278f..16fca5e 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useReport.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useReport.ts @@ -1,8 +1,11 @@ import { useEffect, useState } from 'react'; import { useReportApi, type ReportContentResponse } from '../api/report.api'; import { AnalysisStatus } from "../domain/AnalysisStatus.ts"; +import { useOnlineStatus } from '../../../hooks/useOnlineStatus.ts'; export const useReport = (requestId: string | undefined, status: string | undefined) => { + const online = useOnlineStatus() + const { getMyReport } = useReportApi(); const [report, setReport] = useState(undefined); @@ -14,7 +17,7 @@ export const useReport = (requestId: string | undefined, status: string | undefi } getMyReport(requestId).then(setReport); - }, [requestId, status]); + }, [requestId, status, online]); return report; }; diff --git a/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts index 9cca08e..f6ecd8a 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts @@ -1,7 +1,10 @@ import { useEffect, useState } from 'react'; import { useReportApi, type ReportListItemResponse } from '../api/report.api'; +import { useOnlineStatus } from '../../../hooks/useOnlineStatus'; export const useReportsList = (reload: boolean | undefined) => { + const online = useOnlineStatus() + const { getAllMyReports } = useReportApi(); const [reports, setReports] = useState([]); @@ -11,7 +14,7 @@ export const useReportsList = (reload: boolean | undefined) => { getAllMyReports() .then(setReports) .finally(() => setLoading(false)); - }, [reload]); + }, [reload, online]); return { reports, loading }; }; diff --git a/wiarygodnik_frontend/src/lib/domainExtractor.ts b/wiarygodnik_frontend/src/features/report/lib/domainExtractor.ts similarity index 100% rename from wiarygodnik_frontend/src/lib/domainExtractor.ts rename to wiarygodnik_frontend/src/features/report/lib/domainExtractor.ts diff --git a/wiarygodnik_frontend/src/hooks/useOnlineStatus.ts b/wiarygodnik_frontend/src/hooks/useOnlineStatus.ts new file mode 100644 index 0000000..bb6b0a5 --- /dev/null +++ b/wiarygodnik_frontend/src/hooks/useOnlineStatus.ts @@ -0,0 +1,20 @@ +import { useEffect, useState } from 'react' + +export function useOnlineStatus() { + const [online, setOnline] = useState(navigator.onLine) + + useEffect(() => { + const onOnline = () => setOnline(true) + const onOffline = () => setOnline(false) + + window.addEventListener('online', onOnline) + window.addEventListener('offline', onOffline) + + return () => { + window.removeEventListener('online', onOnline) + window.removeEventListener('offline', onOffline) + } + }, []) + + return online +} diff --git a/wiarygodnik_frontend/src/main.tsx b/wiarygodnik_frontend/src/main.tsx index aa964c0..65aad94 100644 --- a/wiarygodnik_frontend/src/main.tsx +++ b/wiarygodnik_frontend/src/main.tsx @@ -3,8 +3,10 @@ import App from './App' import { CssBaseline, ThemeProvider } from "@mui/material"; import theme from "./theme.ts"; import "./index.css" -import * as serviceWorkerRegistration from './serviceWorkerRegistration'; import { StrictMode } from 'react'; +import { registerSW } from 'virtual:pwa-register' + +registerSW({ immediate: true }) ReactDOM.createRoot(document.getElementById('root')!) .render( @@ -15,5 +17,3 @@ ReactDOM.createRoot(document.getElementById('root')!) ); - -serviceWorkerRegistration.register(); diff --git a/wiarygodnik_frontend/src/pages/ConnectionRequired.tsx b/wiarygodnik_frontend/src/pages/ConnectionRequired.tsx new file mode 100644 index 0000000..7d1643f --- /dev/null +++ b/wiarygodnik_frontend/src/pages/ConnectionRequired.tsx @@ -0,0 +1,34 @@ +import { Box, Container, Typography } from "@mui/material"; +import NavBar from "../layout/NavBar"; + +export default function AccessDenied() { + return ( + + + + + Brak połączenia z internetem + + + Aby się zalogować, wymagane jest aktywne połączenie z internetem. + Po zalogowaniu możesz korzystać z aplikacji również w trybie offline. + + + + ); +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/pages/User.tsx b/wiarygodnik_frontend/src/pages/User.tsx index dc02a14..84da78f 100644 --- a/wiarygodnik_frontend/src/pages/User.tsx +++ b/wiarygodnik_frontend/src/pages/User.tsx @@ -1,20 +1,28 @@ -import { Box, Button, Container, Divider, Typography } from "@mui/material"; +import { Box, Button, Container, Divider, Tooltip, Typography } from "@mui/material"; import NavBar from "../layout/NavBar.tsx"; import PersonIcon from '@mui/icons-material/Person'; import theme from "../theme.ts"; import LogoutIcon from '@mui/icons-material/Logout'; import { userPageButton, userPageButtonIcon, userPageButtonText, userPageDivider } from "../Style.tsx"; -import InfoIcon from '@mui/icons-material/Info'; import SettingsIcon from '@mui/icons-material/Settings'; import useKeycloak from "../features/auth/hooks/useKeycloak.ts"; -import { useKeycloakProfile } from "../features/auth/hooks/useKeycloakProfile.ts"; function User() { - const { keycloak, authenticated } = useKeycloak(); - const profile = useKeycloakProfile(keycloak, authenticated); + const isOffline = !navigator.onLine; - const handleSettings = () => keycloak?.accountManagement(); - const handleLogout = () => keycloak?.logout({ redirectUri: window.location.origin }); + const { keycloak, logout } = useKeycloak(); + + const handleSettings = () => { + if (!isOffline) { + keycloak?.accountManagement(); + } + }; + + const handleLogout = () => { + if (keycloak) { + logout(keycloak, window.location.origin ); + } + } return ( @@ -23,22 +31,20 @@ function User() { - {profile?.firstName} {profile?.lastName} + {keycloak?.tokenParsed?.name} - - + + + + + ) +} \ No newline at end of file diff --git a/wiarygodnik_frontend/src/features/notification/hooks/usePushNotifications.ts b/wiarygodnik_frontend/src/features/notification/hooks/usePushNotifications.ts new file mode 100644 index 0000000..2fd6167 --- /dev/null +++ b/wiarygodnik_frontend/src/features/notification/hooks/usePushNotifications.ts @@ -0,0 +1,61 @@ +import { useCallback } from 'react'; +import { usePushApi } from '../api/push.api'; + +const VAPID_PUBLIC_KEY = import.meta.env.VITE_VAPID_PUBLIC_KEY; + +function urlBase64ToUint8Array(base64String: string) { + const padding = '='.repeat((4 - (base64String.length % 4)) % 4); + const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/'); + const rawData = atob(base64); + return new Uint8Array(rawData.length).map((_, i) => rawData.charCodeAt(i)); +} + +export const usePushNotifications = () => { + const { postSubscribe } = usePushApi(); + + const askPermission = useCallback(async () => { + if (!('Notification' in window)) { + throw new Error('Notifications not supported'); + } + + const permission = await Notification.requestPermission(); + if (permission !== 'granted') { + throw new Error('Permission denied'); + } + + return permission; + }, []) + + const subscribe = useCallback(async (): Promise => { + if (!('serviceWorker' in navigator)) return null; + if (!('PushManager' in window)) return null; + + const registration = await navigator.serviceWorker.ready; + + let subscription = await registration.pushManager.getSubscription(); + if (subscription) return subscription; + + await askPermission(); + + subscription = await registration.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY) + }); + + await postSubscribe(subscription); + + return subscription; + }, [askPermission]) + + const isSubscribed = useCallback(async (): Promise => { + if (!('serviceWorker' in navigator)) return false + if (!('PushManager' in window)) return false + + const registration = await navigator.serviceWorker.ready + const subscription = await registration.pushManager.getSubscription() + + return subscription !== null + }, []) + + return { askPermission, subscribe, isSubscribed } +} diff --git a/wiarygodnik_frontend/src/layout/NavBar.tsx b/wiarygodnik_frontend/src/layout/NavBar.tsx index 77b5d71..97a482b 100644 --- a/wiarygodnik_frontend/src/layout/NavBar.tsx +++ b/wiarygodnik_frontend/src/layout/NavBar.tsx @@ -17,6 +17,7 @@ function NavBar(props: NavBarProps) { const isMobile = useIsMobile(); const navigate = useNavigate(); const location = useLocation(); + const { authenticated } = useKeycloak(); function handleHome() { @@ -45,7 +46,7 @@ function NavBar(props: NavBarProps) { alignItems: "center", px: isMobile ? 0 : 4 }}> - + {authenticated ? location.pathname.startsWith("/reports") ? ( @@ -73,7 +74,7 @@ function NavBar(props: NavBarProps) { - + {authenticated && location.pathname !== "/user" ? ( + + + + + + ); } \ No newline at end of file diff --git a/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts b/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts new file mode 100644 index 0000000..4146441 --- /dev/null +++ b/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts @@ -0,0 +1,17 @@ +import { useCallback } from "react"; +import { useReportApi } from "../api/report.api"; + +export const useDeleteReport = () => { + const { deleteMyReport } = useReportApi(); + + const deleteReport = useCallback(async (requestId: string) => { + try { + await deleteMyReport(requestId); + return true; + } catch (err: any) { + return false; + } + }, []); + + return { deleteReport }; +}; diff --git a/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts index f6ecd8a..62f4315 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useReportList.ts @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react'; import { useReportApi, type ReportListItemResponse } from '../api/report.api'; import { useOnlineStatus } from '../../../hooks/useOnlineStatus'; -export const useReportsList = (reload: boolean | undefined) => { +export const useReportsList = (recentlyDeletedReqId?: string, requestId?: string) => { const online = useOnlineStatus() const { getAllMyReports } = useReportApi(); @@ -14,7 +14,7 @@ export const useReportsList = (reload: boolean | undefined) => { getAllMyReports() .then(setReports) .finally(() => setLoading(false)); - }, [reload, online]); + }, [requestId, recentlyDeletedReqId, online]); return { reports, loading }; }; diff --git a/wiarygodnik_frontend/src/pages/Reports.tsx b/wiarygodnik_frontend/src/pages/Reports.tsx index 7900bf9..7e72734 100644 --- a/wiarygodnik_frontend/src/pages/Reports.tsx +++ b/wiarygodnik_frontend/src/pages/Reports.tsx @@ -12,6 +12,7 @@ import { ReportLoading } from "../features/report/components/ReportLoading.tsx"; import { enqueueSnackbar } from "notistack"; import { AnalysisStatus } from "../features/report/domain/AnalysisStatus.ts"; import { useAnalysis } from "../features/report/hooks/useAnalysis.ts"; +import { clearUnreadNotifications } from "../features/push/lib/badging-db.ts"; function Reports() { const isMobile = useIsMobile(); @@ -31,11 +32,20 @@ function Reports() { } }, [status]); + useEffect(() => { + const markAllAsRead = async () => { + await clearUnreadNotifications(); + navigator.clearAppBadge(); + }; + + markAllAsRead(); + }, [report]); + return ( <> - {menuActive && } + {menuActive && } {report && analysis ? : status ? : } diff --git a/wiarygodnik_frontend/src/pages/User.tsx b/wiarygodnik_frontend/src/pages/User.tsx index f6f601f..1580a95 100644 --- a/wiarygodnik_frontend/src/pages/User.tsx +++ b/wiarygodnik_frontend/src/pages/User.tsx @@ -6,7 +6,7 @@ import LogoutIcon from '@mui/icons-material/Logout'; import { userPageButton, userPageButtonIcon, userPageButtonText, userPageDivider } from "../Style.tsx"; import SettingsIcon from '@mui/icons-material/Settings'; import useKeycloak from "../features/auth/hooks/useKeycloak.ts"; -import { PushNotificationButton } from "../features/notification/components/PushNotificationButton.tsx"; +import { PushNotificationButton } from "../features/push/components/PushNotificationButton.tsx"; function User() { const isOffline = !navigator.onLine; diff --git a/wiarygodnik_frontend/src/sw.ts b/wiarygodnik_frontend/src/sw.ts index 8258e25..1425268 100644 --- a/wiarygodnik_frontend/src/sw.ts +++ b/wiarygodnik_frontend/src/sw.ts @@ -6,6 +6,7 @@ import { ExpirationPlugin } from 'workbox-expiration'; import { CacheableResponsePlugin } from 'workbox-cacheable-response'; import { precacheAndRoute } from 'workbox-precaching'; import { clientsClaim } from 'workbox-core' +import { incrementUnreadNotifications, decrementUnreadNotifications } from './features/push/lib/badging-db'; declare let self: ServiceWorkerGlobalScope; @@ -35,10 +36,10 @@ registerRoute( ); registerRoute( - ({ url }) => url.pathname.startsWith('/api'), + ({ url }) => url.pathname === '/api/analysis/process', new NetworkOnly({ plugins: [ - new BackgroundSyncPlugin('backgroundSyncQueue', { + new BackgroundSyncPlugin('analysisProcessBackgroundSyncQueue', { maxRetentionTime: 24 * 60 }) ] @@ -46,6 +47,18 @@ registerRoute( 'POST' ); +registerRoute( + ({ url }) => /^\/api\/report\/.+$/.test(url.pathname), + new NetworkOnly({ + plugins: [ + new BackgroundSyncPlugin('deleteReportBackgroundSyncQueue', { + maxRetentionTime: 24 * 60 + }) + ] + }), + 'DELETE' +); + self.addEventListener('push', (event: PushEvent) => { if (!event.data) return; @@ -53,14 +66,21 @@ self.addEventListener('push', (event: PushEvent) => { const data = event.data.json(); event.waitUntil( - self.registration.showNotification(data.title, { - body: data.body, - icon: '/web-app-manifest-192x192.png', - badge: '/web-app-manifest-192x192.png', - data: { - url: data.url - } - }) + (async () => { + await incrementUnreadNotifications(); + + self.registration.showNotification(data.title, { + body: data.body, + icon: '/web-app-manifest-192x192.png', + badge: '/web-app-manifest-192x192.png', + data: { + url: data.url + } + }) + + const allClients = await self.clients.matchAll(); + allClients.forEach(client => client.postMessage({ type: 'SYNC_BADGE' })); + })() ); }) @@ -68,6 +88,11 @@ self.addEventListener('notificationclick', (event: NotificationEvent) => { event.notification.close(); event.waitUntil( - self.clients.openWindow(event.notification.data.url) + (async () => { + await decrementUnreadNotifications(); + + self.clients.openWindow(event.notification.data.url) + .then(client => client?.postMessage({ type: 'SYNC_BADGE' })) + })() ); }) From f23728f37f862f2b9cfdb355164f0e8f95b56876 Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Tue, 6 Jan 2026 16:37:15 +0100 Subject: [PATCH 12/15] Add delete event for analysis after report deletion --- .../wiarygodnik/cas/amqp/RabbitMqConfig.kt | 14 +++++++++++++ .../wiarygodnik/cas/amqp/RabbitMqConsumer.kt | 21 +++++++++++++++++++ .../wiarygodnik/cas/amqp/RabbitMqProducer.kt | 6 +++--- .../{dto => message}/AnalysisResultMessage.kt | 5 ++++- .../model/message/DeleteAnalysisMessage.kt | 3 +++ .../cas/service/AnalysisProcessor.kt | 2 +- .../cas/service/AnalysisService.kt | 4 ++++ .../wiarygodnik/rgs/amqp/RabbitMqConfig.kt | 14 +++++++++++++ .../wiarygodnik/rgs/amqp/RabbitMqConsumer.kt | 2 +- .../wiarygodnik/rgs/amqp/RabbitMqProducer.kt | 20 ++++++++++++++++++ .../p/lodz/wiarygodnik/rgs/model/Report.kt | 3 +-- .../{dto => message}/AnalysisResultMessage.kt | 2 +- .../model/message/DeleteAnalysisMessage.kt | 3 +++ .../rgs/service/AiAnalysisReportGenerator.kt | 2 +- .../wiarygodnik/rgs/service/ReportService.kt | 8 +++++-- 15 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConsumer.kt rename content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/{dto => message}/AnalysisResultMessage.kt (52%) create mode 100644 content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/DeleteAnalysisMessage.kt create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqProducer.kt rename report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/{dto => message}/AnalysisResultMessage.kt (94%) create mode 100644 report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/DeleteAnalysisMessage.kt diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConfig.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConfig.kt index a06ccb2..d78065a 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConfig.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConfig.kt @@ -17,8 +17,12 @@ class RabbitMQConfig { companion object { const val EXCHANGE_NAME: String = "wiarygodnik.exchange" + const val ANALYSIS_RESULTS_QUEUE: String = "content-analysis-service.results.queue" const val ANALYSIS_ROUTING_KEY: String = "analysis.key" + + const val DELETE_ANALYSIS_QUEUE: String = "report-generation-service.delete.queue" + const val DELETE_ANALYSIS_ROUTING_KEY: String = "delete-analysis.key" } @Bean @@ -36,6 +40,16 @@ class RabbitMQConfig { return BindingBuilder.bind(analysisResultsQueue()).to(exchange()).with(ANALYSIS_ROUTING_KEY) } + @Bean + fun deleteAnalysisQueue(): Queue { + return Queue(DELETE_ANALYSIS_QUEUE) + } + + @Bean + fun deleteAnalysisBinding(): Binding { + return BindingBuilder.bind(deleteAnalysisQueue()).to(exchange()).with(DELETE_ANALYSIS_ROUTING_KEY) + } + @Bean fun jsonMessageConverter(): MessageConverter { return Jackson2JsonMessageConverter() diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConsumer.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConsumer.kt new file mode 100644 index 0000000..6cd335b --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqConsumer.kt @@ -0,0 +1,21 @@ +package pl.edu.p.lodz.wiarygodnik.cas.amqp + +import io.github.oshai.kotlinlogging.KotlinLogging +import org.springframework.amqp.rabbit.annotation.RabbitListener +import org.springframework.stereotype.Component +import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQConfig.Companion.DELETE_ANALYSIS_QUEUE +import pl.edu.p.lodz.wiarygodnik.cas.model.message.DeleteAnalysisMessage +import pl.edu.p.lodz.wiarygodnik.cas.service.AnalysisService + +@Component +class RabbitMQConsumer(private val analysisService: AnalysisService) { + + private val log = KotlinLogging.logger {} + + @RabbitListener(queues = [DELETE_ANALYSIS_QUEUE]) + fun contentAnalysisServiceResultsQueue(message: DeleteAnalysisMessage) { + log.info { "Received message: $message" } + analysisService.deleteAnalysis(message.requestId) + } + +} \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt index ff0d3cd..03929c1 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/amqp/RabbitMqProducer.kt @@ -2,12 +2,12 @@ package pl.edu.p.lodz.wiarygodnik.cas.amqp import io.github.oshai.kotlinlogging.KotlinLogging import org.springframework.amqp.rabbit.core.RabbitTemplate -import org.springframework.stereotype.Service +import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQConfig.Companion.ANALYSIS_ROUTING_KEY import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQConfig.Companion.EXCHANGE_NAME -import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisResultMessage +import pl.edu.p.lodz.wiarygodnik.cas.model.message.AnalysisResultMessage -@Service +@Component class RabbitMQProducer(val rabbitTemplate: RabbitTemplate) { private val log = KotlinLogging.logger {} diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/AnalysisResultMessage.kt similarity index 52% rename from content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt rename to content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/AnalysisResultMessage.kt index 90f91f9..79610e7 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/dto/AnalysisResultMessage.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/AnalysisResultMessage.kt @@ -1,4 +1,7 @@ -package pl.edu.p.lodz.wiarygodnik.cas.model.dto +package pl.edu.p.lodz.wiarygodnik.cas.model.message + +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis +import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentComparison data class AnalysisResultMessage( val requestId: String, diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/DeleteAnalysisMessage.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/DeleteAnalysisMessage.kt new file mode 100644 index 0000000..cf4dcf1 --- /dev/null +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/message/DeleteAnalysisMessage.kt @@ -0,0 +1,3 @@ +package pl.edu.p.lodz.wiarygodnik.cas.model.message + +data class DeleteAnalysisMessage(val requestId: String) \ No newline at end of file diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt index b4a1b61..b22ecfe 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisProcessor.kt @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.cas.amqp.RabbitMQProducer import pl.edu.p.lodz.wiarygodnik.cas.model.Analysis import pl.edu.p.lodz.wiarygodnik.cas.model.AnalysisStatus.* -import pl.edu.p.lodz.wiarygodnik.cas.model.dto.AnalysisResultMessage +import pl.edu.p.lodz.wiarygodnik.cas.model.message.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentAnalysis import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ContentComparison import pl.edu.p.lodz.wiarygodnik.cas.model.dto.ScrapedWebContent diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt index 9ff0b4b..3042465 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/AnalysisService.kt @@ -44,4 +44,8 @@ class AnalysisService(private val analysisRepository: AnalysisRepository) { analysisRepository.save(analysis) } + fun deleteAnalysis(requestId: String) { + analysisRepository.findAnalysisByRequestId(requestId)?.let { analysisRepository.delete(it) } + } + } \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConfig.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConfig.kt index 7ab84e5..3052724 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConfig.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConfig.kt @@ -17,8 +17,12 @@ class RabbitMQConfig { companion object { const val EXCHANGE_NAME: String = "wiarygodnik.exchange" + const val ANALYSIS_RESULTS_QUEUE: String = "content-analysis-service.results.queue" const val ANALYSIS_ROUTING_KEY: String = "analysis.key" + + const val DELETE_ANALYSIS_QUEUE: String = "report-generation-service.delete.queue" + const val DELETE_ANALYSIS_ROUTING_KEY: String = "delete-analysis.key" } @Bean @@ -36,6 +40,16 @@ class RabbitMQConfig { return BindingBuilder.bind(contentAnalysisServiceResultsQueue()).to(exchange()).with(ANALYSIS_ROUTING_KEY) } + @Bean + fun deleteAnalysisQueue(): Queue { + return Queue(DELETE_ANALYSIS_QUEUE) + } + + @Bean + fun deleteAnalysisBinding(): Binding { + return BindingBuilder.bind(deleteAnalysisQueue()).to(exchange()).with(DELETE_ANALYSIS_ROUTING_KEY) + } + @Bean fun jsonMessageConverter(): MessageConverter { return Jackson2JsonMessageConverter() diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt index 09f308a..ca3be6f 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqConsumer.kt @@ -5,7 +5,7 @@ import org.springframework.amqp.rabbit.annotation.RabbitListener import org.springframework.stereotype.Component import pl.edu.p.lodz.wiarygodnik.rgs.amqp.RabbitMQConfig.Companion.ANALYSIS_RESULTS_QUEUE import pl.edu.p.lodz.wiarygodnik.rgs.model.Report -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.service.ReportService @Component diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqProducer.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqProducer.kt new file mode 100644 index 0000000..fb735b5 --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/amqp/RabbitMqProducer.kt @@ -0,0 +1,20 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.amqp + +import io.github.oshai.kotlinlogging.KotlinLogging +import org.springframework.amqp.rabbit.core.RabbitTemplate +import org.springframework.stereotype.Component +import pl.edu.p.lodz.wiarygodnik.rgs.amqp.RabbitMQConfig.Companion.DELETE_ANALYSIS_ROUTING_KEY +import pl.edu.p.lodz.wiarygodnik.rgs.amqp.RabbitMQConfig.Companion.EXCHANGE_NAME +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.DeleteAnalysisMessage + +@Component +class RabbitMQProducer(val rabbitTemplate: RabbitTemplate) { + + private val log = KotlinLogging.logger {} + + fun sendDeleteEvent(message: DeleteAnalysisMessage) { + rabbitTemplate.convertAndSend(EXCHANGE_NAME, DELETE_ANALYSIS_ROUTING_KEY, message) + log.info { "Sent analysis: $message" } + } + +} \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt index e35dde1..8f1a40e 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/Report.kt @@ -1,8 +1,7 @@ package pl.edu.p.lodz.wiarygodnik.rgs.model import jakarta.persistence.* -import jakarta.persistence.GenerationType.IDENTITY -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult enum class ReportStatus { diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResultMessage.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/AnalysisResultMessage.kt similarity index 94% rename from report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResultMessage.kt rename to report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/AnalysisResultMessage.kt index 45da968..f8fa2d9 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/dto/AnalysisResultMessage.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/AnalysisResultMessage.kt @@ -1,4 +1,4 @@ -package pl.edu.p.lodz.wiarygodnik.rgs.model.dto +package pl.edu.p.lodz.wiarygodnik.rgs.model.message enum class Sentiment { NEUTRAL, POSITIVE, NEGATIVE, ALARMIST, IRONIC, PERSUASIVE, AGGRESSIVE, FORMAL diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/DeleteAnalysisMessage.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/DeleteAnalysisMessage.kt new file mode 100644 index 0000000..8fe159c --- /dev/null +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/model/message/DeleteAnalysisMessage.kt @@ -0,0 +1,3 @@ +package pl.edu.p.lodz.wiarygodnik.rgs.model.message + +data class DeleteAnalysisMessage(val requestId: String) \ No newline at end of file diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt index 0b28e71..4a13424 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt @@ -7,7 +7,7 @@ import org.springframework.core.io.ResourceLoader import org.springframework.retry.annotation.Backoff import org.springframework.retry.annotation.Retryable import org.springframework.stereotype.Component -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult @Component diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt index e6563ef..3c111d0 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/ReportService.kt @@ -5,12 +5,14 @@ import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Propagation.REQUIRES_NEW import org.springframework.transaction.annotation.Transactional +import pl.edu.p.lodz.wiarygodnik.rgs.amqp.RabbitMQProducer import pl.edu.p.lodz.wiarygodnik.rgs.model.Report import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.FAILED import pl.edu.p.lodz.wiarygodnik.rgs.model.ReportStatus.GENERATED -import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.AnalysisResultMessage +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.DeleteAnalysisMessage import pl.edu.p.lodz.wiarygodnik.rgs.repo.ReportRepository import pl.edu.p.lodz.wiarygodnik.rgs.security.PrincipalProvider import pl.edu.p.lodz.wiarygodnik.rgs.service.notifications.ReportGeneratedEvent @@ -19,7 +21,8 @@ import pl.edu.p.lodz.wiarygodnik.rgs.service.notifications.ReportGeneratedEvent class ReportService( private val analysisReportGenerator: AiAnalysisReportGenerator, private val reportRepository: ReportRepository, - private val eventPublisher: ApplicationEventPublisher + private val eventPublisher: ApplicationEventPublisher, + private val rabbitProducer: RabbitMQProducer, ) { private val log = KotlinLogging.logger {} @@ -69,6 +72,7 @@ class ReportService( fun deleteReport(requestId: String) { val currentUserId = PrincipalProvider.getCurrentUserId() reportRepository.findReportByRequestIdAndUserId(requestId, currentUserId)?.let { reportRepository.delete(it) } + rabbitProducer.sendDeleteEvent(DeleteAnalysisMessage(requestId)) } } \ No newline at end of file From a2b1b103aca9512aee55b5c6619c4e5a5c7919bd Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Thu, 22 Jan 2026 19:45:02 +0100 Subject: [PATCH 13/15] Fix KeycloakContext & add HTTPS to all services --- .../cas/security/SecurityConfig.kt | 1 + .../src/main/resources/application.yml | 12 +++++++--- .../main/resources/keystore/wiarygodnik.p12 | Bin 0 -> 2770 bytes docker-compose.yml | 5 ++++- keycloak/wiarygodnik.crt | 21 ++++++++++++++++++ keycloak/wiarygodnik.p12 | Bin 0 -> 2770 bytes .../rgs/security/SecurityConfig.kt | 1 + .../src/main/resources/application.yml | 12 +++++++--- .../main/resources/keystore/wiarygodnik.p12 | Bin 0 -> 2770 bytes wiarygodnik_frontend/.env.production | 5 ++++- .../features/auth/context/KeycloakContext.tsx | 6 ++--- 11 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 content-analysis-service/src/main/resources/keystore/wiarygodnik.p12 create mode 100644 keycloak/wiarygodnik.crt create mode 100644 keycloak/wiarygodnik.p12 create mode 100644 report-generation-service/src/main/resources/keystore/wiarygodnik.p12 diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/SecurityConfig.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/SecurityConfig.kt index 6fdf604..0572738 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/SecurityConfig.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/security/SecurityConfig.kt @@ -18,6 +18,7 @@ class SecurityConfig { cors { } csrf { disable() } authorizeHttpRequests { + authorize("/actuator/health", permitAll) authorize("/api/analysis/**", hasRole("USER")) } oauth2ResourceServer { diff --git a/content-analysis-service/src/main/resources/application.yml b/content-analysis-service/src/main/resources/application.yml index 1e9bc37..236f0b2 100644 --- a/content-analysis-service/src/main/resources/application.yml +++ b/content-analysis-service/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: oauth2: resource-server: jwt: - issuer-uri: http://localhost:8888/realms/wiarygodnik + issuer-uri: https://localhost:8888/realms/wiarygodnik rabbitmq: host: localhost @@ -44,14 +44,20 @@ spring: server: port: 8081 + ssl: + enabled: true + key-store: classpath:keystore/wiarygodnik.p12 + key-store-password: changeit + key-store-type: PKCS12 + key-alias: wiarygodnik cors: allowed-origins: - http://localhost:5173 - - http://localhost:4173 - - http://localhost - https://localhost:5173 + - http://localhost:4173 - https://localhost:4173 + - http://localhost - https://localhost allowed-methods: - GET diff --git a/content-analysis-service/src/main/resources/keystore/wiarygodnik.p12 b/content-analysis-service/src/main/resources/keystore/wiarygodnik.p12 new file mode 100644 index 0000000000000000000000000000000000000000..838e7297d66c9ed86a8d21869f317439e55da8a5 GIT binary patch literal 2770 zcma)8XEYm(`cEP;VsEu~Z3(s0QpKwjjZvd2s9CQWl-iL7C1}yA7*Va%tUX#3wO3-) zrqotCsm=92|9kqL`{~{f&w0*oJs*GPfnlISARrYC0}Y|3lffC{_85UQKq3a}3C2KO z&uJ$Z2GZ~!5~K)>fxJ4W^Uo)Tn*QG@1}G3j#6Wb;Nd(O8PXfXSvxTYu0~uhlU=BH} z5gyh>n`RcHU+f|h{->)cfC3QcA`1v83}c|C{r`&~ItTzJKuza}GX%O)fq^n$7QWvd zBDn%4qJ{B7s>fMzu3!w9(qyP+^CjYhSSjcHPK>Ai(RM@1k*?^VT?X(~>P^B^oX2}9 z!Nwim8tQAWcvD~cndv^iSBA=)Jft&1(0o2b-FqE-24$*>o~?eQE?0WGo+X^nbUifX zFut_qrligTZ%d7%sI}wT4WC4dzD0o{Ln8dPj=YqE;*i}z`M|u&WGnYvB4V)tw&hwN z-(QIA&yOxRP2zu#=v^&ExC|dW?p3PPk~yRGBl!FKb8**M6hlj=J+j4d7F&MkhZo38 zU!UKoD};|5HGRbAM%e5I#rPwy$2L>jWU!LoIvpBOUQo4rhrJn0U{-3utHeWvSptN5 z28Dj@x(kmnxmC{lp}fLaCxuH%+O$*b#qV;=A2lnG57(M`5<2f{Hkt-E()TT;w2@gI z2s8^=Dg0uX{&CHw#G_K1{D3uge|Wq7&lbq`jtlQiAp_sur%4l+tbkA!yO zc4uF776fHoGi&h?ol+5O1k!#UI?r1Tkg043DWJ&7Dah$aP6LKdum@2+Wvt1>6x>7`-5F+1q2)D64hOh@)^A%Izxv} zxcuXjbQxEpE&bmiwHXH~xMFMfFHJ&e^_eDd@2p-L^kdfx3I#QGjgRuuo|W}6XpfN& zF1Ka!uWr>_F$c?#5IbSjUmx9>oL>%+uOF6Zy)y->VnUy4U(vX*Qs>#Ch?#y@MD4L6 z7se&EKn3d)^BTpG(mdj_8HOIpkyO=at7u-zk0bl@cpUhZ*{C!)f6U9|{A{gVq9H-4 zjKyMl?R#Cpe@T3O6<5~0xJnnM|Dni@kjc8L`!3Ghy3kFazGdMw55lQIs7Ue02&I?d zaK-{;KB3tiP{o15{>rCN9qU1Baem9&6k8@cViw(1foLSpxWYt~5$}(( zjOy*nHkf_~7w75GsIkp2J)gYj%JAhi4TZr^oU$Lcc66`va_TwF+huv1Ic=wP-FB04 zXP(v?CqWfJxG1lG?ZPiLPaP2B}_D_SlS*JNie zDi}^pR#z!EOZjxI2Vx&5^5q=zJ)6NMAHom{wSi!JKR1p}koQ4iX@=%<+=&6#9rN0Y zU1uSldDA!!UI?AF*mzRUzI%eo{7E(lU3^z^c!1YQ3{rC0KG`%MuxAoFGTx4UpHIXo zf`VG-9)<)uK$l%~qX@qe#9~=v4#SMB=?lKMv^`jmiJ9+Neg2@b=U9D6@|XD@kMnTT zGTDAo>|V)|+9r@;x-@COr)6X^o7S`Y2pXSZDODdf79>rMd+>V##MYC>5bA5>$g* z_0gKp*VnS<+pxm5fuBSlIrHRwSIHj~#J~;TOJA>mWWv&}l-(z=nxhB_lEx`E{?91M za3h$+pSq;ufb$4)0qz4l0ZxDbKq$Z+;0tg8_?%-en8-giPB;gc&C=7`RT!?OssV?o zs;euhD8pbFaQ+_?4K)!1esWGFgMfhZ759$<{BMPQwwD>5Gr#!d8&b)p{5W4y*G%^9 z|5Df;Jok0#i2J$0$8SX1iwITG7%o$hTN!?G$n;kfi8AA!Xluh`P{yk~ z6EW;)vK72Y@@o89N3o^7ib`2G{5+~{(*Ns5!8ev1If){X9g=7OItdj})y_a2rv_ho z>gX*S$e(~?7E9g0k7NUhk*(eSgQf#&8$X+@D4c#v>^*(l3K;YzKI1ll7^SJz#Wip_ z^R;>ar%#Z(bm8KYJMFjGnpGn)6?-c8n-wJ8Ec5e~bim}SiUkKoUR-)YlO#D=@1x7F&W(NSj?)`dDwe7Tpz5)DW=UR0 zyYTD!NtH9DDvvEId7-<|J?8x)RFUQt9PvL_X>%LHb5=?PCo7cFmnfI-lXD)_wU~q zty!hrWPFK6+uxd@SMFi5H~iNBgR6pKyUVecEG9J2#~EQ)fgsj9ij>?b7=QmtI=Mij zzB3FfkIl8@IMi`?5qY9{)Gj|@8#I4IzWl>TOe{NXWO%ZYtw)|H#JTa-c8$3*(~A<8 zX>uvtiDZU=c?4=^PPw$U^cu0GB^(}qQR_AFbHRos z#>Mk|pL+xhU2>z7v8?eSy`3q35?~)uIS(#TuA;X_mMK={Qe_3-$kb^I&yD?r=(N0C z4dl9Tz*=j4M#W|!H4)glaKWi>6>gGap_k3AF1hQx<~b^1QZbLgpx2dI53>JeG4T9} z9#%zT9C?BGz{#;MlPfwAFp2UB*lM@%^-9w2=0>YW7v~Q;e>=UYjmO{dQh)6Dc)Ys3bg|TemGyfxGEl&Y3!@~ekrF^CAZoo zr+x>V8Y;@PeM6V27O7f8n`&}12n92N!C{Pl{yY#60ssqtxvI+GW)e+XikHf)oNl_8 tUCA~m=8c@&@+pxzMX%t%9NV{U{}w*+{=s=MK;iDdRMJi`TJrxY>0jZu|4IM= literal 0 HcmV?d00001 diff --git a/docker-compose.yml b/docker-compose.yml index 07276d3..9770922 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -117,7 +117,9 @@ services: KC_DB_PASSWORD: password KEYCLOAK_ADMIN: admin KC_BOOTSTRAP_ADMIN_PASSWORD: admin - KC_HTTP_PORT: 8888 + KC_HTTPS_PORT: 8888 + KC_HTTPS_KEY_STORE_FILE: /opt/keycloak/conf/wiarygodnik.p12 + KC_HTTPS_KEY_STORE_PASSWORD: changeit command: - start-dev - --import-realm @@ -125,6 +127,7 @@ services: - "8888:8888" volumes: - ./keycloak:/opt/keycloak/data/import/ + - ./keycloak/wiarygodnik.p12:/opt/keycloak/conf/wiarygodnik.p12:ro networks: - wiarygodnik depends_on: diff --git a/keycloak/wiarygodnik.crt b/keycloak/wiarygodnik.crt new file mode 100644 index 0000000..507ac40 --- /dev/null +++ b/keycloak/wiarygodnik.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDhDCCAmygAwIBAgIJAPL+OxxUrraoMA0GCSqGSIb3DQEBDAUAMF8xCzAJBgNV +BAYTAlBMMQ0wCwYDVQQHEwRMb2R6MRwwGgYDVQQKExNQb2xpdGVjaG5pa2EgTG9k +emthMQswCQYDVQQLEwJJVDEWMBQGA1UEAxMNMTkyLjE2OC40LjE4MzAeFw0yNjAx +MjIxODM0NDJaFw0zNjAxMjAxODM0NDJaMF8xCzAJBgNVBAYTAlBMMQ0wCwYDVQQH +EwRMb2R6MRwwGgYDVQQKExNQb2xpdGVjaG5pa2EgTG9kemthMQswCQYDVQQLEwJJ +VDEWMBQGA1UEAxMNMTkyLjE2OC40LjE4MzCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANgbmOm0uYZ7XkqQCkGHPSSDOYySHKACVhtHWlxDfdR1kJj3Bx1l +A8LhfhcLIZRmXDSrOPzCSbpGRQpexqZJFu4SKV+wOCmDP2RX8Xm0skwWgPeB6q69 +v7EeoF4Tqx/0TezD+EIm9i7bsqnqWsN+bVnasnUdpbid2+ZxMOnDsximxX9adgw0 +e9ebBSpTZPOrqiVY+CadMvkEEUIWVLEvg77ZwY3b09+VZgpXD3Fov4Ruu13rKsJ+ +JKxh7kxOUhAnuG9b404p8bYkOIABErO4QDQmxGl30kVsMRZ2U0UWk1cNSWJaJJsn +7bfRt8NtFi7zb3PaNZKTsXmZxdp/oH5v2/ECAwEAAaNDMEEwHQYDVR0OBBYEFCQN +n6bw8O7XvT9UIIuofsKNzMhPMCAGA1UdEQQZMBeHBMCoBLeCCWxvY2FsaG9zdIcE +fwAAATANBgkqhkiG9w0BAQwFAAOCAQEA1zG77Jxy5OevubhNMqDmyGM5cD8JC2qR +a1MXgK1GjvuFdziG1WTEPL3Tzx5rvVvBZlv0GayrzmnzHkTXnJ69buFw1N0Jp9yA +FSXx+wT3Fq/pL14DyaP1+SIVmZI9OjrwwMaRPJnIQYLTbEZcRcrNg1KvoT5mA4FO +fKEnE8osCYLRbC1E2ZnfitOGl8JY08xHY/mbPPmDumhREV+uZG7F2ySL6G7+4sDt +XB6IEjkjCioA9LqxD15Ilkri0mWsctczGIIFyVfbZWCSKtdurL0KGv2czBQeprV4 +OSPynbJkuSwMdo+58Zqu86jj5f3+QB9tBP+4yWpTVHraZ8vLdy/tsw== +-----END CERTIFICATE----- diff --git a/keycloak/wiarygodnik.p12 b/keycloak/wiarygodnik.p12 new file mode 100644 index 0000000000000000000000000000000000000000..838e7297d66c9ed86a8d21869f317439e55da8a5 GIT binary patch literal 2770 zcma)8XEYm(`cEP;VsEu~Z3(s0QpKwjjZvd2s9CQWl-iL7C1}yA7*Va%tUX#3wO3-) zrqotCsm=92|9kqL`{~{f&w0*oJs*GPfnlISARrYC0}Y|3lffC{_85UQKq3a}3C2KO z&uJ$Z2GZ~!5~K)>fxJ4W^Uo)Tn*QG@1}G3j#6Wb;Nd(O8PXfXSvxTYu0~uhlU=BH} z5gyh>n`RcHU+f|h{->)cfC3QcA`1v83}c|C{r`&~ItTzJKuza}GX%O)fq^n$7QWvd zBDn%4qJ{B7s>fMzu3!w9(qyP+^CjYhSSjcHPK>Ai(RM@1k*?^VT?X(~>P^B^oX2}9 z!Nwim8tQAWcvD~cndv^iSBA=)Jft&1(0o2b-FqE-24$*>o~?eQE?0WGo+X^nbUifX zFut_qrligTZ%d7%sI}wT4WC4dzD0o{Ln8dPj=YqE;*i}z`M|u&WGnYvB4V)tw&hwN z-(QIA&yOxRP2zu#=v^&ExC|dW?p3PPk~yRGBl!FKb8**M6hlj=J+j4d7F&MkhZo38 zU!UKoD};|5HGRbAM%e5I#rPwy$2L>jWU!LoIvpBOUQo4rhrJn0U{-3utHeWvSptN5 z28Dj@x(kmnxmC{lp}fLaCxuH%+O$*b#qV;=A2lnG57(M`5<2f{Hkt-E()TT;w2@gI z2s8^=Dg0uX{&CHw#G_K1{D3uge|Wq7&lbq`jtlQiAp_sur%4l+tbkA!yO zc4uF776fHoGi&h?ol+5O1k!#UI?r1Tkg043DWJ&7Dah$aP6LKdum@2+Wvt1>6x>7`-5F+1q2)D64hOh@)^A%Izxv} zxcuXjbQxEpE&bmiwHXH~xMFMfFHJ&e^_eDd@2p-L^kdfx3I#QGjgRuuo|W}6XpfN& zF1Ka!uWr>_F$c?#5IbSjUmx9>oL>%+uOF6Zy)y->VnUy4U(vX*Qs>#Ch?#y@MD4L6 z7se&EKn3d)^BTpG(mdj_8HOIpkyO=at7u-zk0bl@cpUhZ*{C!)f6U9|{A{gVq9H-4 zjKyMl?R#Cpe@T3O6<5~0xJnnM|Dni@kjc8L`!3Ghy3kFazGdMw55lQIs7Ue02&I?d zaK-{;KB3tiP{o15{>rCN9qU1Baem9&6k8@cViw(1foLSpxWYt~5$}(( zjOy*nHkf_~7w75GsIkp2J)gYj%JAhi4TZr^oU$Lcc66`va_TwF+huv1Ic=wP-FB04 zXP(v?CqWfJxG1lG?ZPiLPaP2B}_D_SlS*JNie zDi}^pR#z!EOZjxI2Vx&5^5q=zJ)6NMAHom{wSi!JKR1p}koQ4iX@=%<+=&6#9rN0Y zU1uSldDA!!UI?AF*mzRUzI%eo{7E(lU3^z^c!1YQ3{rC0KG`%MuxAoFGTx4UpHIXo zf`VG-9)<)uK$l%~qX@qe#9~=v4#SMB=?lKMv^`jmiJ9+Neg2@b=U9D6@|XD@kMnTT zGTDAo>|V)|+9r@;x-@COr)6X^o7S`Y2pXSZDODdf79>rMd+>V##MYC>5bA5>$g* z_0gKp*VnS<+pxm5fuBSlIrHRwSIHj~#J~;TOJA>mWWv&}l-(z=nxhB_lEx`E{?91M za3h$+pSq;ufb$4)0qz4l0ZxDbKq$Z+;0tg8_?%-en8-giPB;gc&C=7`RT!?OssV?o zs;euhD8pbFaQ+_?4K)!1esWGFgMfhZ759$<{BMPQwwD>5Gr#!d8&b)p{5W4y*G%^9 z|5Df;Jok0#i2J$0$8SX1iwITG7%o$hTN!?G$n;kfi8AA!Xluh`P{yk~ z6EW;)vK72Y@@o89N3o^7ib`2G{5+~{(*Ns5!8ev1If){X9g=7OItdj})y_a2rv_ho z>gX*S$e(~?7E9g0k7NUhk*(eSgQf#&8$X+@D4c#v>^*(l3K;YzKI1ll7^SJz#Wip_ z^R;>ar%#Z(bm8KYJMFjGnpGn)6?-c8n-wJ8Ec5e~bim}SiUkKoUR-)YlO#D=@1x7F&W(NSj?)`dDwe7Tpz5)DW=UR0 zyYTD!NtH9DDvvEId7-<|J?8x)RFUQt9PvL_X>%LHb5=?PCo7cFmnfI-lXD)_wU~q zty!hrWPFK6+uxd@SMFi5H~iNBgR6pKyUVecEG9J2#~EQ)fgsj9ij>?b7=QmtI=Mij zzB3FfkIl8@IMi`?5qY9{)Gj|@8#I4IzWl>TOe{NXWO%ZYtw)|H#JTa-c8$3*(~A<8 zX>uvtiDZU=c?4=^PPw$U^cu0GB^(}qQR_AFbHRos z#>Mk|pL+xhU2>z7v8?eSy`3q35?~)uIS(#TuA;X_mMK={Qe_3-$kb^I&yD?r=(N0C z4dl9Tz*=j4M#W|!H4)glaKWi>6>gGap_k3AF1hQx<~b^1QZbLgpx2dI53>JeG4T9} z9#%zT9C?BGz{#;MlPfwAFp2UB*lM@%^-9w2=0>YW7v~Q;e>=UYjmO{dQh)6Dc)Ys3bg|TemGyfxGEl&Y3!@~ekrF^CAZoo zr+x>V8Y;@PeM6V27O7f8n`&}12n92N!C{Pl{yY#60ssqtxvI+GW)e+XikHf)oNl_8 tUCA~m=8c@&@+pxzMX%t%9NV{U{}w*+{=s=MK;iDdRMJi`TJrxY>0jZu|4IM= literal 0 HcmV?d00001 diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt index a07498d..9d01964 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/security/SecurityConfig.kt @@ -18,6 +18,7 @@ class SecurityConfig { cors { } csrf { disable() } authorizeHttpRequests { + authorize("/actuator/health", permitAll) authorize("/api/report/**", hasRole("USER")) authorize("/api/push/**", hasRole("USER")) } diff --git a/report-generation-service/src/main/resources/application.yml b/report-generation-service/src/main/resources/application.yml index cc36aea..f3ca0fc 100644 --- a/report-generation-service/src/main/resources/application.yml +++ b/report-generation-service/src/main/resources/application.yml @@ -6,7 +6,7 @@ spring: oauth2: resource-server: jwt: - issuer-uri: http://localhost:8888/realms/wiarygodnik + issuer-uri: https://localhost:8888/realms/wiarygodnik rabbitmq: host: localhost @@ -36,14 +36,20 @@ spring: server: port: 8082 + ssl: + enabled: true + key-store: classpath:keystore/wiarygodnik.p12 + key-store-password: changeit + key-store-type: PKCS12 + key-alias: wiarygodnik cors: allowed-origins: - http://localhost:5173 - - http://localhost:4173 - - http://localhost - https://localhost:5173 + - http://localhost:4173 - https://localhost:4173 + - http://localhost - https://localhost allowed-methods: - GET diff --git a/report-generation-service/src/main/resources/keystore/wiarygodnik.p12 b/report-generation-service/src/main/resources/keystore/wiarygodnik.p12 new file mode 100644 index 0000000000000000000000000000000000000000..838e7297d66c9ed86a8d21869f317439e55da8a5 GIT binary patch literal 2770 zcma)8XEYm(`cEP;VsEu~Z3(s0QpKwjjZvd2s9CQWl-iL7C1}yA7*Va%tUX#3wO3-) zrqotCsm=92|9kqL`{~{f&w0*oJs*GPfnlISARrYC0}Y|3lffC{_85UQKq3a}3C2KO z&uJ$Z2GZ~!5~K)>fxJ4W^Uo)Tn*QG@1}G3j#6Wb;Nd(O8PXfXSvxTYu0~uhlU=BH} z5gyh>n`RcHU+f|h{->)cfC3QcA`1v83}c|C{r`&~ItTzJKuza}GX%O)fq^n$7QWvd zBDn%4qJ{B7s>fMzu3!w9(qyP+^CjYhSSjcHPK>Ai(RM@1k*?^VT?X(~>P^B^oX2}9 z!Nwim8tQAWcvD~cndv^iSBA=)Jft&1(0o2b-FqE-24$*>o~?eQE?0WGo+X^nbUifX zFut_qrligTZ%d7%sI}wT4WC4dzD0o{Ln8dPj=YqE;*i}z`M|u&WGnYvB4V)tw&hwN z-(QIA&yOxRP2zu#=v^&ExC|dW?p3PPk~yRGBl!FKb8**M6hlj=J+j4d7F&MkhZo38 zU!UKoD};|5HGRbAM%e5I#rPwy$2L>jWU!LoIvpBOUQo4rhrJn0U{-3utHeWvSptN5 z28Dj@x(kmnxmC{lp}fLaCxuH%+O$*b#qV;=A2lnG57(M`5<2f{Hkt-E()TT;w2@gI z2s8^=Dg0uX{&CHw#G_K1{D3uge|Wq7&lbq`jtlQiAp_sur%4l+tbkA!yO zc4uF776fHoGi&h?ol+5O1k!#UI?r1Tkg043DWJ&7Dah$aP6LKdum@2+Wvt1>6x>7`-5F+1q2)D64hOh@)^A%Izxv} zxcuXjbQxEpE&bmiwHXH~xMFMfFHJ&e^_eDd@2p-L^kdfx3I#QGjgRuuo|W}6XpfN& zF1Ka!uWr>_F$c?#5IbSjUmx9>oL>%+uOF6Zy)y->VnUy4U(vX*Qs>#Ch?#y@MD4L6 z7se&EKn3d)^BTpG(mdj_8HOIpkyO=at7u-zk0bl@cpUhZ*{C!)f6U9|{A{gVq9H-4 zjKyMl?R#Cpe@T3O6<5~0xJnnM|Dni@kjc8L`!3Ghy3kFazGdMw55lQIs7Ue02&I?d zaK-{;KB3tiP{o15{>rCN9qU1Baem9&6k8@cViw(1foLSpxWYt~5$}(( zjOy*nHkf_~7w75GsIkp2J)gYj%JAhi4TZr^oU$Lcc66`va_TwF+huv1Ic=wP-FB04 zXP(v?CqWfJxG1lG?ZPiLPaP2B}_D_SlS*JNie zDi}^pR#z!EOZjxI2Vx&5^5q=zJ)6NMAHom{wSi!JKR1p}koQ4iX@=%<+=&6#9rN0Y zU1uSldDA!!UI?AF*mzRUzI%eo{7E(lU3^z^c!1YQ3{rC0KG`%MuxAoFGTx4UpHIXo zf`VG-9)<)uK$l%~qX@qe#9~=v4#SMB=?lKMv^`jmiJ9+Neg2@b=U9D6@|XD@kMnTT zGTDAo>|V)|+9r@;x-@COr)6X^o7S`Y2pXSZDODdf79>rMd+>V##MYC>5bA5>$g* z_0gKp*VnS<+pxm5fuBSlIrHRwSIHj~#J~;TOJA>mWWv&}l-(z=nxhB_lEx`E{?91M za3h$+pSq;ufb$4)0qz4l0ZxDbKq$Z+;0tg8_?%-en8-giPB;gc&C=7`RT!?OssV?o zs;euhD8pbFaQ+_?4K)!1esWGFgMfhZ759$<{BMPQwwD>5Gr#!d8&b)p{5W4y*G%^9 z|5Df;Jok0#i2J$0$8SX1iwITG7%o$hTN!?G$n;kfi8AA!Xluh`P{yk~ z6EW;)vK72Y@@o89N3o^7ib`2G{5+~{(*Ns5!8ev1If){X9g=7OItdj})y_a2rv_ho z>gX*S$e(~?7E9g0k7NUhk*(eSgQf#&8$X+@D4c#v>^*(l3K;YzKI1ll7^SJz#Wip_ z^R;>ar%#Z(bm8KYJMFjGnpGn)6?-c8n-wJ8Ec5e~bim}SiUkKoUR-)YlO#D=@1x7F&W(NSj?)`dDwe7Tpz5)DW=UR0 zyYTD!NtH9DDvvEId7-<|J?8x)RFUQt9PvL_X>%LHb5=?PCo7cFmnfI-lXD)_wU~q zty!hrWPFK6+uxd@SMFi5H~iNBgR6pKyUVecEG9J2#~EQ)fgsj9ij>?b7=QmtI=Mij zzB3FfkIl8@IMi`?5qY9{)Gj|@8#I4IzWl>TOe{NXWO%ZYtw)|H#JTa-c8$3*(~A<8 zX>uvtiDZU=c?4=^PPw$U^cu0GB^(}qQR_AFbHRos z#>Mk|pL+xhU2>z7v8?eSy`3q35?~)uIS(#TuA;X_mMK={Qe_3-$kb^I&yD?r=(N0C z4dl9Tz*=j4M#W|!H4)glaKWi>6>gGap_k3AF1hQx<~b^1QZbLgpx2dI53>JeG4T9} z9#%zT9C?BGz{#;MlPfwAFp2UB*lM@%^-9w2=0>YW7v~Q;e>=UYjmO{dQh)6Dc)Ys3bg|TemGyfxGEl&Y3!@~ekrF^CAZoo zr+x>V8Y;@PeM6V27O7f8n`&}12n92N!C{Pl{yY#60ssqtxvI+GW)e+XikHf)oNl_8 tUCA~m=8c@&@+pxzMX%t%9NV{U{}w*+{=s=MK;iDdRMJi`TJrxY>0jZu|4IM= literal 0 HcmV?d00001 diff --git a/wiarygodnik_frontend/.env.production b/wiarygodnik_frontend/.env.production index ec4d866..0e8999e 100644 --- a/wiarygodnik_frontend/.env.production +++ b/wiarygodnik_frontend/.env.production @@ -1 +1,4 @@ -VITE_KEYCLOAK_URL=http://keycloak:8888/ \ No newline at end of file +VITE_KEYCLOAK_URL=https://localhost:8888/ + +VITE_CONTENT_ANALYSIS_SERVICE_API_URL=https://localhost:8081/ +VITE_REPORT_GENERATION_SERVICE_API_URL=https://localhost:8082/ \ No newline at end of file diff --git a/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx b/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx index d7ea7b7..76a2c1c 100644 --- a/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx +++ b/wiarygodnik_frontend/src/features/auth/context/KeycloakContext.tsx @@ -79,13 +79,11 @@ export const KeycloakProvider: React.FC = ({ children }) const keycloak = createKeycloak(); restoreOfflineSession(keycloak, setAuthenticated); - if (navigator.onLine) { initOnline(keycloak, setAuthenticated) - .catch(() => setAuthenticated(false)); + .catch(() => setAuthenticated(false)) + .finally(() => setKeycloak(keycloak)); } - - setKeycloak(keycloak); }, []); useEffect(() => { From a38ebe45ebb3fa23d9326bce3df804247eacfecc Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Sat, 24 Jan 2026 20:09:11 +0100 Subject: [PATCH 14/15] Retry on JSON parsing error from LLM & adjust prompts and db types --- .../cas/model/ComparisonSourceFacts.kt | 2 +- .../cas/service/agent/AbstractAgent.kt | 16 ++++++++-------- .../service/agent/ContentSummarizationAgent.kt | 1 + .../rgs/service/AiAnalysisReportGenerator.kt | 18 +++++++++--------- .../notifications/ReportGeneratedListener.kt | 4 ++-- 5 files changed, 21 insertions(+), 20 deletions(-) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt index dafcdf6..589e6f9 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/model/ComparisonSourceFacts.kt @@ -7,6 +7,6 @@ import jakarta.persistence.GenerationType.SEQUENCE class ComparisonSourceFacts( @ManyToOne @JoinColumn(name = "comparison_summary_id") val comparisonSummary: ComparisonSummary, @Column(columnDefinition = "TEXT") val sourceUrl: String, - @ElementCollection @CollectionTable(name = "source_facts") val facts: Set = mutableSetOf(), + @ElementCollection @CollectionTable(name = "source_facts") @Column(columnDefinition = "TEXT") val facts: Set = mutableSetOf(), @Id @GeneratedValue(strategy = SEQUENCE) val id: Long? = null ) diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt index 3b6f4ef..b783157 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/AbstractAgent.kt @@ -1,25 +1,25 @@ package pl.edu.p.lodz.wiarygodnik.cas.service.agent -import com.fasterxml.jackson.core.JsonParseException import org.springframework.ai.chat.client.ChatClient +import org.springframework.ai.chat.client.advisor.StructuredOutputValidationAdvisor +import org.springframework.ai.chat.client.advisor.api.BaseAdvisor import org.springframework.ai.chat.model.ChatModel -import org.springframework.retry.annotation.Backoff -import org.springframework.retry.annotation.Retryable abstract class AbstractAgent(chatModel: ChatModel, private val responseType: Class) { private val chatClient = ChatClient.create(chatModel) + private val outputValidationAdvisor = StructuredOutputValidationAdvisor.builder() + .outputType(responseType) + .maxRepeatAttempts(3) + .advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 1000) + .build() protected abstract fun systemPrompt(): String - @Retryable( - value = [JsonParseException::class], - maxAttempts = 3, - backoff = Backoff(delay = 0) - ) fun work(input: String): T = chatClient.prompt() .system { system -> system.text(systemPrompt()) } .user { user -> user.text(input) } + .advisors(outputValidationAdvisor) .call() .entity(responseType) ?: throw RuntimeException("Agent ${responseType.name} returned a null object.") diff --git a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt index 0b70e64..dc9f5f9 100644 --- a/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt +++ b/content-analysis-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/cas/service/agent/ContentSummarizationAgent.kt @@ -22,6 +22,7 @@ class ContentSummarizationAgent(chatModel: ChatModel) : - Wypisz najważniejsze słowa kluczowe opisujące temat artykułu. - Nie uwzględniaj elementów strony ani przypadkowych słów (np. „menu”, „reklama”, „footer”). - Używaj pojedynczych słów lub krótkich fraz. + - Nie więcej niż 8 słów lub krótkich fraz. ### Ważne zasady filtrowania treści - Bierz pod uwagę tylko właściwą treść artykułu. diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt index 4a13424..c02ad3d 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/AiAnalysisReportGenerator.kt @@ -1,25 +1,24 @@ package pl.edu.p.lodz.wiarygodnik.rgs.service -import com.fasterxml.jackson.core.JsonParseException import org.springframework.ai.chat.client.ChatClient +import org.springframework.ai.chat.client.advisor.StructuredOutputValidationAdvisor +import org.springframework.ai.chat.client.advisor.api.BaseAdvisor import org.springframework.ai.chat.model.ChatModel import org.springframework.core.io.ResourceLoader -import org.springframework.retry.annotation.Backoff -import org.springframework.retry.annotation.Retryable import org.springframework.stereotype.Component -import pl.edu.p.lodz.wiarygodnik.rgs.model.message.AnalysisResultMessage import pl.edu.p.lodz.wiarygodnik.rgs.model.dto.ReportGenerationResult +import pl.edu.p.lodz.wiarygodnik.rgs.model.message.AnalysisResultMessage @Component class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader: ResourceLoader) { private val chatClient = ChatClient.create(chatModel) + private val outputValidationAdvisor = StructuredOutputValidationAdvisor.builder() + .outputType(ReportGenerationResult::class.java) + .maxRepeatAttempts(3) + .advisorOrder(BaseAdvisor.HIGHEST_PRECEDENCE + 1000) + .build() - @Retryable( - value = [JsonParseException::class], - maxAttempts = 3, - backoff = Backoff(delay = 0) - ) fun generate(input: AnalysisResultMessage): ReportGenerationResult { val analysisReportGenerationPrompt: String = prepareAnalysisReportGenerationPrompt(input) return callChatGeneration(analysisReportGenerationPrompt) @@ -28,6 +27,7 @@ class AiAnalysisReportGenerator(chatModel: ChatModel, private val resourceLoader private fun callChatGeneration(input: String): ReportGenerationResult = chatClient.prompt() .system { system -> system.text(readSystemPrompt()) } .user { user -> user.text(input) } + .advisors(outputValidationAdvisor) .call() .entity(ReportGenerationResult::class.java) ?: throw RuntimeException("LLM returned a null object while generating a report.") diff --git a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/notifications/ReportGeneratedListener.kt b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/notifications/ReportGeneratedListener.kt index ba4910e..8e4bee8 100644 --- a/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/notifications/ReportGeneratedListener.kt +++ b/report-generation-service/src/main/kotlin/pl/edu/p/lodz/wiarygodnik/rgs/service/notifications/ReportGeneratedListener.kt @@ -22,8 +22,8 @@ class ReportGeneratedListener( .forEach(Consumer { sub: PushSubscription -> pushService.send( sub, - "Analysis completed", - "Your report is ready", + "Analiza zakończona!", + "Twój raport jest gotowy.", "/reports/" + event.requestId ) }) From a00199aa515dd4cad53da9cb8c258cfe0064f523 Mon Sep 17 00:00:00 2001 From: Oskar Trela Date: Tue, 27 Jan 2026 20:54:00 +0100 Subject: [PATCH 15/15] Fix some issues --- content-analysis-service/build.gradle.kts | 2 -- report-generation-service/build.gradle.kts | 2 -- wiarygodnik_frontend/src/App.tsx | 1 + .../report/components/ReportListButton.tsx | 19 +++++++++++++++---- .../features/report/hooks/useDeleteReport.ts | 7 +------ 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/content-analysis-service/build.gradle.kts b/content-analysis-service/build.gradle.kts index 1ab23a1..a40bb94 100644 --- a/content-analysis-service/build.gradle.kts +++ b/content-analysis-service/build.gradle.kts @@ -32,8 +32,6 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") implementation("org.springframework.boot:spring-boot-starter-amqp") - implementation("org.springframework.retry:spring-retry") - implementation("org.springframework.boot:spring-boot-starter-aop") implementation("org.springframework.ai:spring-ai-starter-model-ollama") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1") diff --git a/report-generation-service/build.gradle.kts b/report-generation-service/build.gradle.kts index adb691a..e7c2981 100644 --- a/report-generation-service/build.gradle.kts +++ b/report-generation-service/build.gradle.kts @@ -30,8 +30,6 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-oauth2-resource-server") implementation("org.springframework.boot:spring-boot-starter-amqp") - implementation("org.springframework.retry:spring-retry") - implementation("org.springframework.boot:spring-boot-starter-aop") implementation("org.springframework.ai:spring-ai-starter-model-ollama") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") diff --git a/wiarygodnik_frontend/src/App.tsx b/wiarygodnik_frontend/src/App.tsx index a883848..c1a5f11 100644 --- a/wiarygodnik_frontend/src/App.tsx +++ b/wiarygodnik_frontend/src/App.tsx @@ -7,6 +7,7 @@ import { syncBadge } from './features/push/lib/badging-db.ts'; function App() { useEffect(() => { + if (!('serviceWorker' in navigator)) return; navigator.serviceWorker.addEventListener('message', (event) => { if (event.data?.type === 'SYNC_BADGE') { syncBadge(); diff --git a/wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx b/wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx index bdd5dc8..6eb2c23 100644 --- a/wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx +++ b/wiarygodnik_frontend/src/features/report/components/ReportListButton.tsx @@ -3,6 +3,8 @@ import DeleteIcon from '@mui/icons-material/Delete'; import { sideMenuButton } from "../../../Style.tsx"; import { useNavigate } from "react-router-dom"; import { useDeleteReport } from "../hooks/useDeleteReport.ts"; +import { useOnlineStatus } from "../../../hooks/useOnlineStatus.ts"; +import { enqueueSnackbar } from "notistack"; interface ReportListButtonProps { reportTitle: string; @@ -12,6 +14,7 @@ interface ReportListButtonProps { } export const ReportListButton = ({ reportTitle, requestId, setRecentlyDeletedReqId, currentPageReqId }: ReportListButtonProps) => { + const online = useOnlineStatus(); const navigate = useNavigate(); const { deleteReport } = useDeleteReport(); @@ -20,11 +23,19 @@ export const ReportListButton = ({ reportTitle, requestId, setRecentlyDeletedReq const handleDelete = async () => { if (!window.confirm("Czy na pewno chcesz usunąć raport?")) return; - await deleteReport(requestId); - setRecentlyDeletedReqId(requestId); + try { + await deleteReport(requestId); + setRecentlyDeletedReqId(requestId); - if (currentPageReqId && currentPageReqId === requestId) { - navigate('/reports') + if (currentPageReqId && currentPageReqId === requestId) { + navigate('/reports') + } + } catch (e) { + if (!online) { + enqueueSnackbar("Raport zostanie usunięty automatycznie po przywróceniu połączenia.", { variant: 'success' }); + return; + } + return; } } diff --git a/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts b/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts index 4146441..ec9f0ad 100644 --- a/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts +++ b/wiarygodnik_frontend/src/features/report/hooks/useDeleteReport.ts @@ -5,12 +5,7 @@ export const useDeleteReport = () => { const { deleteMyReport } = useReportApi(); const deleteReport = useCallback(async (requestId: string) => { - try { - await deleteMyReport(requestId); - return true; - } catch (err: any) { - return false; - } + await deleteMyReport(requestId); }, []); return { deleteReport };