diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/entities/prior_notification/PriorNotificationSentMessage.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/entities/prior_notification/PriorNotificationSentMessage.kt new file mode 100644 index 0000000000..cbadb08f0c --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/entities/prior_notification/PriorNotificationSentMessage.kt @@ -0,0 +1,16 @@ +package fr.gouv.cnsp.monitorfish.domain.entities.prior_notification + +import java.time.ZonedDateTime + +data class PriorNotificationSentMessage( + val id: Int, + val communicationMeans: String, + val dateTimeUtc: ZonedDateTime, + val errorMessage: String?, + val priorNotificationReportId: String?, + val priorNotificationSource: String, + val recipientAddressOrNumber: String, + val recipientName: String, + val recipientOrganization: String, + val success: Boolean, +) diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/repositories/PriorNotificationSentMessageRepository.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/repositories/PriorNotificationSentMessageRepository.kt new file mode 100644 index 0000000000..a991e17ca6 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/repositories/PriorNotificationSentMessageRepository.kt @@ -0,0 +1,7 @@ +package fr.gouv.cnsp.monitorfish.domain.repositories + +import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage + +interface PriorNotificationSentMessageRepository { + fun findAllByReportId(reportId: String): List +} diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/use_cases/prior_notification/GetPriorNotificationSentMessages.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/use_cases/prior_notification/GetPriorNotificationSentMessages.kt new file mode 100644 index 0000000000..c956026a09 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/domain/use_cases/prior_notification/GetPriorNotificationSentMessages.kt @@ -0,0 +1,14 @@ +package fr.gouv.cnsp.monitorfish.domain.use_cases.prior_notification + +import fr.gouv.cnsp.monitorfish.config.UseCase +import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage +import fr.gouv.cnsp.monitorfish.domain.repositories.* + +@UseCase +class GetPriorNotificationSentMessages( + private val priorNotificationSentMessageRepository: PriorNotificationSentMessageRepository, +) { + fun execute(reportId: String): List { + return priorNotificationSentMessageRepository.findAllByReportId(reportId) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationController.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationController.kt index 042e719dc0..95b384aa99 100644 --- a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationController.kt +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationController.kt @@ -36,6 +36,7 @@ class PriorNotificationController( private val deletePriorNotificationUpload: DeletePriorNotificationUpload, private val getPriorNotification: GetPriorNotification, private val getPriorNotificationPdfDocument: GetPriorNotificationPdfDocument, + private val getPriorNotificationSentMessages: GetPriorNotificationSentMessages, private val getPriorNotificationUpload: GetPriorNotificationUpload, private val getPriorNotificationUploads: GetPriorNotificationUploads, private val getPriorNotifications: GetPriorNotifications, @@ -374,6 +375,17 @@ class PriorNotificationController( return PriorNotificationDataOutput.fromPriorNotification(updatedPriorNotification) } + @GetMapping("/{reportId}/sent_messages") + @Operation(summary = "Get all sent messages for a given prior notification") + fun getSentMessages( + @PathParam("Logbook message `reportId`") + @PathVariable(name = "reportId") + reportId: String, + ): List { + return getPriorNotificationSentMessages.execute(reportId) + .map { PriorNotificationSentMessageDataOutput.fromPriorNotificationSentMessage(it) } + } + @GetMapping("/{reportId}/uploads/{priorNotificationUploadId}") @Operation(summary = "Download a prior notification attachment") fun getUploads( diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationDataOutput.kt index a0f28d93b2..df42b5c011 100644 --- a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationDataOutput.kt +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationDataOutput.kt @@ -19,6 +19,7 @@ class PriorNotificationDataOutput( val operationDate: ZonedDateTime, val state: PriorNotificationState?, val riskFactor: Double?, + val vesselId: Int, ) { companion object { fun fromPriorNotification(priorNotification: PriorNotification): PriorNotificationDataOutput { @@ -46,15 +47,14 @@ class PriorNotificationDataOutput( null } - val isLessThanTwelveMetersVessel = + val vessel = requireNotNull(priorNotification.vessel) { "`priorNotification.vessel` is null." - }.isLessThanTwelveMetersVessel() - val isVesselUnderCharter = - requireNotNull(priorNotification.vessel) { - "`priorNotification.vessel` is null." - }.underCharter + } + val isLessThanTwelveMetersVessel = vessel.isLessThanTwelveMetersVessel() + val isVesselUnderCharter = vessel.underCharter val logbookMessage = priorNotification.logbookMessageAndValue.logbookMessage + val vesselId = vessel.id val logbookMessageDataOutput = LogbookMessageDataOutput.fromLogbookMessage(logbookMessage) @@ -71,6 +71,7 @@ class PriorNotificationDataOutput( operationDate = logbookMessage.operationDateTime, state = priorNotification.state, riskFactor = priorNotification.logbookMessageAndValue.value.riskFactor, + vesselId = vesselId, ) } } diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationSentMessageDataOutput.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationSentMessageDataOutput.kt new file mode 100644 index 0000000000..41a8158703 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/outputs/PriorNotificationSentMessageDataOutput.kt @@ -0,0 +1,32 @@ +package fr.gouv.cnsp.monitorfish.infrastructure.api.outputs + +import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage +import java.time.ZonedDateTime + +data class PriorNotificationSentMessageDataOutput( + val id: Int, + val communicationMeans: String, + val dateTimeUtc: ZonedDateTime, + val errorMessage: String?, + val recipientAddressOrNumber: String, + val recipientName: String, + val recipientOrganization: String, + val success: Boolean, +) { + companion object { + fun fromPriorNotificationSentMessage( + priorNotificationSentMessage: PriorNotificationSentMessage, + ): PriorNotificationSentMessageDataOutput { + return PriorNotificationSentMessageDataOutput( + id = priorNotificationSentMessage.id, + communicationMeans = priorNotificationSentMessage.communicationMeans, + dateTimeUtc = priorNotificationSentMessage.dateTimeUtc, + errorMessage = priorNotificationSentMessage.errorMessage, + recipientAddressOrNumber = priorNotificationSentMessage.recipientAddressOrNumber, + recipientName = priorNotificationSentMessage.recipientName, + recipientOrganization = priorNotificationSentMessage.recipientOrganization, + success = priorNotificationSentMessage.success, + ) + } + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/entities/PriorNotificationSentMessageEntity.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/entities/PriorNotificationSentMessageEntity.kt new file mode 100644 index 0000000000..6a77741941 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/entities/PriorNotificationSentMessageEntity.kt @@ -0,0 +1,49 @@ +package fr.gouv.cnsp.monitorfish.infrastructure.database.entities + +import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage +import jakarta.persistence.* +import org.hibernate.annotations.Immutable +import java.time.ZonedDateTime + +@Entity +@Immutable +@Table(name = "prior_notification_sent_messages") +data class PriorNotificationSentMessageEntity( + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", unique = true, nullable = false) + val id: Int, + @Column(name = "communication_means", nullable = false) + val communicationMeans: String, + @Column(name = "date_time_utc", nullable = false) + val dateTimeUtc: ZonedDateTime, + @Column(name = "error_message", nullable = true) + val errorMessage: String?, + @Column(name = "prior_notification_report_id", nullable = false) + val priorNotificationReportId: String?, + @Column(name = "prior_notification_source", nullable = false) + val priorNotificationSource: String, + @Column(name = "recipient_address_or_number", nullable = false) + val recipientAddressOrNumber: String, + @Column(name = "recipient_name", nullable = false) + val recipientName: String, + @Column(name = "recipient_organization", nullable = false) + val recipientOrganization: String, + @Column(name = "success", nullable = false) + val success: Boolean, +) { + fun toPriorNotificationSentMessage(): PriorNotificationSentMessage { + return PriorNotificationSentMessage( + id = id, + communicationMeans = communicationMeans, + dateTimeUtc = dateTimeUtc, + errorMessage = errorMessage, + priorNotificationReportId = priorNotificationReportId, + priorNotificationSource = priorNotificationSource, + recipientAddressOrNumber = recipientAddressOrNumber, + recipientName = recipientName, + recipientOrganization = recipientOrganization, + success = success, + ) + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/JpaPriorNotificationSentMessageRepository.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/JpaPriorNotificationSentMessageRepository.kt new file mode 100644 index 0000000000..ba15199311 --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/JpaPriorNotificationSentMessageRepository.kt @@ -0,0 +1,17 @@ +package fr.gouv.cnsp.monitorfish.infrastructure.database.repositories + +import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage +import fr.gouv.cnsp.monitorfish.domain.repositories.PriorNotificationSentMessageRepository +import fr.gouv.cnsp.monitorfish.infrastructure.database.repositories.interfaces.DBPriorNotificationSentMessageRepository +import org.springframework.stereotype.Repository + +@Repository +class JpaPriorNotificationSentMessageRepository( + private val dbPriorNotificationSentMessageRepository: DBPriorNotificationSentMessageRepository, +) : PriorNotificationSentMessageRepository { + override fun findAllByReportId(reportId: String): List { + return dbPriorNotificationSentMessageRepository + .findAllByReportId(reportId) + .map { it.toPriorNotificationSentMessage() } + } +} diff --git a/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/interfaces/DBPriorNotificationSentMessageRepository.kt b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/interfaces/DBPriorNotificationSentMessageRepository.kt new file mode 100644 index 0000000000..4940027acb --- /dev/null +++ b/backend/src/main/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/interfaces/DBPriorNotificationSentMessageRepository.kt @@ -0,0 +1,17 @@ +package fr.gouv.cnsp.monitorfish.infrastructure.database.repositories.interfaces + +import fr.gouv.cnsp.monitorfish.infrastructure.database.entities.PriorNotificationSentMessageEntity +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query + +interface DBPriorNotificationSentMessageRepository : JpaRepository { + @Query( + """ + SELECT * + FROM prior_notification_sent_messages + WHERE prior_notification_report_id = :reportId + """, + nativeQuery = true, + ) + fun findAllByReportId(reportId: String): List +} diff --git a/backend/src/main/resources/db/migration/internal/V0.280__Update_prior_notification_sent_messages_table.sql b/backend/src/main/resources/db/migration/internal/V0.280__Update_prior_notification_sent_messages_table.sql new file mode 100644 index 0000000000..bd98e8fc2d --- /dev/null +++ b/backend/src/main/resources/db/migration/internal/V0.280__Update_prior_notification_sent_messages_table.sql @@ -0,0 +1,5 @@ +DELETE FROM public.prior_notification_sent_messages; + +ALTER TABLE public.prior_notification_sent_messages + ADD COLUMN recipient_name VARCHAR NOT NULL, + ADD COLUMN recipient_organization VARCHAR NOT NULL; \ No newline at end of file diff --git a/backend/src/main/resources/db/testdata/V666.29__Insert_dummy_prior_notification_sent_messages.sql b/backend/src/main/resources/db/testdata/V666.29__Insert_dummy_prior_notification_sent_messages.sql new file mode 100644 index 0000000000..aa19f07e2f --- /dev/null +++ b/backend/src/main/resources/db/testdata/V666.29__Insert_dummy_prior_notification_sent_messages.sql @@ -0,0 +1,39 @@ +INSERT INTO public.prior_notification_sent_messages ( + prior_notification_report_id, prior_notification_source, date_time_utc, communication_means, recipient_address_or_number, success, error_message, recipient_name, recipient_organization +) VALUES + ( 'FAKE_OPERATION_103', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'bgc-lorient@douane.finances.gouv.fr', TRUE, NULL, 'Unité 1', 'Douane'), + + ( 'FAKE_OPERATION_106', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'sgcd-nantes-codm@douane.finances.gouv.fr', TRUE, NULL, 'Unité 1', 'Douane'), + ( 'FAKE_OPERATION_106', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'bsl.lorient@gendarmerie.defense.gouv.fr', TRUE, NULL, 'Unité 3', 'Gendarmerie'), + + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.3 minutes', 'EMAIL', 'pgmarc720.lorient@gendarmerie.defense.gouv.fr', FALSE, NULL, 'Unité 3', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'ggmaratlan@gendarmerie.defense.gouv.fr', FALSE, NULL, 'Unité 4', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.1 minutes', 'SMS', '+33123456789', FALSE, NULL, 'Unité 3', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.2 minutes', 'SMS', '+33987654321', FALSE, NULL, 'Unité 4', 'Gendarmerie'), + + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '4.0 minutes', 'EMAIL', 'pgmarc720.lorient@gendarmerie.defense.gouv.fr', FALSE, NULL, 'Unité 3', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '4.1 minutes', 'EMAIL', 'ggmaratlan@gendarmerie.defense.gouv.fr', TRUE, NULL, 'Unité 4', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '4.2 minutes', 'EMAIL', 'unite5@ddtm-40.gouv.fr', FALSE, NULL, 'Unité 5', 'DDTM 40'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '4.3 minutes', 'SMS', '+33123456789', TRUE, NULL, 'Unité 3', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '4.4 minutes', 'SMS', '+33987654321', FALSE, NULL, 'Unité 4', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '4.5 minutes', 'SMS', '+33000000000', FALSE, NULL, 'Unité 5', 'DDTM 40'), + + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '9.3 minutes', 'EMAIL', 'pgmarc720.lorient@gendarmerie.defense.gouv.fr', TRUE, NULL, 'Unité 3', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '9.2 minutes', 'EMAIL', 'ggmaratlan@gendarmerie.defense.gouv.fr', TRUE, NULL, 'Unité 4', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '9.1 minutes', 'SMS', '+33123456789', TRUE, NULL, 'Unité 3', 'Gendarmerie'), + ( 'FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '9.0 minutes', 'SMS', '+33987654321', TRUE, NULL, 'Unité 4', 'Gendarmerie'), + + ( 'FAKE_OPERATION_110', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'ddtm-samel@morbihan.gouv.fr', TRUE, NULL, 'Unité 6', 'DDTM'), + ( 'FAKE_OPERATION_110', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'sd56@ofb.gouv.fr', FALSE, NULL, 'Unité 7', 'Office Français de la Biodiversité'), + ( 'FAKE_OPERATION_110', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'SMS', '+33111111111', FALSE, NULL, 'Unité 7', 'Office Français de la Biodiversité'), + + ('00000000-0000-4000-0000-000000000003', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'ddtm-pre@morbihan.gouv.fr', TRUE, NULL, 'Unité 9', 'DDTM'), + ('00000000-0000-4000-0000-000000000003', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'namo@example.gouv.fr', FALSE, NULL, 'Unité 10', 'DIRM / DM'), + + ('00000000-0000-4000-0000-000000000004', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'dreal@example.gouv.fr', FALSE, NULL, 'Unité 11', 'DDTM'), + + ('00000000-0000-4000-0000-000000000006', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'ddtm-ulam@morbihan.gouv.fr', TRUE, NULL, 'Unité 11', 'DDTM'), + + ('00000000-0000-4000-0000-000000000008', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'dirm@example.gouv.fr', FALSE, NULL, 'Unité 12', 'DIRM / DM'), + + ('00000000-0000-4000-0000-000000000010', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2.0 minutes', 'EMAIL', 'pam-jeanne-barret.dirm-memn@developpement-durable.gouv.fr', TRUE, NULL, 'Unité 12', 'DIRM / DM'); diff --git a/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/domain/use_cases/prior_notification/GetPriorNotificationSentMessagesUTests.kt b/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/domain/use_cases/prior_notification/GetPriorNotificationSentMessagesUTests.kt new file mode 100644 index 0000000000..deb0763df9 --- /dev/null +++ b/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/domain/use_cases/prior_notification/GetPriorNotificationSentMessagesUTests.kt @@ -0,0 +1,59 @@ +package fr.gouv.cnsp.monitorfish.domain.use_cases.prior_notification + +import com.nhaarman.mockitokotlin2.given +import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage +import fr.gouv.cnsp.monitorfish.domain.repositories.PriorNotificationSentMessageRepository +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.test.context.junit.jupiter.SpringExtension +import java.time.ZonedDateTime + +@ExtendWith(SpringExtension::class) +class GetPriorNotificationSentMessagesUTests { + @MockBean + private lateinit var priorNotificationSentMessageRepository: PriorNotificationSentMessageRepository + + @Test + fun `execute Should return a list of prior notification types`() { + // Given + val fakeReportId = "FAKE_REPORT_ID" + given(priorNotificationSentMessageRepository.findAllByReportId(fakeReportId)).willReturn( + listOf( + PriorNotificationSentMessage( + id = 1, + communicationMeans = "EMAIL", + dateTimeUtc = ZonedDateTime.now(), + errorMessage = null, + priorNotificationReportId = fakeReportId, + priorNotificationSource = "LOGBOOK", + recipientAddressOrNumber = "dreal01@example.org", + recipientName = "DREAL 01", + recipientOrganization = "DREAL", + success = true, + ), + PriorNotificationSentMessage( + id = 2, + communicationMeans = "SMS", + dateTimeUtc = ZonedDateTime.now(), + errorMessage = null, + priorNotificationReportId = fakeReportId, + priorNotificationSource = "MANUAL", + recipientAddressOrNumber = "+33123456789", + recipientName = "DREAL 02", + recipientOrganization = "DREAL", + success = true, + ), + ), + ) + + // When + val result = GetPriorNotificationSentMessages(priorNotificationSentMessageRepository).execute(fakeReportId) + + // Then + assertThat(result).hasSize(2) + assertThat(result[0].communicationMeans).isEqualTo("EMAIL") + assertThat(result[1].communicationMeans).isEqualTo("SMS") + } +} diff --git a/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationControllerUTests.kt b/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationControllerUTests.kt index ebf32ccf46..e02161223e 100644 --- a/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationControllerUTests.kt +++ b/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/api/bff/PriorNotificationControllerUTests.kt @@ -55,6 +55,9 @@ class PriorNotificationControllerUTests { @MockBean private lateinit var getPriorNotificationPdfDocument: GetPriorNotificationPdfDocument + @MockBean + private lateinit var getPriorNotificationSentMessages: GetPriorNotificationSentMessages + @MockBean private lateinit var getPriorNotificationUpload: GetPriorNotificationUpload @@ -497,4 +500,47 @@ class PriorNotificationControllerUTests { ) .andExpect(jsonPath("$.reportId", equalTo(fakePriorNotification.reportId))) } + + @Test + fun `getSentMessages Should get a list of prior notification sent messages`() { + val fakeReportId = "FAKE_REPORT_ID" + + // Given + given(getPriorNotificationSentMessages.execute(fakeReportId)).willReturn( + listOf( + PriorNotificationSentMessage( + id = 1, + communicationMeans = "EMAIL", + dateTimeUtc = ZonedDateTime.now(), + errorMessage = null, + priorNotificationReportId = fakeReportId, + priorNotificationSource = "LOGBOOK", + recipientAddressOrNumber = "dreal01@example.org", + recipientName = "DREAL 01", + recipientOrganization = "DREAL", + success = true, + ), + PriorNotificationSentMessage( + id = 2, + communicationMeans = "SMS", + dateTimeUtc = ZonedDateTime.now(), + errorMessage = null, + priorNotificationReportId = fakeReportId, + priorNotificationSource = "MANUAL", + recipientAddressOrNumber = "+33123456789", + recipientName = "DREAL 02", + recipientOrganization = "DREAL", + success = true, + ), + ), + ) + + // When + api.perform(get("/bff/v1/prior_notifications/$fakeReportId/sent_messages")) + // Then + .andExpect(status().isOk) + .andExpect(jsonPath("$.length()", equalTo(2))) + .andExpect(jsonPath("$[0].communicationMeans", equalTo("EMAIL"))) + .andExpect(jsonPath("$[1].communicationMeans", equalTo("SMS"))) + } } diff --git a/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/JpaPriorNotificationSentMessageITests.kt b/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/JpaPriorNotificationSentMessageITests.kt new file mode 100644 index 0000000000..9fc50cc443 --- /dev/null +++ b/backend/src/test/kotlin/fr/gouv/cnsp/monitorfish/infrastructure/database/repositories/JpaPriorNotificationSentMessageITests.kt @@ -0,0 +1,24 @@ +package fr.gouv.cnsp.monitorfish.infrastructure.database.repositories + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.transaction.annotation.Transactional + +class JpaPriorNotificationSentMessageITests : AbstractDBTests() { + @Autowired + private lateinit var jpaPriorNotificationSentMessageRepository: JpaPriorNotificationSentMessageRepository + + @Test + @Transactional + fun `findAllByReportId Should return the expected sent messages`() { + // Given + val reportId = "FAKE_OPERATION_103" + + // When + val result = jpaPriorNotificationSentMessageRepository.findAllByReportId(reportId) + + // Then + assertThat(result).isNotEmpty() + } +} diff --git a/datascience/src/pipeline/entities/beacon_malfunctions.py b/datascience/src/pipeline/entities/beacon_malfunctions.py index 9daffbe5f1..55bae0eb76 100644 --- a/datascience/src/pipeline/entities/beacon_malfunctions.py +++ b/datascience/src/pipeline/entities/beacon_malfunctions.py @@ -9,7 +9,7 @@ CNSP_SIP_DEPARTMENT_FAX, CNSP_SIP_DEPARTMENT_MOBILE_PHONE, ) -from src.pipeline.helpers.emails import CommunicationMeans +from src.pipeline.entities.communication_means import CommunicationMeans class BeaconStatus(Enum): diff --git a/datascience/src/pipeline/entities/communication_means.py b/datascience/src/pipeline/entities/communication_means.py new file mode 100644 index 0000000000..825fa3814b --- /dev/null +++ b/datascience/src/pipeline/entities/communication_means.py @@ -0,0 +1,7 @@ +from enum import Enum + + +class CommunicationMeans(Enum): + EMAIL = "EMAIL" + SMS = "SMS" + FAX = "FAX" diff --git a/datascience/src/pipeline/entities/control_units.py b/datascience/src/pipeline/entities/control_units.py index 225a05a613..076c4213d0 100644 --- a/datascience/src/pipeline/entities/control_units.py +++ b/datascience/src/pipeline/entities/control_units.py @@ -8,10 +8,12 @@ @dataclass -class ControlUnitWithEmails: +class ControlUnit: control_unit_id: int control_unit_name: str + administration: str emails: List[str] + phone_numbers: List[str] @dataclass @@ -20,7 +22,7 @@ class ControlUnitActions: Control unit and its fisheries control actions between two dates. """ - control_unit: ControlUnitWithEmails + control_unit: ControlUnit period: Period land_controls: pd.DataFrame sea_controls: pd.DataFrame diff --git a/datascience/src/pipeline/entities/pnos.py b/datascience/src/pipeline/entities/pnos.py index ee4d66a9ed..bc9929ede7 100644 --- a/datascience/src/pipeline/entities/pnos.py +++ b/datascience/src/pipeline/entities/pnos.py @@ -6,9 +6,10 @@ import pandas as pd +from src.pipeline.entities.communication_means import CommunicationMeans +from src.pipeline.entities.control_units import ControlUnit from src.pipeline.entities.fleet_segments import FishingGear, FleetSegment from src.pipeline.entities.missions import Infraction -from src.pipeline.helpers.emails import CommunicationMeans @dataclass(kw_only=True) @@ -196,6 +197,13 @@ def label(self): return labels[self.name] +@dataclass +class PnoAddressee: + name: str + organization: str + email_address_or_number: str + + @dataclass class RenderedPno: report_id: str @@ -208,14 +216,45 @@ class RenderedPno: port_locode: str facade: str source: PnoSource - html_for_pdf: Optional[str] = None - pdf_document: Optional[bytes] = None - generation_datetime_utc: Optional[datetime] = None - html_email_body: Optional[str] = None - sms_content: Optional[str] = None - control_unit_ids: Optional[list] = None - emails: Optional[list] = None - phone_numbers: Optional[list] = None + html_for_pdf: str | None = None + pdf_document: bytes | None = None + generation_datetime_utc: datetime | None = None + html_email_body: str | None = None + sms_content: str | None = None + control_units: List[ControlUnit] | None = None + + def get_addressees( + self, communication_means: CommunicationMeans + ) -> List[PnoAddressee]: + if self.control_units: + if communication_means == CommunicationMeans.EMAIL: + addressees = [ + PnoAddressee( + name=control_unit.control_unit_name, + organization=control_unit.administration, + email_address_or_number=email, + ) + for control_unit in self.control_units + for email in control_unit.emails + ] + elif communication_means == CommunicationMeans.SMS: + addressees = [ + PnoAddressee( + name=control_unit.control_unit_name, + organization=control_unit.administration, + email_address_or_number=phone_number, + ) + for control_unit in self.control_units + for phone_number in control_unit.phone_numbers + ] + else: + raise ValueError( + f"Unexpected communication_means {communication_means}" + ) + + else: + addressees = [] + return addressees @dataclass @@ -224,16 +263,6 @@ class PnoToSend: message: EmailMessage communication_means: CommunicationMeans - def get_addressees(self): - if self.communication_means == CommunicationMeans.EMAIL: - return self.pno.emails - elif self.communication_means == CommunicationMeans.SMS: - return self.pno.phone_numbers - else: - raise ValueError( - f"Unexpected communication_means {self.communication_means}" - ) - @dataclass class PriorNotificationSentMessage: @@ -243,4 +272,6 @@ class PriorNotificationSentMessage: communication_means: CommunicationMeans recipient_address_or_number: str success: bool + recipient_name: str + recipient_organization: str error_message: Optional[str] = None diff --git a/datascience/src/pipeline/flows/distribute_pnos.py b/datascience/src/pipeline/flows/distribute_pnos.py index 03f36317ac..5a9b5c2ae0 100644 --- a/datascience/src/pipeline/flows/distribute_pnos.py +++ b/datascience/src/pipeline/flows/distribute_pnos.py @@ -1,7 +1,6 @@ import dataclasses from datetime import datetime from email.policy import EmailPolicy -from itertools import chain from pathlib import Path from typing import List, Tuple @@ -35,6 +34,8 @@ STATE_FLAGS_ICONS_LOCATION, default_risk_factors, ) +from src.pipeline.entities.communication_means import CommunicationMeans +from src.pipeline.entities.control_units import ControlUnit from src.pipeline.entities.fleet_segments import FishingGear, FleetSegment from src.pipeline.entities.missions import Infraction from src.pipeline.entities.pnos import ( @@ -49,7 +50,6 @@ ) from src.pipeline.generic_tasks import extract, load from src.pipeline.helpers.emails import ( - CommunicationMeans, create_html_email, create_sms_email, resize_pdf_to_A4, @@ -59,7 +59,7 @@ check_flow_not_running, filter_results, ) -from src.pipeline.shared_tasks.control_units import fetch_control_units_contacts +from src.pipeline.shared_tasks.control_units import fetch_control_units from src.pipeline.shared_tasks.dates import get_utcnow, make_timedelta from src.pipeline.shared_tasks.infrastructure import execute_statement, get_table from src.pipeline.shared_tasks.pnos import ( @@ -582,13 +582,12 @@ def attribute_addressees( pno_to_distribute: RenderedPno, units_targeting_vessels: pd.DataFrame, units_ports_and_segments_subscriptions: pd.DataFrame, - control_units_contacts: pd.DataFrame, - facade_email_addresses: dict, + control_units: List[ControlUnit], ) -> RenderedPno: """ - Returns a copy of the input `RenderedPno`'s with its `control_unit_ids`, - `email_addresses` and `phone_numbers` attributes updated, representing control - units that should receive the PNO. The control units attributed to the PNO are : + Returns a copy of the input `RenderedPno`'s with its `control_units`, + attribute updated, representing control units that should receive the PNO. + The control units attributed to the PNO are : - control units who target the vessel - control units who subscribed to the port with the "receive all pnos" @@ -606,11 +605,9 @@ def attribute_addressees( units_ports_and_segments_subscriptions (pd.DataFrame): DataFrame with columns `control_unit_id`, `port_locode`, `receive_all_pnos_from_port`, and `unit_subscribed_segments` - control_units_contacts (pd.DataFrame): DataFrame with columns - `control_unit_id`, `emails` and `phone_numbers` - facade_email_addresses (dict): dictionnary with facade names as keys and FMC facade email addresses as values. The email address of the corresponding facade will be added to addressees in PNO emails. + control_units (List[ControlUnit]): List of all active `ControlUnits` Returns: RenderedPno: copy of the input `pno_to_distribute` with addressees added @@ -663,52 +660,35 @@ def attribute_addressees( control_unit_ids = units_subscribed_to_port.union(units_targeting_vessel) - emails = sorted( - set( - chain.from_iterable( - control_units_contacts.loc[ - control_units_contacts.control_unit_id.isin(control_unit_ids), - "emails", - ].tolist() - ) - ) - ) - if emails: - facade_email_address = facade_email_addresses.get(pno_to_distribute.facade) - if facade_email_address: - emails.append(facade_email_address) - - phone_numbers = sorted( - set( - chain.from_iterable( - control_units_contacts.loc[ - control_units_contacts.control_unit_id.isin(control_unit_ids), - "phone_numbers", - ].tolist() - ) - ) - ) - return dataclasses.replace( pno_to_distribute, - control_unit_ids=control_unit_ids, - emails=emails, - phone_numbers=phone_numbers, + control_units=[ + control_unit + for control_unit in control_units + if control_unit.control_unit_id in control_unit_ids + ], ) @task(checkpoint=False) def create_email( - pno: RenderedPno, uploaded_attachments: dict, test_mode: bool + pno: RenderedPno, + uploaded_attachments: dict, + facade_email_addresses: dict, + test_mode: bool, ) -> PnoToSend: - if pno.emails: + addressees = pno.get_addressees(CommunicationMeans.EMAIL) + + if addressees: if test_mode: if PNO_TEST_EMAIL: to = PNO_TEST_EMAIL + cc = None else: return None else: - to = pno.emails + to = [addressee.email_address_or_number for addressee in addressees] + cc = facade_email_addresses.get(pno.facade) attachments = [ ( @@ -719,6 +699,7 @@ def create_email( message = create_html_email( to=to, + cc=cc, subject=f"Préavis de débarquement - {pno.vessel_name}", html=pno.html_email_body, from_=MONITORFISH_EMAIL_ADDRESS, @@ -742,14 +723,16 @@ def create_email( @task(checkpoint=False) def create_sms(pno: RenderedPno, test_mode: bool) -> PnoToSend: - if pno.phone_numbers: + addressees = pno.get_addressees(CommunicationMeans.SMS) + + if addressees: if test_mode: if CNSP_SIP_DEPARTMENT_MOBILE_PHONE: to = CNSP_SIP_DEPARTMENT_MOBILE_PHONE else: return None else: - to = pno.phone_numbers + to = [addressee.email_address_or_number for addressee in addressees] return PnoToSend( pno=pno, @@ -774,8 +757,10 @@ def send_pno_message( policy = EmailPolicy() - for addressee in pno_to_send.get_addressees(): - formatted_addressee = policy.header_factory("To", addressee) + for addressee in pno_to_send.pno.get_addressees(pno_to_send.communication_means): + formatted_addressee = policy.header_factory( + "To", addressee.email_address_or_number + ) if formatted_addressee in send_errors: success = False @@ -790,8 +775,10 @@ def send_pno_message( prior_notification_source=pno_to_send.pno.source, date_time_utc=datetime.utcnow(), communication_means=pno_to_send.communication_means, - recipient_address_or_number=addressee, + recipient_address_or_number=addressee.email_address_or_number, success=success, + recipient_name=addressee.name, + recipient_organization=addressee.organization, error_message=error_message, ) ) @@ -1025,16 +1012,11 @@ def make_manual_prior_notifications_statement( with case(generation_needed, True): # Extract - control_units_contacts = fetch_control_units_contacts() species_names = extract_species_names() fishing_gear_names = extract_fishing_gear_names() html_for_pdf_template = get_html_for_pdf_template() email_body_template = get_email_body_template() sms_template = get_sms_template() - units_targeting_vessels = extract_pno_units_targeting_vessels() - units_ports_and_segments_subscriptions = ( - extract_pno_units_ports_and_segments_subscriptions() - ) # Render pdf documents pnos_to_render = to_pnos_to_render(pnos_to_generate) @@ -1066,17 +1048,22 @@ def make_manual_prior_notifications_statement( attachments = execute_prior_notification_attachments_query(query) facade_email_addresses = extract_facade_email_addresses() + control_units = fetch_control_units() + units_targeting_vessels = extract_pno_units_targeting_vessels() + units_ports_and_segments_subscriptions = ( + extract_pno_units_ports_and_segments_subscriptions() + ) pnos_with_addressees = attribute_addressees.map( pnos_to_distribute, unmapped(units_targeting_vessels), unmapped(units_ports_and_segments_subscriptions), - control_units_contacts=unmapped(control_units_contacts), - facade_email_addresses=unmapped(facade_email_addresses), + control_units=unmapped(control_units), ) email = create_email.map( pnos_with_addressees, + facade_email_addresses=unmapped(facade_email_addresses), uploaded_attachments=unmapped(attachments), test_mode=unmapped(test_mode), ) diff --git a/datascience/src/pipeline/flows/email_actions_to_units.py b/datascience/src/pipeline/flows/email_actions_to_units.py index 43fca1a02e..7f6056c348 100644 --- a/datascience/src/pipeline/flows/email_actions_to_units.py +++ b/datascience/src/pipeline/flows/email_actions_to_units.py @@ -16,16 +16,16 @@ EMAIL_STYLESHEETS_LOCATION, EMAIL_TEMPLATES_LOCATION, ) +from src.pipeline.entities.communication_means import CommunicationMeans from src.pipeline.entities.control_units import ( + ControlUnit, ControlUnitActions, ControlUnitActionsSentMessage, - ControlUnitWithEmails, ) from src.pipeline.entities.missions import FlightGoal, MissionActionType from src.pipeline.generic_tasks import extract, load from src.pipeline.helpers.dates import Period from src.pipeline.helpers.emails import ( - CommunicationMeans, create_html_email, send_email_or_sms_or_fax_message, ) @@ -33,7 +33,7 @@ check_flow_not_running, filter_results, ) -from src.pipeline.shared_tasks.control_units import fetch_control_units_contacts +from src.pipeline.shared_tasks.control_units import fetch_control_units from src.pipeline.shared_tasks.dates import get_utcnow @@ -95,28 +95,29 @@ def get_control_unit_ids(env_action: pd.DataFrame) -> List[int]: @task(checkpoint=False) -def filter_control_units_contacts( - all_control_units_contacts: pd.DataFrame, control_unit_ids: List[str] -) -> List[ControlUnitWithEmails]: +def filter_control_units( + all_control_units: List[ControlUnit], control_unit_ids: List[str] +) -> List[ControlUnit]: if len(control_unit_ids) == 0: raise SKIP("No control units to extract.") - control_units = all_control_units_contacts.loc[ - ( - all_control_units_contacts.control_unit_id.isin(control_unit_ids) - & (all_control_units_contacts.emails.map(len) > 0) - ), - ["control_unit_id", "control_unit_name", "emails"], + filtered_control_units = [ + control_unit + for control_unit in all_control_units + if ( + (len(control_unit.emails) > 0) + and (control_unit.control_unit_id in control_unit_ids) + ) ] - records = control_units.to_dict(orient="records") - return [ControlUnitWithEmails(**control_unit) for control_unit in records] + + return filtered_control_units @task(checkpoint=False) def to_control_unit_actions( mission_actions: pd.DataFrame, period: Period, - control_units: List[ControlUnitWithEmails], + control_units: List[ControlUnit], ) -> List[ControlUnitActions]: return [ ControlUnitActions( @@ -451,15 +452,15 @@ def load_emails_sent_to_control_units( end_days_ago=end_days_ago, ) mission_actions = extract_mission_actions(period=period) - all_control_units_contacts = fetch_control_units_contacts() + all_control_units = fetch_control_units() control_unit_ids = get_control_unit_ids(mission_actions) - control_units_emails = filter_control_units_contacts( - all_control_units_contacts, control_unit_ids + control_units_with_emails = filter_control_units( + all_control_units, control_unit_ids ) control_unit_actions = to_control_unit_actions( - mission_actions, period, control_units_emails + mission_actions, period, control_units_with_emails ) html = render.map(control_unit_actions, template=unmapped(template)) diff --git a/datascience/src/pipeline/flows/notify_beacon_malfunctions.py b/datascience/src/pipeline/flows/notify_beacon_malfunctions.py index 6fdc596935..da76f3cac7 100644 --- a/datascience/src/pipeline/flows/notify_beacon_malfunctions.py +++ b/datascience/src/pipeline/flows/notify_beacon_malfunctions.py @@ -26,9 +26,9 @@ BeaconMalfunctionNotificationType, BeaconMalfunctionToNotify, ) +from src.pipeline.entities.communication_means import CommunicationMeans from src.pipeline.generic_tasks import extract, load from src.pipeline.helpers.emails import ( - CommunicationMeans, create_fax_email, create_html_email, create_sms_email, diff --git a/datascience/src/pipeline/helpers/emails.py b/datascience/src/pipeline/helpers/emails.py index 185be020ce..a9fbfb82b2 100644 --- a/datascience/src/pipeline/helpers/emails.py +++ b/datascience/src/pipeline/helpers/emails.py @@ -2,7 +2,6 @@ import io import smtplib from email.message import EmailMessage -from enum import Enum from logging import Logger from mimetypes import guess_type from pathlib import Path @@ -29,12 +28,7 @@ MONITORFISH_SMS_SERVER_PORT, MONITORFISH_SMS_SERVER_URL, ) - - -class CommunicationMeans(Enum): - EMAIL = "EMAIL" - SMS = "SMS" - FAX = "FAX" +from src.pipeline.entities.communication_means import CommunicationMeans def create_html_email( @@ -393,6 +387,8 @@ def send_email_or_sms_or_fax_message( suffix = "" send_errors = {k.removesuffix(suffix): v for k, v in send_errors.items()} + if send_errors: + logger.error(send_errors) return send_errors diff --git a/datascience/src/pipeline/shared_tasks/control_units.py b/datascience/src/pipeline/shared_tasks/control_units.py index daa05050b9..30153fcef3 100644 --- a/datascience/src/pipeline/shared_tasks/control_units.py +++ b/datascience/src/pipeline/shared_tasks/control_units.py @@ -1,13 +1,16 @@ +from typing import List + import pandas as pd import requests from prefect import task from config import MONITORENV_API_ENDPOINT +from src.pipeline.entities.control_units import ControlUnit from src.pipeline.processing import remove_nones_from_list @task(checkpoint=False) -def fetch_control_units_contacts() -> pd.DataFrame: +def fetch_control_units() -> List[ControlUnit]: r = requests.get(MONITORENV_API_ENDPOINT + "control_units") r.raise_for_status() @@ -18,14 +21,21 @@ def fetch_control_units_contacts() -> pd.DataFrame: "name": "control_unit_name", "controlUnitContacts": "control_unit_contacts", "isArchived": "is_archived", + "administration": "administration", } df = df[columns.keys()].rename(columns=columns) + df["administration"] = df.administration.map(lambda d: d.get("name")) contacts = ( df.loc[ ~df.is_archived, - ["control_unit_id", "control_unit_name", "control_unit_contacts"], + [ + "control_unit_id", + "control_unit_name", + "administration", + "control_unit_contacts", + ], ] .explode("control_unit_contacts") .dropna() @@ -44,9 +54,11 @@ def fetch_control_units_contacts() -> pd.DataFrame: ) email_and_phone_contacts = ( - contacts[["control_unit_id", "control_unit_name", "email", "phone"]] + contacts[ + ["control_unit_id", "control_unit_name", "administration", "email", "phone"] + ] .dropna(subset=["email", "phone"], how="all") - .groupby(["control_unit_id", "control_unit_name"]) + .groupby(["control_unit_id", "control_unit_name", "administration"]) .agg({"email": "unique", "phone": "unique"}) .rename(columns={"email": "emails", "phone": "phone_numbers"}) .map(remove_nones_from_list) @@ -54,4 +66,5 @@ def fetch_control_units_contacts() -> pd.DataFrame: .reset_index() ) - return email_and_phone_contacts + records = email_and_phone_contacts.to_dict(orient="records") + return [ControlUnit(**control_unit) for control_unit in records] diff --git a/datascience/tests/test_pipeline/conftest.py b/datascience/tests/test_pipeline/conftest.py index 73c9b22293..4661ec3437 100644 --- a/datascience/tests/test_pipeline/conftest.py +++ b/datascience/tests/test_pipeline/conftest.py @@ -1,6 +1,8 @@ import pandas as pd import pytest +from src.pipeline.entities.control_units import ControlUnit + @pytest.fixture def pno_units_targeting_vessels(): @@ -54,6 +56,11 @@ def monitorenv_control_units_api_response() -> list: return [ { "id": 1, + "administration": { + "id": 1, + "isArchived": False, + "name": "Administration 1", + }, "controlUnitContacts": [], "isArchived": False, "name": "Unité 1", @@ -62,6 +69,11 @@ def monitorenv_control_units_api_response() -> list: }, { "id": 2, + "administration": { + "id": 1, + "isArchived": False, + "name": "Administration 1", + }, "controlUnitContacts": [ { "id": 559, @@ -109,6 +121,11 @@ def monitorenv_control_units_api_response() -> list: }, { "id": 3, + "administration": { + "id": 1, + "isArchived": False, + "name": "Administration 1", + }, "controlUnitContacts": [ { "id": 320, @@ -143,6 +160,11 @@ def monitorenv_control_units_api_response() -> list: }, { "id": 4, + "administration": { + "id": 3, + "isArchived": False, + "name": "Administration 3", + }, "controlUnitContacts": [ { "id": 1182, @@ -176,6 +198,11 @@ def monitorenv_control_units_api_response() -> list: }, { "id": 5, + "administration": { + "id": 1, + "isArchived": False, + "name": "Administration 1", + }, "controlUnitContacts": [ { "id": 382, @@ -219,6 +246,11 @@ def monitorenv_control_units_api_response() -> list: }, { "id": 6, + "administration": { + "id": 1, + "isArchived": False, + "name": "Administration 1", + }, "controlUnitContacts": [ { "id": 631, @@ -252,6 +284,11 @@ def monitorenv_control_units_api_response() -> list: }, { "id": 7, + "administration": { + "id": 1, + "isArchived": False, + "name": "Administration 1", + }, "controlUnitContacts": [ { "id": 1540, @@ -270,20 +307,27 @@ def monitorenv_control_units_api_response() -> list: @pytest.fixture -def control_units_contacts() -> pd.DataFrame: - return pd.DataFrame( - { - "control_unit_id": [2, 3, 4], - "control_unit_name": ["Unité 2", "Unité 3", "Unité 4"], - "emails": [ - ["alternative@email", "some.email@control.unit.4"], - [], - ["email4@email.com"], - ], - "phone_numbers": [ - ["'00 11 22 33 44 55"], - ["44 44 44 44 44"], - [], - ], - } - ) +def monitorenv_control_units() -> pd.DataFrame: + return [ + ControlUnit( + control_unit_id=2, + control_unit_name="Unité 2", + administration="Administration 1", + emails=["alternative@email", "some.email@control.unit.4"], + phone_numbers=["'00 11 22 33 44 55"], + ), + ControlUnit( + control_unit_id=3, + control_unit_name="Unité 3", + administration="Administration 1", + emails=[], + phone_numbers=["44 44 44 44 44"], + ), + ControlUnit( + control_unit_id=4, + control_unit_name="Unité 4", + administration="Administration 3", + emails=["email4@email.com"], + phone_numbers=[], + ), + ] diff --git a/datascience/tests/test_pipeline/test_entities/test_beacon_malfunctions.py b/datascience/tests/test_pipeline/test_entities/test_beacon_malfunctions.py index d36e76d05b..8378b76e29 100644 --- a/datascience/tests/test_pipeline/test_entities/test_beacon_malfunctions.py +++ b/datascience/tests/test_pipeline/test_entities/test_beacon_malfunctions.py @@ -11,7 +11,7 @@ BeaconMalfunctionNotificationType, BeaconMalfunctionToNotify, ) -from src.pipeline.helpers.emails import CommunicationMeans +from src.pipeline.entities.communication_means import CommunicationMeans @fixture diff --git a/datascience/tests/test_pipeline/test_flows/test_distribute_pnos.py b/datascience/tests/test_pipeline/test_flows/test_distribute_pnos.py index 5f28c5adee..a00c23d7ce 100644 --- a/datascience/tests/test_pipeline/test_flows/test_distribute_pnos.py +++ b/datascience/tests/test_pipeline/test_flows/test_distribute_pnos.py @@ -29,6 +29,8 @@ from config import EMAIL_IMAGES_LOCATION, TEST_DATA_LOCATION, default_risk_factors from src.db_config import create_engine +from src.pipeline.entities.communication_means import CommunicationMeans +from src.pipeline.entities.control_units import ControlUnit from src.pipeline.entities.fleet_segments import FishingGear, FleetSegment from src.pipeline.entities.missions import Infraction from src.pipeline.entities.pnos import ( @@ -62,7 +64,6 @@ send_pno_message, to_pnos_to_render, ) -from src.pipeline.helpers.emails import CommunicationMeans from src.read_query import read_query from tests.mocks import mock_check_flow_not_running, mock_datetime_utcnow @@ -926,7 +927,6 @@ def pno_pdf_document_to_distribute_targeted_vessel_and_segments() -> RenderedPno source=PnoSource.MANUAL, generation_datetime_utc=datetime(2023, 5, 6, 23, 52, 0), pdf_document=b"PDF Document", - control_unit_ids=None, sms_content="Message SMS préavis 123-abc", html_email_body="Ce navire va débarquer", ) @@ -938,9 +938,22 @@ def pno_pdf_document_to_distribute_targeted_vessel_and_segments_assigned( ) -> RenderedPno: return dataclasses.replace( pno_pdf_document_to_distribute_targeted_vessel_and_segments, - control_unit_ids={1, 2, 3}, - phone_numbers=["'00 11 22 33 44 55", "44 44 44 44 44"], - emails=["alternative@email", "some.email@control.unit.4", "namo@email"], + control_units=[ + ControlUnit( + control_unit_id=2, + control_unit_name="Unité 2", + administration="Administration 1", + emails=["alternative@email", "some.email@control.unit.4"], + phone_numbers=["'00 11 22 33 44 55"], + ), + ControlUnit( + control_unit_id=3, + control_unit_name="Unité 3", + administration="Administration 1", + emails=[], + phone_numbers=["44 44 44 44 44"], + ), + ], ) @@ -959,7 +972,6 @@ def pno_pdf_document_to_distribute_receive_all_pnos_from_port() -> RenderedPno: source=PnoSource.MANUAL, generation_datetime_utc=datetime(2023, 6, 6, 23, 50, 0), pdf_document=b"PDF Document", - control_unit_ids=None, ) @@ -969,9 +981,15 @@ def pno_pdf_document_to_distribute_receive_all_pnos_from_port_assigned( ) -> RenderedPno: return dataclasses.replace( pno_pdf_document_to_distribute_receive_all_pnos_from_port, - control_unit_ids={4}, - emails=["email4@email.com"], - phone_numbers=[], + control_units=[ + ControlUnit( + control_unit_id=4, + control_unit_name="Unité 4", + administration="Administration 3", + emails=["email4@email.com"], + phone_numbers=[], + ) + ], ) @@ -990,7 +1008,6 @@ def pno_pdf_document_to_distribute_without_addressees() -> RenderedPno: source=PnoSource.MANUAL, generation_datetime_utc=datetime(2023, 6, 6, 23, 50, 0), pdf_document=b"PDF Document", - control_unit_ids=None, ) @@ -1000,9 +1017,10 @@ def pno_pdf_document_to_distribute_without_addressees_assigned( ) -> RenderedPno: return dataclasses.replace( pno_pdf_document_to_distribute_without_addressees, - control_unit_ids=set(), - emails=[], - phone_numbers=[], + control_units=[], + # control_unit_ids=set(), + # emails=[], + # phone_numbers=[], ) @@ -1021,7 +1039,6 @@ def pno_pdf_document_to_distribute_verified() -> RenderedPno: source=PnoSource.LOGBOOK, generation_datetime_utc=datetime(2023, 6, 6, 23, 50, 0), pdf_document=b"PDF Document", - control_unit_ids=None, ) @@ -1031,9 +1048,22 @@ def pno_pdf_document_to_distribute_verified_assigned( ) -> RenderedPno: return dataclasses.replace( pno_pdf_document_to_distribute_verified, - control_unit_ids={2, 3}, - emails=["alternative@email", "some.email@control.unit.4", "namo@email"], - phone_numbers=["'00 11 22 33 44 55", "44 44 44 44 44"], + control_units=[ + ControlUnit( + control_unit_id=2, + control_unit_name="Unité 2", + administration="Administration 1", + emails=["alternative@email", "some.email@control.unit.4"], + phone_numbers=["'00 11 22 33 44 55"], + ), + ControlUnit( + control_unit_id=3, + control_unit_name="Unité 3", + administration="Administration 1", + emails=[], + phone_numbers=["44 44 44 44 44"], + ), + ], ) @@ -1100,9 +1130,22 @@ def logbook_rendered_pno(): generation_datetime_utc=datetime(2023, 5, 6, 12, 52, 12), html_email_body="Hello this is a prior notification", sms_content="Hello, PNO", - control_unit_ids=[1, 2], - emails=["email1@control.unit", "email.in.error@control.unit"], - phone_numbers=["00000000000"], + control_units=[ + ControlUnit( + control_unit_id=1, + control_unit_name="Unité de test numero 1", + administration="Une Administration quelconque", + emails=["email1@control.unit"], + phone_numbers=[], + ), + ControlUnit( + control_unit_id=2, + control_unit_name="Unité de test numero 2", + administration="Une autre Administration", + emails=["email.in.error@control.unit"], + phone_numbers=["00000000000"], + ), + ], ) @@ -1124,9 +1167,18 @@ def manual_rendered_pno(): generation_datetime_utc=datetime(2023, 5, 4, 8, 42, 26), html_email_body="Hello this is a manual prior notification", sms_content="Hello, PNO manual", - control_unit_ids=[3], - emails=["manual.email1@control.unit", "manual.email.in.error@control.unit"], - phone_numbers=["11111111111"], + control_units=[ + ControlUnit( + control_unit_id=3, + control_unit_name="Unité n°3", + administration="Administration de l'unité 3", + emails=[ + "manual.email1@control.unit", + "manual.email.in.error@control.unit", + ], + phone_numbers=["11111111111"], + ) + ], ) @@ -1147,6 +1199,8 @@ def messages_sent_by_email() -> List[PriorNotificationSentMessage]: prior_notification_source=PnoSource.LOGBOOK, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.EMAIL, + recipient_name="Unité de test numero 1", + recipient_organization="Une Administration quelconque", recipient_address_or_number="email1@control.unit", success=True, error_message=None, @@ -1156,6 +1210,8 @@ def messages_sent_by_email() -> List[PriorNotificationSentMessage]: prior_notification_source=PnoSource.LOGBOOK, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.EMAIL, + recipient_name="Unité de test numero 2", + recipient_organization="Une autre Administration", recipient_address_or_number="email.in.error@control.unit", success=False, error_message="Error when sending email", @@ -1178,6 +1234,8 @@ def messages_sent_by_sms() -> List[PriorNotificationSentMessage]: prior_notification_source=PnoSource.LOGBOOK, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.SMS, + recipient_name="Unité de test numero 2", + recipient_organization="Une autre Administration", recipient_address_or_number="00000000000", success=True, error_message=None, @@ -1198,6 +1256,8 @@ def some_more_sent_messages( prior_notification_source=PnoSource.MANUAL, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.SMS, + recipient_name="Someone", + recipient_organization="Somewhere", recipient_address_or_number="00000000000", success=True, error_message=None, @@ -1207,6 +1267,8 @@ def some_more_sent_messages( prior_notification_source=PnoSource.LOGBOOK, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.SMS, + recipient_name="Someone", + recipient_organization="Somewhere", recipient_address_or_number="00000000000", success=False, error_message=None, @@ -1216,6 +1278,8 @@ def some_more_sent_messages( prior_notification_source=PnoSource.LOGBOOK, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.SMS, + recipient_name="Someone", + recipient_organization="Somewhere", recipient_address_or_number="00000000000", success=True, error_message=None, @@ -1225,6 +1289,8 @@ def some_more_sent_messages( prior_notification_source=PnoSource.MANUAL, date_time_utc=datetime(2023, 6, 6, 16, 10), communication_means=CommunicationMeans.SMS, + recipient_name="Someone", + recipient_organization="Somewhere", recipient_address_or_number="00000000000", success=False, error_message=None, @@ -1253,6 +1319,16 @@ def loaded_sent_messages() -> pd.DataFrame: ], "success": [True, False, True], "error_message": [None, "Error when sending email", None], + "recipient_name": [ + "Unité de test numero 1", + "Unité de test numero 2", + "Unité de test numero 2", + ], + "recipient_organization": [ + "Une Administration quelconque", + "Une autre Administration", + "Une autre Administration", + ], } ) @@ -1657,15 +1733,13 @@ def test_attribute_addressees_uses_target_vessels_and_segments( pno_pdf_document_to_distribute_targeted_vessel_and_segments_assigned, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ): res = attribute_addressees.run( pno_pdf_document_to_distribute_targeted_vessel_and_segments, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ) assert res == pno_pdf_document_to_distribute_targeted_vessel_and_segments_assigned @@ -1675,15 +1749,13 @@ def test_attribute_addressees_uses_receive_all_pnos_from_port( pno_pdf_document_to_distribute_receive_all_pnos_from_port_assigned, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ): res = attribute_addressees.run( pno_pdf_document_to_distribute_receive_all_pnos_from_port, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ) assert res == pno_pdf_document_to_distribute_receive_all_pnos_from_port_assigned @@ -1693,15 +1765,13 @@ def test_attribute_addressees_returns_empty_addressees( pno_pdf_document_to_distribute_without_addressees_assigned, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ): res = attribute_addressees.run( pno_pdf_document_to_distribute_without_addressees, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ) assert res == pno_pdf_document_to_distribute_without_addressees_assigned @@ -1711,15 +1781,13 @@ def test_attribute_addressees_when_is_verified( pno_pdf_document_to_distribute_verified_assigned, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ): res = attribute_addressees.run( pno_pdf_document_to_distribute_verified, pno_units_targeting_vessels, pno_units_ports_and_segments_subscriptions, - control_units_contacts, - facade_email_addresses, + monitorenv_control_units, ) assert res == pno_pdf_document_to_distribute_verified_assigned @@ -1768,6 +1836,7 @@ def test_create_email( marianne_gif, liberte_egalite_fraternite_gif, prior_notification_attachments, + facade_email_addresses, test_mode, pno_has_uploaded_attachments, ): @@ -1776,6 +1845,7 @@ def test_create_email( uploaded_attachments=prior_notification_attachments if pno_has_uploaded_attachments else dict(), + facade_email_addresses=facade_email_addresses, test_mode=test_mode, ) @@ -1788,13 +1858,13 @@ def test_create_email( assert isinstance(pno_to_send.message, EmailMessage) if test_mode: assert pno_to_send.message["To"] == "pno.test@email.fr" + assert pno_to_send.message["Cc"] is None else: assert ( - pno_to_send.message["To"] - == "alternative@email, some.email@control.unit.4, namo@email" + pno_to_send.message["To"] == "alternative@email, some.email@control.unit.4" ) + assert pno_to_send.message["Cc"] == "namo@email" assert pno_to_send.message["From"] == "monitorfish@test.email" - assert pno_to_send.message["Cc"] is None assert pno_to_send.message["Bcc"] is None assert pno_to_send.message["Reply-To"] == "cnsp.france@test.email" assert ( @@ -1852,11 +1922,13 @@ def test_create_email( def test_create_email_with_no_email_addressees_returns_none( pno_pdf_document_to_distribute_without_addressees_assigned, prior_notification_attachments, + facade_email_addresses, test_mode, ): pno_to_send = create_email.run( pno_pdf_document_to_distribute_without_addressees_assigned, uploaded_attachments=prior_notification_attachments, + facade_email_addresses=facade_email_addresses, test_mode=test_mode, ) assert pno_to_send is None @@ -2136,7 +2208,7 @@ class UnexpectedFailureOfDeath(Exception): assert len(initial_pdf_documents) == 8 assert len(initial_sent_messages) == 0 assert len(final_pdf_documents) == 14 - assert len(final_sent_messages) == 15 + assert len(final_sent_messages) == 12 if is_integration: assert final_sent_messages.success.all() @@ -2159,7 +2231,7 @@ class UnexpectedFailureOfDeath(Exception): == CommunicationMeans.EMAIL.value ] ) - == 10 + == 7 ) assert final_sent_messages.loc[ ( diff --git a/datascience/tests/test_pipeline/test_flows/test_email_actions_to_units.py b/datascience/tests/test_pipeline/test_flows/test_email_actions_to_units.py index 0790009c55..424c94a99a 100644 --- a/datascience/tests/test_pipeline/test_flows/test_email_actions_to_units.py +++ b/datascience/tests/test_pipeline/test_flows/test_email_actions_to_units.py @@ -17,16 +17,16 @@ TEST_DATA_LOCATION, ) from src.pipeline.entities.control_units import ( + ControlUnit, ControlUnitActions, ControlUnitActionsSentMessage, - ControlUnitWithEmails, ) from src.pipeline.entities.missions import FlightGoal from src.pipeline.flows.email_actions_to_units import ( control_unit_actions_list_to_df, create_email, extract_mission_actions, - filter_control_units_contacts, + filter_control_units, flow, get_actions_period, get_control_unit_ids, @@ -44,28 +44,33 @@ @task(checkpoint=False) -def mock_fetch_control_units_contacts(): - return pd.DataFrame( - { - "control_unit_id": [3, 5, 8], - "control_unit_name": ["Unité 3", "Unité 5", "Unité 8"], - "emails": [ - ["alternative@email", "some.email@control.unit.4"], - [], - ["email8@email.com"], - ], - "phone_numbers": [ - ["'00 11 22 33 44 55"], - ["44 44 44 44 44"], - [], - ], - } - ) +def mock_fetch_control_units(): + return [ + ControlUnit( + control_unit_id=3, + control_unit_name="Unité 3", + administration="Administration 1", + emails=["alternative@email", "some.email@control.unit.4"], + phone_numbers=["'00 11 22 33 44 55"], + ), + ControlUnit( + control_unit_id=5, + control_unit_name="Unité 5", + administration="Administration 2", + emails=[], + phone_numbers=["44 44 44 44 44"], + ), + ControlUnit( + control_unit_id=8, + control_unit_name="Unité 8", + administration="Administration 3", + emails=["email8@email.com"], + phone_numbers=[], + ), + ] -flow.replace( - flow.get_tasks("fetch_control_units_contacts")[0], mock_fetch_control_units_contacts -) +flow.replace(flow.get_tasks("fetch_control_units")[0], mock_fetch_control_units) @pytest.fixture @@ -310,44 +315,39 @@ def expected_control_unit_ids() -> List[int]: @pytest.fixture def sample_control_units() -> pd.DataFrame: return [ - ControlUnitWithEmails( + ControlUnit( control_unit_id=3, control_unit_name="Unité 3", + administration="Administration 1", emails=["unité_3@email.fr", "unité_3_bis@email.fr"], + phone_numbers=[], ), - ControlUnitWithEmails( - control_unit_id=5, control_unit_name="Unité 5", emails=["unité_5@email.fr"] + ControlUnit( + control_unit_id=5, + control_unit_name="Unité 5", + administration="Administration 3", + emails=["unité_5@email.fr"], + phone_numbers=["0600"], ), - ControlUnitWithEmails( + ControlUnit( control_unit_id=8, control_unit_name="Unité 8", + administration="Administration 2", emails=["unité_8@email.fr", "unité_8_bis@email.fr"], + phone_numbers=["0700"], ), ] -@pytest.fixture -def expected_all_control_units() -> pd.DataFrame: - return pd.DataFrame( - { - "control_unit_id": [10002, 10018, 10019], - "control_unit_name": ["DML – DDTM 59", "P602 Verdon", "BN Toulon"], - "email_addresses": [ - ["dml59@surveillance.fr"], - ["diffusion.p602@email.fr", "diffusion_bis.p602@email.fr"], - ["bn_toulon@email.fr"], - ], - } - ) - - @pytest.fixture def sample_control_unit_actions(sample_mission_actions) -> ControlUnitActions: return ControlUnitActions( - control_unit=ControlUnitWithEmails( + control_unit=ControlUnit( control_unit_id=13, control_unit_name="Nom de l'unité", + administration="Administration 1", emails=["email@email.com", "email2@email.com"], + phone_numbers=[], ), period=Period( start=datetime(2020, 6, 23, 0, 0, 0), @@ -493,16 +493,18 @@ def test_get_control_unit_ids(expected_mission_actions, expected_control_unit_id assert ids == expected_control_unit_ids -def test_filter_control_units_contacts(control_units_contacts): - res = filter_control_units_contacts.run( - all_control_units_contacts=control_units_contacts, control_unit_ids=[2, 3] +def test_filter_control_units_contacts(monitorenv_control_units): + res = filter_control_units.run( + all_control_units=monitorenv_control_units, control_unit_ids=[2, 3] ) assert res == [ - ControlUnitWithEmails( + ControlUnit( control_unit_id=2, control_unit_name="Unité 2", + administration="Administration 1", emails=["alternative@email", "some.email@control.unit.4"], + phone_numbers=["'00 11 22 33 44 55"], ) ] diff --git a/datascience/tests/test_pipeline/test_flows/test_notify_beacon_malfunctions.py b/datascience/tests/test_pipeline/test_flows/test_notify_beacon_malfunctions.py index a734d085cb..af1cba0be8 100644 --- a/datascience/tests/test_pipeline/test_flows/test_notify_beacon_malfunctions.py +++ b/datascience/tests/test_pipeline/test_flows/test_notify_beacon_malfunctions.py @@ -21,6 +21,7 @@ BeaconMalfunctionNotificationType, BeaconMalfunctionToNotify, ) +from src.pipeline.entities.communication_means import CommunicationMeans from src.pipeline.flows.notify_beacon_malfunctions import ( create_email, create_fax, @@ -35,7 +36,6 @@ send_beacon_malfunction_message, to_malfunctions_to_notify_list, ) -from src.pipeline.helpers.emails import CommunicationMeans from src.read_query import read_query from tests.mocks import mock_check_flow_not_running, mock_datetime_utcnow diff --git a/datascience/tests/test_pipeline/test_shared_tasks/test_control_units.py b/datascience/tests/test_pipeline/test_shared_tasks/test_control_units.py index 3f3b5c1937..bc589033a3 100644 --- a/datascience/tests/test_pipeline/test_shared_tasks/test_control_units.py +++ b/datascience/tests/test_pipeline/test_shared_tasks/test_control_units.py @@ -1,15 +1,14 @@ import json from unittest.mock import patch -import pandas as pd from requests import Response -from src.pipeline.shared_tasks.control_units import fetch_control_units_contacts +from src.pipeline.shared_tasks.control_units import fetch_control_units @patch("src.pipeline.shared_tasks.control_units.requests") def test_fetch_control_units_contacts( - mock_requests, monitorenv_control_units_api_response, control_units_contacts + mock_requests, monitorenv_control_units_api_response, monitorenv_control_units ): response = Response() response.status_code = 200 @@ -19,5 +18,5 @@ def test_fetch_control_units_contacts( response.encoding = "utf-8" mock_requests.get.return_value = response - res = fetch_control_units_contacts.run() - pd.testing.assert_frame_equal(res, control_units_contacts) + res = fetch_control_units.run() + assert res == monitorenv_control_units diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts index e676e4fd88..f0cc0533e9 100644 --- a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/error_handling.spec.ts @@ -4,9 +4,10 @@ import { editSideWindowPriorNotification } from './utils' context('Side Window > Logbook Prior Notification Form > Error Handling', () => { const failedQueryCount = RTK_MAX_RETRIES + 1 - const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' it('Should handle fetching error as expected', () => { + const url = '/bff/v1/prior_notifications/FAKE_OPERATION_109_COR?isManuallyCreated=false&operationDate=*' + cy.intercept( { method: 'GET', @@ -32,4 +33,30 @@ context('Side Window > Logbook Prior Notification Form > Error Handling', () => cy.contains(`L'ANCRE SÈCHE (CFR106)`).should('be.visible') }) + + it('Should handle sent message list fetching error as expected', () => { + const url = '/bff/v1/prior_notifications/FAKE_OPERATION_108/sent_messages' + + cy.intercept( + { + method: 'GET', + times: failedQueryCount, + url + }, + { + statusCode: 400 + } + ).as('getPriorNotificationSentMessagesWithError') + + editSideWindowPriorNotification(`CALAMARO`, 'FAKE_OPERATION_108') + + cy.clickButton('Voir les détails de la diffusion du préavis', { withoutScroll: true }) + + for (let i = 1; i <= failedQueryCount; i += 1) { + cy.wait('@getPriorNotificationSentMessagesWithError') + } + + cy.contains(`Impossible de récupérer la liste.`).should('be.visible') + cy.contains(`Impossible de récupérer l’historique.`).should('be.visible') + }) }) diff --git a/frontend/cypress/e2e/side_window/logbook_prior_notification_form/sent_message_list.spec.ts b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/sent_message_list.spec.ts new file mode 100644 index 0000000000..e42423f35e --- /dev/null +++ b/frontend/cypress/e2e/side_window/logbook_prior_notification_form/sent_message_list.spec.ts @@ -0,0 +1,41 @@ +import { editSideWindowPriorNotification } from './utils' + +context('Side Window > Logbook Prior Notification Form > Sent Message List', () => { + it('Should display the expected list of subscribers and sent messages history', () => { + editSideWindowPriorNotification(`CALAMARO`, 'FAKE_OPERATION_108') + + cy.intercept('GET', `/bff/v1/prior_notifications/FAKE_OPERATION_108/sent_messages`).as( + 'getPriorNotificationSentMessages' + ) + + cy.clickButton('Voir les détails de la diffusion du préavis') + + cy.wait('@getPriorNotificationSentMessages') + + cy.get('address').eq(0).contains('Unité 3 (Gendarmerie)') + cy.get('address').eq(0).contains('pgmarc720.lorient@gendarmerie.defense.gouv.fr') + cy.get('address').eq(0).contains('+33123456789') + + cy.get('address').eq(1).contains('Unité 4 (Gendarmerie)') + cy.get('address').eq(1).contains('ggmaratlan@gendarmerie.defense.gouv.fr') + cy.get('address').eq(1).contains('+33987654321') + + // The last sent message doesn't include this unit contact details, + // they should not be displayed since they likely were unsubscribed in the meantime. + cy.get('address').contains('Unité 5 (DDTM 40)').should('not.exist') + + cy.getDataCy('SentMessageList-historyItem') + .eq(0) + .contains( + 'Échec de la diffusion pour tous les contacts: pgmarc720.lorient@gendarmerie.defense.gouv.fr, +33987654321, +33123456789, ggmaratlan@gendarmerie.defense.gouv.fr.' + ) + + cy.getDataCy('SentMessageList-historyItem') + .eq(1) + .contains( + 'Échec de la diffusion pour les contacts: +33000000000, +33987654321, unite5@ddtm-40.gouv.fr, pgmarc720.lorient@gendarmerie.defense.gouv.fr.' + ) + + cy.getDataCy('SentMessageList-historyItem').eq(2).contains('Préavis diffusé avec succès à tous les contacts.') + }) +}) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index be7ab4c4ac..8d370c8183 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@dnd-kit/core": "6.1.0", "@dnd-kit/modifiers": "6.0.1", - "@mtes-mct/monitor-ui": "23.1.3", + "@mtes-mct/monitor-ui": "23.3.0", "@reduxjs/toolkit": "2.2.7", "@sentry/react": "7.117.0", "@tanstack/react-table": "8.20.5", @@ -1057,1287 +1057,1199 @@ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", "license": "MIT" }, - "node_modules/@esbuild/aix-ppc64": { + "node_modules/@esbuild/linux-x64": { "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", - "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", + "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", "cpu": [ - "ppc64" + "x64" ], "dev": true, "optional": true, "os": [ - "aix" + "linux" ], "engines": { "node": ">=18" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", - "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", - "cpu": [ - "arm" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", - "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", - "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, - "optional": true, - "os": [ - "android" - ], + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", - "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/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, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } + "license": "Python-2.0" }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", - "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", - "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", - "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/eslintrc/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, - "optional": true, - "os": [ - "freebsd" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", - "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=18" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", - "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/js": { + "version": "8.56.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", + "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", - "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", - "cpu": [ - "ia32" - ], + "node_modules/@faker-js/faker": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", + "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", "dev": true, - "optional": true, - "os": [ - "linux" + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/fakerjs" + } ], + "license": "MIT", "engines": { - "node": ">=18" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=6.14.13" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", - "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@floating-ui/core": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.7" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", - "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", - "cpu": [ - "mips64el" - ], + "node_modules/@floating-ui/dom": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, "engines": { - "node": ">=18" + "node": ">=10.10.0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", - "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", - "cpu": [ - "ppc64" - ], + "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, - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", "engines": { - "node": ">=18" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", - "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", - "cpu": [ - "riscv64" - ], + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } + "license": "BSD-3-Clause" }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", - "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "node_modules/@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", + "license": "MIT", + "peerDependencies": { + "react": "*" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", - "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", - "cpu": [ - "x64" - ], + "node_modules/@import-meta-env/cli": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@import-meta-env/cli/-/cli-0.7.0.tgz", + "integrity": "sha512-2ARV8ZSqdB3Oh9MYyh2JlGVV16IjqlXfmyRbp2Fng8geONWh5SGPZwXLFjsqj4z1LN5KYfdDgL6dSz9PV+CxWQ==", "dev": true, - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "commander": "12.1.0", + "dotenv": "^16.0.0", + "glob": "11.0.0", + "picocolors": "1.0.1", + "serialize-javascript": "6.0.2" + }, + "bin": { + "import-meta-env": "bin/import-meta-env.js" + }, "engines": { - "node": ">=18" + "node": ">= 14" + }, + "peerDependencies": { + "@import-meta-env/babel": "^0.5.0", + "@import-meta-env/swc": "^0.4.5", + "@import-meta-env/unplugin": "0.6.0" + }, + "peerDependenciesMeta": { + "@import-meta-env/babel": { + "optional": true + }, + "@import-meta-env/swc": { + "optional": true + }, + "@import-meta-env/unplugin": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", - "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", - "cpu": [ - "x64" - ], + "node_modules/@import-meta-env/prepare": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@import-meta-env/prepare/-/prepare-0.2.0.tgz", + "integrity": "sha512-n5/0PUS1swCgsen8dUx3JCy6EW4dZv1izXjuJF8pe2y9F5VMtfHso3Ov8+2lqKNOZOsm60KMewN9XUCubYFI6g==", "dev": true, - "optional": true, - "os": [ - "netbsd" - ], + "dependencies": { + "commander": "12.1.0", + "dotenv": "^16.0.0", + "glob": "11.0.0", + "picocolors": "1.0.1", + "serialize-javascript": "6.0.2" + }, + "bin": { + "import-meta-env-prepare": "bin/import-meta-env-prepare.js" + }, "engines": { - "node": ">=18" + "node": ">= 14" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", - "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", - "cpu": [ - "arm64" - ], + "node_modules/@import-meta-env/unplugin": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@import-meta-env/unplugin/-/unplugin-0.6.0.tgz", + "integrity": "sha512-oKttBqTQpAK0D6iWSR952L58+86GW7EMhfHD1ueF7xwJxfbIikvNa+oNIvdinr46m9g0aaHA0XywpZTGCCwm+g==", "dev": true, - "optional": true, - "os": [ - "openbsd" - ], + "hasInstallScript": true, + "dependencies": { + "dotenv": "^16.0.0", + "magic-string": "^0.30.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "unplugin": "^1.5.0" + }, "engines": { - "node": ">=18" + "node": ">= 14" + }, + "peerDependencies": { + "@import-meta-env/cli": "^0.7.0" + }, + "peerDependenciesMeta": { + "@import-meta-env/cli": { + "optional": true + } } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", - "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", - "cpu": [ - "x64" - ], + "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, - "optional": true, - "os": [ - "openbsd" - ], + "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": ">=18" + "node": ">=12" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", - "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", - "cpu": [ - "x64" - ], + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "optional": true, - "os": [ - "sunos" - ], + "license": "MIT", "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", - "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", - "cpu": [ - "arm64" - ], + "node_modules/@isaacs/cliui/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, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", - "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", - "cpu": [ - "ia32" - ], + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, "engines": { - "node": ">=18" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", - "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", - "cpu": [ - "x64" - ], + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, - "optional": true, - "os": [ - "win32" - ], + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, "engines": { - "node": ">=18" + "node": ">=8" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=8" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", - "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=8" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "p-try": "^2.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "p-limit": "^2.2.0" }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", "dev": true, "license": "MIT", "dependencies": { - "argparse": "^2.0.1" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@eslint/eslintrc/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/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", "dev": true, "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@faker-js/faker": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/@faker-js/faker/-/faker-8.4.1.tgz", - "integrity": "sha512-XQ3cU+Q8Uqmrbf2e0cIC/QN43sTBSC8KF12u29Mb47tWrt2hAgBXSgpZMj4Ao8Uk0iJcU99QsOCaIL8934obCg==", + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/fakerjs" - } - ], "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0", - "npm": ">=6.14.13" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/core": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", - "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.7" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/dom": { - "version": "1.6.10", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", - "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.7" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@floating-ui/utils": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", - "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==", - "license": "MIT" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "jest-get-type": "^29.6.3" }, "engines": { - "node": ">=10.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.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/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@icons/material": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", - "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", "license": "MIT", - "peerDependencies": { - "react": "*" - } - }, - "node_modules/@import-meta-env/cli": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@import-meta-env/cli/-/cli-0.7.0.tgz", - "integrity": "sha512-2ARV8ZSqdB3Oh9MYyh2JlGVV16IjqlXfmyRbp2Fng8geONWh5SGPZwXLFjsqj4z1LN5KYfdDgL6dSz9PV+CxWQ==", - "dev": true, - "dependencies": { - "commander": "12.1.0", - "dotenv": "^16.0.0", - "glob": "11.0.0", - "picocolors": "1.0.1", - "serialize-javascript": "6.0.2" - }, - "bin": { - "import-meta-env": "bin/import-meta-env.js" - }, - "engines": { - "node": ">= 14" - }, - "peerDependencies": { - "@import-meta-env/babel": "^0.5.0", - "@import-meta-env/swc": "^0.4.5", - "@import-meta-env/unplugin": "0.6.0" - }, - "peerDependenciesMeta": { - "@import-meta-env/babel": { - "optional": true - }, - "@import-meta-env/swc": { - "optional": true - }, - "@import-meta-env/unplugin": { - "optional": true - } - } - }, - "node_modules/@import-meta-env/prepare": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@import-meta-env/prepare/-/prepare-0.2.0.tgz", - "integrity": "sha512-n5/0PUS1swCgsen8dUx3JCy6EW4dZv1izXjuJF8pe2y9F5VMtfHso3Ov8+2lqKNOZOsm60KMewN9XUCubYFI6g==", - "dev": true, "dependencies": { - "commander": "12.1.0", - "dotenv": "^16.0.0", - "glob": "11.0.0", - "picocolors": "1.0.1", - "serialize-javascript": "6.0.2" - }, - "bin": { - "import-meta-env-prepare": "bin/import-meta-env-prepare.js" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">= 14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@import-meta-env/unplugin": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@import-meta-env/unplugin/-/unplugin-0.6.0.tgz", - "integrity": "sha512-oKttBqTQpAK0D6iWSR952L58+86GW7EMhfHD1ueF7xwJxfbIikvNa+oNIvdinr46m9g0aaHA0XywpZTGCCwm+g==", + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", "dev": true, - "hasInstallScript": true, + "license": "MIT", "dependencies": { - "dotenv": "^16.0.0", - "magic-string": "^0.30.0", - "object-hash": "^3.0.0", - "picocolors": "^1.0.0", - "unplugin": "^1.5.0" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": ">= 14" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@import-meta-env/cli": "^0.7.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "@import-meta-env/cli": { + "node-notifier": { "optional": true } } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "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" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "node": "*" }, "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^6.0.1" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@jimp/bmp": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.13.tgz", + "integrity": "sha512-9edAxu7N2FX7vzkdl5Jo1BbACfycUtBQX+XBMcHA2bk62P8R0otgkHg798frgAk/WxQIzwxqOH6wMiCwrlAzdQ==", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "bmp-js": "^0.1.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@jimp/core": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.13.tgz", + "integrity": "sha512-qXpA1tzTnlkTku9yqtuRtS/wVntvE6f3m3GNxdTdtmc+O+Wcg9Xo2ABPMh7Nc0AHbMKzwvwgB2JnjZmlmJEObg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^16.5.4", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@jimp/core/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@jimp/custom": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.13.tgz", + "integrity": "sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.16.13" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@jimp/gif": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.13.tgz", + "integrity": "sha512-yFAMZGv3o+YcjXilMWWwS/bv1iSqykFahFMSO169uVMtfQVfa90kt4/kDwrXNR6Q9i6VHpFiGZMlF2UnHClBvg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "gifwrap": "^0.9.2", + "omggif": "^1.0.9" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/core/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/@jimp/jpeg": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.13.tgz", + "integrity": "sha512-BJHlDxzTlCqP2ThqP8J0eDrbBfod7npWCbJAcfkKqdQuFk0zBPaZ6KKaQKyKxmWJ87Z6ohANZoMKEbtvrwz1AA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "jpeg-js": "^0.4.2" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/core/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "node_modules/@jimp/plugin-blit": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.13.tgz", + "integrity": "sha512-8Z1k96ZFxlhK2bgrY1JNWNwvaBeI/bciLM0yDOni2+aZwfIIiC7Y6PeWHTAvjHNjphz+XCt01WQmOYWCn0ML6g==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/create-cache-key-function": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", - "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "node_modules/@jimp/plugin-blur": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.13.tgz", + "integrity": "sha512-PvLrfa8vkej3qinlebyhLpksJgCF5aiysDMSVhOZqwH5nQLLtDE9WYbnsofGw4r0VVpyw3H/ANCIzYTyCtP9Cg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@jimp/plugin-circle": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.13.tgz", + "integrity": "sha512-RNave7EFgZrb5V5EpdvJGAEHMnDAJuwv05hKscNfIYxf0kR3KhViBTDy+MoTnMlIvaKFULfwIgaZWzyhuINMzA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "node_modules/@jimp/plugin-color": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.13.tgz", + "integrity": "sha512-xW+9BtEvoIkkH/Wde9ql4nAFbYLkVINhpgAE7VcBUsuuB34WUbcBl/taOuUYQrPEFQJ4jfXiAJZ2H/rvKjCVnQ==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13", + "tinycolor2": "^1.4.1" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "node_modules/@jimp/plugin-contain": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.13.tgz", + "integrity": "sha512-QayTXw4tXMwU6q6acNTQrTTFTXpNRBe+MgTGMDU0lk+23PjlFCO/9sacflelG8lsp7vNHhAxFeHptDMAksEYzg==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "node_modules/@jimp/plugin-cover": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.13.tgz", + "integrity": "sha512-BSsP71GTNaqWRcvkbWuIVH+zK7b3TSNebbhDkFK0fVaUTzHuKMS/mgY4hDZIEVt7Rf5FjadAYtsujHN9w0iSYA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "node_modules/@jimp/plugin-crop": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.13.tgz", + "integrity": "sha512-WEl2tPVYwzYL8OKme6Go2xqiWgKsgxlMwyHabdAU4tXaRwOCnOI7v4021gCcBb9zn/oWwguHuKHmK30Fw2Z/PA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "node_modules/@jimp/plugin-displace": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.13.tgz", + "integrity": "sha512-qt9WKq8vWrcjySa9DyQ0x/RBMHQeiVjdVSY1SJsMjssPUf0pS74qorcuAkGi89biN3YoGUgPkpqECnAWnYwgGA==", "dev": true, "license": "MIT", "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/@jimp/plugin-dither": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.13.tgz", + "integrity": "sha512-5/N3yJggbWQTlGZHQYJPmQXEwR52qaXjEzkp1yRBbtdaekXE3BG/suo0fqeoV/csf8ooI78sJzYmIrxNoWVtgQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "node_modules/@jimp/plugin-fisheye": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.13.tgz", + "integrity": "sha512-2rZmTdFbT/cF9lEZIkXCYO0TsT114Q27AX5IAo0Sju6jVQbvIk1dFUTnwLDadTo8wkJlFzGqMQ24Cs8cHWOliA==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.27.8" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "node_modules/@jimp/plugin-flip": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.13.tgz", + "integrity": "sha512-EmcgAA74FTc5u7Z+hUO/sRjWwfPPLuOQP5O64x5g4j0T12Bd29IgsYZxoutZo/rb3579+JNa/3wsSEmyVv1EpA==", "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-rotate": ">=0.3.5" } }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "node_modules/@jimp/plugin-gaussian": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.13.tgz", + "integrity": "sha512-A1XKfGQD0iDdIiKqFYi8nZMv4dDVYdxbrmgR7y/CzUHhSYdcmoljLIIsZZM3Iks/Wa353W3vtvkWLuDbQbch1w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "node_modules/@jimp/plugin-invert": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.13.tgz", + "integrity": "sha512-xFMrIn7czEZbdbMzZWuaZFnlLGJDVJ82y5vlsKsXRTG2kcxRsMPXvZRWHV57nSs1YFsNqXSbrC8B98n0E32njQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "node_modules/@jimp/plugin-mask": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.13.tgz", + "integrity": "sha512-wLRYKVBXql2GAYgt6FkTnCfE+q5NomM7Dlh0oIPGAoMBWDyTx0eYutRK6PlUrRK2yMHuroAJCglICTbxqGzowQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "node_modules/@jimp/plugin-normalize": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.13.tgz", + "integrity": "sha512-3tfad0n9soRna4IfW9NzQdQ2Z3ijkmo21DREHbE6CGcMIxOSvfRdSvf1qQPApxjTSo8LTU4MCi/fidx/NZ0GqQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.16.13" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jimp/bmp": { + "node_modules/@jimp/plugin-print": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.16.13.tgz", - "integrity": "sha512-9edAxu7N2FX7vzkdl5Jo1BbACfycUtBQX+XBMcHA2bk62P8R0otgkHg798frgAk/WxQIzwxqOH6wMiCwrlAzdQ==", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.13.tgz", + "integrity": "sha512-0m6i3p01PGRkGAK9r53hDYrkyMq+tlhLOIbsSTmZyh6HLshUKlTB7eXskF5OpVd5ZUHoltlNc6R+ggvKIzxRFw==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13", - "bmp-js": "^0.1.0" + "load-bmfont": "^1.4.0" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5" } }, - "node_modules/@jimp/core": { + "node_modules/@jimp/plugin-resize": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.16.13.tgz", - "integrity": "sha512-qXpA1tzTnlkTku9yqtuRtS/wVntvE6f3m3GNxdTdtmc+O+Wcg9Xo2ABPMh7Nc0AHbMKzwvwgB2JnjZmlmJEObg==", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.13.tgz", + "integrity": "sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13", - "any-base": "^1.1.0", - "buffer": "^5.2.0", - "exif-parser": "^0.1.12", - "file-type": "^16.5.4", - "load-bmfont": "^1.3.1", - "mkdirp": "^0.5.1", - "phin": "^2.9.1", - "pixelmatch": "^4.0.2", - "tinycolor2": "^1.4.1" + "@jimp/utils": "^0.16.13" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jimp/core/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/@jimp/custom": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.16.13.tgz", - "integrity": "sha512-LTATglVUPGkPf15zX1wTMlZ0+AU7cGEGF6ekVF1crA8eHUWsGjrYTB+Ht4E3HTrCok8weQG+K01rJndCp/l4XA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/core": "^0.16.13" - } - }, - "node_modules/@jimp/gif": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.16.13.tgz", - "integrity": "sha512-yFAMZGv3o+YcjXilMWWwS/bv1iSqykFahFMSO169uVMtfQVfa90kt4/kDwrXNR6Q9i6VHpFiGZMlF2UnHClBvg==", + "node_modules/@jimp/plugin-rotate": { + "version": "0.16.13", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.13.tgz", + "integrity": "sha512-Ev+Jjmj1nHYw897z9C3R9dYsPv7S2/nxdgfFb/h8hOwK0Ovd1k/+yYS46A0uj/JCKK0pQk8wOslYBkPwdnLorw==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13", - "gifwrap": "^0.9.2", - "omggif": "^1.0.9" + "@jimp/utils": "^0.16.13" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" } }, - "node_modules/@jimp/jpeg": { + "node_modules/@jimp/plugin-scale": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.16.13.tgz", - "integrity": "sha512-BJHlDxzTlCqP2ThqP8J0eDrbBfod7npWCbJAcfkKqdQuFk0zBPaZ6KKaQKyKxmWJ87Z6ohANZoMKEbtvrwz1AA==", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.13.tgz", + "integrity": "sha512-05POQaEJVucjTiSGMoH68ZiELc7QqpIpuQlZ2JBbhCV+WCbPFUBcGSmE7w4Jd0E2GvCho/NoMODLwgcVGQA97A==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13", - "jpeg-js": "^0.4.2" + "@jimp/utils": "^0.16.13" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" } }, - "node_modules/@jimp/plugin-blit": { + "node_modules/@jimp/plugin-shadow": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.16.13.tgz", - "integrity": "sha512-8Z1k96ZFxlhK2bgrY1JNWNwvaBeI/bciLM0yDOni2+aZwfIIiC7Y6PeWHTAvjHNjphz+XCt01WQmOYWCn0ML6g==", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.13.tgz", + "integrity": "sha512-nmu5VSZ9hsB1JchTKhnnCY+paRBnwzSyK5fhkhtQHHoFD5ArBQ/5wU8y6tCr7k/GQhhGq1OrixsECeMjPoc8Zw==", "dev": true, "license": "MIT", "dependencies": { @@ -2345,13 +2257,15 @@ "@jimp/utils": "^0.16.13" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blur": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" } }, - "node_modules/@jimp/plugin-blur": { + "node_modules/@jimp/plugin-threshold": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.16.13.tgz", - "integrity": "sha512-PvLrfa8vkej3qinlebyhLpksJgCF5aiysDMSVhOZqwH5nQLLtDE9WYbnsofGw4r0VVpyw3H/ANCIzYTyCtP9Cg==", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.13.tgz", + "integrity": "sha512-+3zArBH0OE3Rhjm4HyAokMsZlIq5gpQec33CncyoSwxtRBM2WAhUVmCUKuBo+Lr/2/4ISoY4BWpHKhMLDix6cA==", "dev": true, "license": "MIT", "dependencies": { @@ -2359,451 +2273,169 @@ "@jimp/utils": "^0.16.13" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-color": ">=0.8.0", + "@jimp/plugin-resize": ">=0.8.0" } }, - "node_modules/@jimp/plugin-circle": { + "node_modules/@jimp/plugins": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.16.13.tgz", - "integrity": "sha512-RNave7EFgZrb5V5EpdvJGAEHMnDAJuwv05hKscNfIYxf0kR3KhViBTDy+MoTnMlIvaKFULfwIgaZWzyhuINMzA==", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.13.tgz", + "integrity": "sha512-CJLdqODEhEVs4MgWCxpWL5l95sCBlkuSLz65cxEm56X5akIsn4LOlwnKoSEZioYcZUBvHhCheH67AyPTudfnQQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" + "@jimp/plugin-blit": "^0.16.13", + "@jimp/plugin-blur": "^0.16.13", + "@jimp/plugin-circle": "^0.16.13", + "@jimp/plugin-color": "^0.16.13", + "@jimp/plugin-contain": "^0.16.13", + "@jimp/plugin-cover": "^0.16.13", + "@jimp/plugin-crop": "^0.16.13", + "@jimp/plugin-displace": "^0.16.13", + "@jimp/plugin-dither": "^0.16.13", + "@jimp/plugin-fisheye": "^0.16.13", + "@jimp/plugin-flip": "^0.16.13", + "@jimp/plugin-gaussian": "^0.16.13", + "@jimp/plugin-invert": "^0.16.13", + "@jimp/plugin-mask": "^0.16.13", + "@jimp/plugin-normalize": "^0.16.13", + "@jimp/plugin-print": "^0.16.13", + "@jimp/plugin-resize": "^0.16.13", + "@jimp/plugin-rotate": "^0.16.13", + "@jimp/plugin-scale": "^0.16.13", + "@jimp/plugin-shadow": "^0.16.13", + "@jimp/plugin-threshold": "^0.16.13", + "timm": "^1.6.1" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jimp/plugin-color": { + "node_modules/@jimp/png": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.16.13.tgz", - "integrity": "sha512-xW+9BtEvoIkkH/Wde9ql4nAFbYLkVINhpgAE7VcBUsuuB34WUbcBl/taOuUYQrPEFQJ4jfXiAJZ2H/rvKjCVnQ==", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.13.tgz", + "integrity": "sha512-8cGqINvbWJf1G0Her9zbq9I80roEX0A+U45xFby3tDWfzn+Zz8XKDF1Nv9VUwVx0N3zpcG1RPs9hfheG4Cq2kg==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", "@jimp/utils": "^0.16.13", - "tinycolor2": "^1.4.1" + "pngjs": "^3.3.3" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jimp/plugin-contain": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.16.13.tgz", - "integrity": "sha512-QayTXw4tXMwU6q6acNTQrTTFTXpNRBe+MgTGMDU0lk+23PjlFCO/9sacflelG8lsp7vNHhAxFeHptDMAksEYzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-blit": ">=0.3.5", - "@jimp/plugin-resize": ">=0.3.5", - "@jimp/plugin-scale": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-cover": { + "node_modules/@jimp/tiff": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.16.13.tgz", - "integrity": "sha512-BSsP71GTNaqWRcvkbWuIVH+zK7b3TSNebbhDkFK0fVaUTzHuKMS/mgY4hDZIEVt7Rf5FjadAYtsujHN9w0iSYA==", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.13.tgz", + "integrity": "sha512-oJY8d9u95SwW00VPHuCNxPap6Q1+E/xM5QThb9Hu+P6EGuu6lIeLaNBMmFZyblwFbwrH+WBOZlvIzDhi4Dm/6Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" + "utif": "^2.0.1" }, "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-crop": ">=0.3.5", - "@jimp/plugin-resize": ">=0.3.5", - "@jimp/plugin-scale": ">=0.3.5" + "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jimp/plugin-crop": { + "node_modules/@jimp/types": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.16.13.tgz", - "integrity": "sha512-WEl2tPVYwzYL8OKme6Go2xqiWgKsgxlMwyHabdAU4tXaRwOCnOI7v4021gCcBb9zn/oWwguHuKHmK30Fw2Z/PA==", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.13.tgz", + "integrity": "sha512-mC0yVNUobFDjoYLg4hoUwzMKgNlxynzwt3cDXzumGvRJ7Kb8qQGOWJQjQFo5OxmGExqzPphkirdbBF88RVLBCg==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" + "@jimp/bmp": "^0.16.13", + "@jimp/gif": "^0.16.13", + "@jimp/jpeg": "^0.16.13", + "@jimp/png": "^0.16.13", + "@jimp/tiff": "^0.16.13", + "timm": "^1.6.1" }, "peerDependencies": { "@jimp/custom": ">=0.3.5" } }, - "node_modules/@jimp/plugin-displace": { + "node_modules/@jimp/utils": { "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.16.13.tgz", - "integrity": "sha512-qt9WKq8vWrcjySa9DyQ0x/RBMHQeiVjdVSY1SJsMjssPUf0pS74qorcuAkGi89biN3YoGUgPkpqECnAWnYwgGA==", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.13.tgz", + "integrity": "sha512-VyCpkZzFTHXtKgVO35iKN0sYR10psGpV6SkcSeV4oF7eSYlR8Bl6aQLCzVeFjvESF7mxTmIiI3/XrMobVrtxDA==", "dev": true, "license": "MIT", "dependencies": { "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "regenerator-runtime": "^0.13.3" } }, - "node_modules/@jimp/plugin-dither": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.16.13.tgz", - "integrity": "sha512-5/N3yJggbWQTlGZHQYJPmQXEwR52qaXjEzkp1yRBbtdaekXE3BG/suo0fqeoV/csf8ooI78sJzYmIrxNoWVtgQ==", + "node_modules/@jimp/utils/node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@jimp/plugin-fisheye": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.16.13.tgz", - "integrity": "sha512-2rZmTdFbT/cF9lEZIkXCYO0TsT114Q27AX5IAo0Sju6jVQbvIk1dFUTnwLDadTo8wkJlFzGqMQ24Cs8cHWOliA==", - "dev": true, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@jimp/plugin-flip": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.16.13.tgz", - "integrity": "sha512-EmcgAA74FTc5u7Z+hUO/sRjWwfPPLuOQP5O64x5g4j0T12Bd29IgsYZxoutZo/rb3579+JNa/3wsSEmyVv1EpA==", - "dev": true, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-rotate": ">=0.3.5" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@jimp/plugin-gaussian": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.16.13.tgz", - "integrity": "sha512-A1XKfGQD0iDdIiKqFYi8nZMv4dDVYdxbrmgR7y/CzUHhSYdcmoljLIIsZZM3Iks/Wa353W3vtvkWLuDbQbch1w==", - "dev": true, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "license": "MIT", + "peer": true, "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@jimp/plugin-invert": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.16.13.tgz", - "integrity": "sha512-xFMrIn7czEZbdbMzZWuaZFnlLGJDVJ82y5vlsKsXRTG2kcxRsMPXvZRWHV57nSs1YFsNqXSbrC8B98n0E32njQ==", - "dev": true, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-mask": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.16.13.tgz", - "integrity": "sha512-wLRYKVBXql2GAYgt6FkTnCfE+q5NomM7Dlh0oIPGAoMBWDyTx0eYutRK6PlUrRK2yMHuroAJCglICTbxqGzowQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-normalize": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.16.13.tgz", - "integrity": "sha512-3tfad0n9soRna4IfW9NzQdQ2Z3ijkmo21DREHbE6CGcMIxOSvfRdSvf1qQPApxjTSo8LTU4MCi/fidx/NZ0GqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-print": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.16.13.tgz", - "integrity": "sha512-0m6i3p01PGRkGAK9r53hDYrkyMq+tlhLOIbsSTmZyh6HLshUKlTB7eXskF5OpVd5ZUHoltlNc6R+ggvKIzxRFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13", - "load-bmfont": "^1.4.0" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-blit": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-resize": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.16.13.tgz", - "integrity": "sha512-qoqtN8LDknm3fJm9nuPygJv30O3vGhSBD2TxrsCnhtOsxKAqVPJtFVdGd/qVuZ8nqQANQmTlfqTiK9mVWQ7MiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-rotate": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.16.13.tgz", - "integrity": "sha512-Ev+Jjmj1nHYw897z9C3R9dYsPv7S2/nxdgfFb/h8hOwK0Ovd1k/+yYS46A0uj/JCKK0pQk8wOslYBkPwdnLorw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-blit": ">=0.3.5", - "@jimp/plugin-crop": ">=0.3.5", - "@jimp/plugin-resize": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-scale": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.16.13.tgz", - "integrity": "sha512-05POQaEJVucjTiSGMoH68ZiELc7QqpIpuQlZ2JBbhCV+WCbPFUBcGSmE7w4Jd0E2GvCho/NoMODLwgcVGQA97A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-resize": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-shadow": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.16.13.tgz", - "integrity": "sha512-nmu5VSZ9hsB1JchTKhnnCY+paRBnwzSyK5fhkhtQHHoFD5ArBQ/5wU8y6tCr7k/GQhhGq1OrixsECeMjPoc8Zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-blur": ">=0.3.5", - "@jimp/plugin-resize": ">=0.3.5" - } - }, - "node_modules/@jimp/plugin-threshold": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.16.13.tgz", - "integrity": "sha512-+3zArBH0OE3Rhjm4HyAokMsZlIq5gpQec33CncyoSwxtRBM2WAhUVmCUKuBo+Lr/2/4ISoY4BWpHKhMLDix6cA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5", - "@jimp/plugin-color": ">=0.8.0", - "@jimp/plugin-resize": ">=0.8.0" - } - }, - "node_modules/@jimp/plugins": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.16.13.tgz", - "integrity": "sha512-CJLdqODEhEVs4MgWCxpWL5l95sCBlkuSLz65cxEm56X5akIsn4LOlwnKoSEZioYcZUBvHhCheH67AyPTudfnQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/plugin-blit": "^0.16.13", - "@jimp/plugin-blur": "^0.16.13", - "@jimp/plugin-circle": "^0.16.13", - "@jimp/plugin-color": "^0.16.13", - "@jimp/plugin-contain": "^0.16.13", - "@jimp/plugin-cover": "^0.16.13", - "@jimp/plugin-crop": "^0.16.13", - "@jimp/plugin-displace": "^0.16.13", - "@jimp/plugin-dither": "^0.16.13", - "@jimp/plugin-fisheye": "^0.16.13", - "@jimp/plugin-flip": "^0.16.13", - "@jimp/plugin-gaussian": "^0.16.13", - "@jimp/plugin-invert": "^0.16.13", - "@jimp/plugin-mask": "^0.16.13", - "@jimp/plugin-normalize": "^0.16.13", - "@jimp/plugin-print": "^0.16.13", - "@jimp/plugin-resize": "^0.16.13", - "@jimp/plugin-rotate": "^0.16.13", - "@jimp/plugin-scale": "^0.16.13", - "@jimp/plugin-shadow": "^0.16.13", - "@jimp/plugin-threshold": "^0.16.13", - "timm": "^1.6.1" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/png": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.16.13.tgz", - "integrity": "sha512-8cGqINvbWJf1G0Her9zbq9I80roEX0A+U45xFby3tDWfzn+Zz8XKDF1Nv9VUwVx0N3zpcG1RPs9hfheG4Cq2kg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/utils": "^0.16.13", - "pngjs": "^3.3.3" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/tiff": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.16.13.tgz", - "integrity": "sha512-oJY8d9u95SwW00VPHuCNxPap6Q1+E/xM5QThb9Hu+P6EGuu6lIeLaNBMmFZyblwFbwrH+WBOZlvIzDhi4Dm/6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "utif": "^2.0.1" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/types": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.16.13.tgz", - "integrity": "sha512-mC0yVNUobFDjoYLg4hoUwzMKgNlxynzwt3cDXzumGvRJ7Kb8qQGOWJQjQFo5OxmGExqzPphkirdbBF88RVLBCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "@jimp/bmp": "^0.16.13", - "@jimp/gif": "^0.16.13", - "@jimp/jpeg": "^0.16.13", - "@jimp/png": "^0.16.13", - "@jimp/tiff": "^0.16.13", - "timm": "^1.6.1" - }, - "peerDependencies": { - "@jimp/custom": ">=0.3.5" - } - }, - "node_modules/@jimp/utils": { - "version": "0.16.13", - "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.16.13.tgz", - "integrity": "sha512-VyCpkZzFTHXtKgVO35iKN0sYR10psGpV6SkcSeV4oF7eSYlR8Bl6aQLCzVeFjvESF7mxTmIiI3/XrMobVrtxDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "regenerator-runtime": "^0.13.3" - } - }, - "node_modules/@jimp/utils/node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.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==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@juggle/resize-observer": { @@ -2855,9 +2487,9 @@ "license": "BSD-2-Clause" }, "node_modules/@mtes-mct/monitor-ui": { - "version": "23.1.3", - "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-23.1.3.tgz", - "integrity": "sha512-+mA4RWUZsO+/ACsojzCONdgtzeY3XSm7BDWiOHw+ad29M3fIk/ZNQYXRlhctGpBgtVxx76fFyu5/0jzVKXrffA==", + "version": "23.3.0", + "resolved": "https://registry.npmjs.org/@mtes-mct/monitor-ui/-/monitor-ui-23.3.0.tgz", + "integrity": "sha512-3BfbwS0glrJAZhPanvFuqEkoLsx6erIdyc1b6NA2UZKQ8ms9Q8ZClspnOhPusMbReC5QBZBv0NUlbgZ7CbsVAA==", "license": "AGPL-3.0", "dependencies": { "@babel/runtime": "7.25.6", @@ -3027,149 +2659,6 @@ } } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.22.4.tgz", - "integrity": "sha512-Fxamp4aEZnfPOcGA8KSNEohV8hX7zVHOemC8jVBoBUHu5zpJK/Eu3uJwt6BMgy9fkvzxDaurgj96F/NiLukF2w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.22.4.tgz", - "integrity": "sha512-VXoK5UMrgECLYaMuGuVTOx5kcuap1Jm8g/M83RnCHBKOqvPPmROFJGQaZhGccnsFtfXQ3XYa4/jMCJvZnbJBdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.22.4.tgz", - "integrity": "sha512-xMM9ORBqu81jyMKCDP+SZDhnX2QEVQzTcC6G18KlTQEzWK8r/oNZtKuZaCcHhnsa6fEeOBionoyl5JsAbE/36Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.22.4.tgz", - "integrity": "sha512-aJJyYKQwbHuhTUrjWjxEvGnNNBCnmpHDvrb8JFDbeSH3m2XdHcxDd3jthAzvmoI8w/kSjd2y0udT+4okADsZIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.22.4.tgz", - "integrity": "sha512-j63YtCIRAzbO+gC2L9dWXRh5BFetsv0j0va0Wi9epXDgU/XUi5dJKo4USTttVyK7fGw2nPWK0PbAvyliz50SCQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.22.4.tgz", - "integrity": "sha512-dJnWUgwWBX1YBRsuKKMOlXCzh2Wu1mlHzv20TpqEsfdZLb3WoJW2kIEsGwLkroYf24IrPAvOT/ZQ2OYMV6vlrg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.22.4.tgz", - "integrity": "sha512-AdPRoNi3NKVLolCN/Sp4F4N1d98c4SBnHMKoLuiG6RXgoZ4sllseuGioszumnPGmPM2O7qaAX/IJdeDU8f26Aw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.22.4.tgz", - "integrity": "sha512-Gl0AxBtDg8uoAn5CCqQDMqAx22Wx22pjDOjBdmG0VIWX3qUBHzYmOKh8KXHL4UpogfJ14G4wk16EQogF+v8hmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.22.4.tgz", - "integrity": "sha512-3aVCK9xfWW1oGQpTsYJJPF6bfpWfhbRnhdlyhak2ZiyFLDaayz0EP5j9V1RVLAAxlmWKTDfS9wyRyY3hvhPoOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.22.4.tgz", - "integrity": "sha512-ePYIir6VYnhgv2C5Xe9u+ico4t8sZWXschR6fMgoPUK31yQu7hTEJb7bCqivHECwIClJfKgE7zYsh1qTP3WHUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.22.4.tgz", - "integrity": "sha512-GqFJ9wLlbB9daxhVlrTe61vJtEY99/xB3C8e4ULVsVfflcpmR6c8UZXjtkMA6FhNONhj2eA5Tk9uAVw5orEs4Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.22.4", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.22.4.tgz", @@ -3196,45 +2685,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.22.4.tgz", - "integrity": "sha512-BjI+NVVEGAXjGWYHz/vv0pBqfGoUH0IGZ0cICTn7kB9PyjrATSkX+8WkguNjWoj2qSr1im/+tTGRaY+4/PdcQw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.22.4.tgz", - "integrity": "sha512-SiWG/1TuUdPvYmzmYnmd3IEifzR61Tragkbx9D3+R8mzQqDBz8v+BvZNDlkiTtI9T15KYZhP0ehn3Dld4n9J5g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.22.4.tgz", - "integrity": "sha512-j8pPKp53/lq9lMXN57S8cFz0MynJk8OWNuUnXct/9KCpKU7DgU3bYMJhwWmcqC0UU29p8Lr0/7KEVcaM6bf47Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@rsuite/icon-font": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@rsuite/icon-font/-/icon-font-4.0.0.tgz", @@ -3771,169 +3221,41 @@ "@swc/core-win32-x64-msvc": "1.7.23" }, "peerDependencies": { - "@swc/helpers": "*" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.23.tgz", - "integrity": "sha512-yyOHPfti6yKlQulfVWMt7BVKst+SyEZYCWuQSGMn1KgmNCH/bYufRWfQXIhkGSj44ZkEepJmsJ8tDyIb4k5WyA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.23.tgz", - "integrity": "sha512-GzqHwQ0Y1VyjdI/bBKFX2GKm5HD3PIB6OhuAQtWZMTtEr2yIrlT0YK2T+XKh7oIg31JwxGBeQdBk3KTI7DARmQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.23.tgz", - "integrity": "sha512-qwX4gB41OS6/OZkHcpTqLFGsdmvoZyffnJIlgB/kZKwH3lfeJWzv6vx57zXtNpM/t7GoQEe0VZUVdmNjxSxBZw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.23.tgz", - "integrity": "sha512-TsrbUZdMaUwzI7+g/8rHPLWbntMKYSu5Bn5IBSqVKPeyqaXxNnlIUnWXgXcUcRAc+T+Y8ADfr7EiFz9iz5DuSA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.23.tgz", - "integrity": "sha512-JEdtwdthazKq4PBz53KSubwwK8MvqODAihGSAzc8u3Unq4ojcvaS8b0CwLBeD+kTQ78HpxOXTt3DsFIxpgaCAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.23.tgz", - "integrity": "sha512-V51gFPWaVAHbI1yg9ahsoya3aB4uawye3SZ5uQWgcP7wdCdiv60dw4F5nuPJf5Z1oXD3U/BslXuamv8Oh9vXqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.23.tgz", - "integrity": "sha512-BBqQi4+UdeRqag3yM4IJjaHG4yc1o3l9ksENHToE0o/u2DT0FY5+K/DiYGZLC1JHbSFzNqRCYsa7DIzRtZ0A1A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.23.tgz", - "integrity": "sha512-JPk6pvCKncL6bXG7p+NLZf8PWx4FakVvKNdwGeMrYunb+yk1IZf7qf9LJk8+GDGF5QviDXPs8opZrTrfsW80fA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } } }, - "node_modules/@swc/core-win32-ia32-msvc": { + "node_modules/@swc/core-linux-x64-gnu": { "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.23.tgz", - "integrity": "sha512-2Whxi8d+bLQBzJcQ5qYPHlk02YYVGsMVav0fWk+FnX2z1QRREIu1L1xvrpi7gBpjXp6BIU40ya8GiKeekNT2bg==", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.23.tgz", + "integrity": "sha512-V51gFPWaVAHbI1yg9ahsoya3aB4uawye3SZ5uQWgcP7wdCdiv60dw4F5nuPJf5Z1oXD3U/BslXuamv8Oh9vXqQ==", "cpu": [ - "ia32" + "x64" ], "dev": true, "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=10" } }, - "node_modules/@swc/core-win32-x64-msvc": { + "node_modules/@swc/core-linux-x64-musl": { "version": "1.7.23", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.23.tgz", - "integrity": "sha512-82fARk4/yJ40kwWKY/gdKDisPdtgJE9jgpl/vkNG3alyJxrCzuNM7+CtiKoYbXLeqM8GQTS3wlvCaJu9oQ8dag==", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.23.tgz", + "integrity": "sha512-BBqQi4+UdeRqag3yM4IJjaHG4yc1o3l9ksENHToE0o/u2DT0FY5+K/DiYGZLC1JHbSFzNqRCYsa7DIzRtZ0A1A==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=10" @@ -9461,21 +8783,6 @@ "dev": true, "license": "ISC" }, - "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", @@ -17878,1068 +17185,694 @@ "node_modules/type-fest": { "version": "4.26.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.0.tgz", - "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", - "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", - "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.7.tgz", - "integrity": "sha512-ueeb9YybpjhivjbHP2LdFDAjbS948fGEPj+ACAMs4xCMmh72OCOMQWBQKlaN4ZNQ04yfLSDLSx1tGRIoWimObQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/types-ramda": { - "version": "0.30.1", - "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz", - "integrity": "sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ts-toolbelt": "^9.6.0" - } - }, - "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/ua-parser-js": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", - "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "license": "MIT" - }, - "node_modules/unidiff": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unidiff/-/unidiff-1.0.2.tgz", - "integrity": "sha512-2sbEzki5fBmjgAqoafwxRenfMcumMlmVAoJDwYJa3CI4ZVugkdR6qjTw5sVsl29/4JfBBXhWEAd5ars8nRdqXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "diff": "^2.2.2" - } - }, - "node_modules/unidiff/node_modules/diff": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", - "integrity": "sha512-9wfm3RLzMp/PyTFWuw9liEzdlxsdGixCW0ZTU1XDmtlAkvpVXTPGF8KnfSs0hm3BPbg19OrUPPsRkHXoREpP1g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/unified": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "bail": "^2.0.0", - "extend": "^3.0.0", - "is-buffer": "^2.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-generated": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", - "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", - "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0" + "integrity": "sha512-OduNjVJsFbifKb57UqZ2EMP1i4u64Xwow3NYXUtBbD4vIwJdQd4+xl8YDou1dlm4DVrtwT/7Ky8z8WyCULVfxw==", + "dev": true, + "engines": { + "node": ">=16" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unist-util-position": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", - "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "engines": { + "node": ">= 0.4" } }, - "node_modules/unist-util-stringify-position": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", - "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unist-util-visit": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", - "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0", - "unist-util-visit-parents": "^5.1.1" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unist-util-visit-parents": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", - "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, "license": "MIT", "dependencies": { - "@types/unist": "^2.0.0", - "unist-util-is": "^5.0.0" + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "node_modules/typedarray": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.7.tgz", + "integrity": "sha512-ueeb9YybpjhivjbHP2LdFDAjbS948fGEPj+ACAMs4xCMmh72OCOMQWBQKlaN4ZNQ04yfLSDLSx1tGRIoWimObQ==", "license": "MIT", - "engines": { - "node": ">= 10.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/unplugin": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.12.2.tgz", - "integrity": "sha512-bEqQxeC7rxtxPZ3M5V4Djcc4lQqKPgGe3mAWZvxcSmX5jhGxll19NliaRzQSQPrk4xJZSGniK3puLWpRuZN7VQ==", + "node_modules/types-ramda": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz", + "integrity": "sha512-1HTsf5/QVRmLzcGfldPFvkVsAdi1db1BBKzi7iW3KBUlOICg/nKnFS+jGqDJS3YD8VsWbAh7JiHeBvbsw8RPxA==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.12.1", - "chokidar": "^3.6.0", - "webpack-sources": "^3.2.3", - "webpack-virtual-modules": "^0.6.2" - }, - "engines": { - "node": ">=14.0.0" + "ts-toolbelt": "^9.6.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "license": "MIT", + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, "engines": { - "node": ">=8" + "node": ">=14.17" } }, - "node_modules/update-browserslist-db": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", - "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "node_modules/ua-parser-js": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", + "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", "funding": [ { "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "url": "https://opencollective.com/ua-parser-js" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "type": "paypal", + "url": "https://paypal.me/faisalman" }, { "type": "github", - "url": "https://github.com/sponsors/ai" + "url": "https://github.com/sponsors/faisalman" } ], "license": "MIT", - "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.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==", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "node_modules/urlgrey": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-1.0.0.tgz", - "integrity": "sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "fast-url-parser": "^1.1.3" - } - }, - "node_modules/urlpattern-polyfill": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", - "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", - "dev": true, - "license": "MIT" - }, - "node_modules/use-debounce": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz", - "integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==", - "license": "MIT", "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" + "node": "*" } }, - "node_modules/use-isomorphic-layout-effect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", - "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/use-sync-external-store": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", - "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", - "license": "MIT", - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/utf8-byte-length": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", - "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", - "dev": true, - "license": "(WTFPL OR MIT)" - }, - "node_modules/utif": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", - "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", "dev": true, "license": "MIT", "dependencies": { - "pako": "^1.0.5" + "buffer": "^5.2.1", + "through": "^2.3.8" } }, - "node_modules/utif/node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true, - "license": "(MIT AND Zlib)" + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" }, - "node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "node_modules/unidiff": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unidiff/-/unidiff-1.0.2.tgz", + "integrity": "sha512-2sbEzki5fBmjgAqoafwxRenfMcumMlmVAoJDwYJa3CI4ZVugkdR6qjTw5sVsl29/4JfBBXhWEAd5ars8nRdqXg==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" + "diff": "^2.2.2" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "node_modules/unidiff/node_modules/diff": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-2.2.3.tgz", + "integrity": "sha512-9wfm3RLzMp/PyTFWuw9liEzdlxsdGixCW0ZTU1XDmtlAkvpVXTPGF8KnfSs0hm3BPbg19OrUPPsRkHXoREpP1g==", "dev": true, - "license": "MIT" - }, - "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "node_modules/uvu": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", - "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", + "node_modules/unified": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", + "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", "license": "MIT", "dependencies": { - "dequal": "^2.0.0", - "diff": "^5.0.0", - "kleur": "^4.0.3", - "sade": "^1.7.3" - }, - "bin": { - "uvu": "bin.js" + "@types/unist": "^2.0.0", + "bail": "^2.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^5.0.0" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/uvu/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/uvu/node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", "license": "MIT", - "engines": { - "node": ">=6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", + "node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "@types/unist": "^2.0.0" }, - "engines": { - "node": ">=10.12.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, + "node_modules/unist-util-position": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", "license": "MIT", - "engines": { - "node": ">= 0.8" + "dependencies": { + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], + "node_modules/unist-util-stringify-position": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "@types/unist": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vfile": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", - "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", + "node_modules/unist-util-visit": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", - "is-buffer": "^2.0.0", - "unist-util-stringify-position": "^3.0.0", - "vfile-message": "^3.0.0" + "unist-util-is": "^5.0.0", + "unist-util-visit-parents": "^5.1.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/vfile-message": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", - "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", + "node_modules/unist-util-visit-parents": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", - "unist-util-stringify-position": "^3.0.0" + "unist-util-is": "^5.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/vite": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", - "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unplugin": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.12.2.tgz", + "integrity": "sha512-bEqQxeC7rxtxPZ3M5V4Djcc4lQqKPgGe3mAWZvxcSmX5jhGxll19NliaRzQSQPrk4xJZSGniK3puLWpRuZN7VQ==", "dev": true, + "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" + "acorn": "^8.12.1", + "chokidar": "^3.6.0", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.6.2" }, "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true + "node": ">=14.0.0" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" }, - "sugarss": { - "optional": true + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" }, - "terser": { - "optional": true + { + "type": "github", + "url": "https://github.com/sponsors/ai" } - } - }, - "node_modules/vite-plugin-svgr": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz", - "integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==", - "dev": true, + ], "license": "MIT", "dependencies": { - "@rollup/pluginutils": "^5.0.5", - "@svgr/core": "^8.1.0", - "@svgr/plugin-jsx": "^8.1.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" }, "peerDependencies": { - "vite": "^2.6.0 || 3 || 4 || 5" + "browserslist": ">= 4.21.0" } }, - "node_modules/vite-tsconfig-paths": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", - "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", - "dev": true, - "license": "MIT", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", "dependencies": { - "debug": "^4.1.1", - "globrex": "^0.1.2", - "tsconfck": "^3.0.3" - }, - "peerDependencies": { - "vite": "*" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } + "punycode": "^2.1.0" } }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/urlgrey": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-1.0.0.tgz", + "integrity": "sha512-hJfIzMPJmI9IlLkby8QrsCykQ+SXDeO2W5Q9QTW3QpqZVTx4a/K7p8/5q+/isD8vsbVaFgql/gvAoQCRQ2Cb5w==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "license": "BSD-2-Clause", + "dependencies": { + "fast-url-parser": "^1.1.3" } }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], + "node_modules/urlpattern-polyfill": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", "dev": true, + "license": "MIT" + }, + "node_modules/use-debounce": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-9.0.4.tgz", + "integrity": "sha512-6X8H/mikbrt0XE8e+JXRtZ8yYVvKkdYRfmIhWZYsP8rcNs9hk3APV8Ua2mFkKRLcJKVdnX2/Vwrmg2GWKUQEaQ==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=12" + "node": ">= 10.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" } }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, + "node_modules/use-sync-external-store": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "license": "(WTFPL OR MIT)" }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "pako": "^1.0.5" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], + "node_modules/utif/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "license": "(MIT AND Zlib)" }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" } }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "license": "MIT" }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, + "node_modules/uvu": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.6.tgz", + "integrity": "sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "dequal": "^2.0.0", + "diff": "^5.0.0", + "kleur": "^4.0.3", + "sade": "^1.7.3" + }, + "bin": { + "uvu": "bin.js" + }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/uvu/node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", "engines": { - "node": ">=12" + "node": ">=0.3.1" } }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, + "node_modules/uvu/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, "engines": { - "node": ">=12" + "node": ">=10.12.0" } }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">= 0.8" } }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" ], - "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" } }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/vfile": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "unist-util-stringify-position": "^3.0.0", + "vfile-message": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, + "node_modules/vfile-message": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" } }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], + "node_modules/vite": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.6.tgz", + "integrity": "sha512-IeL5f8OO5nylsgzd9tq4qD2QqI0k2CQLGrWD0rCN0EQJZpBK5vJAx0I+GDkMOXxQX/OfFHMuLIx6ddAxGX/k+Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, "engines": { - "node": ">=12" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } } }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], + "node_modules/vite-plugin-svgr": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz", + "integrity": "sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@rollup/pluginutils": "^5.0.5", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": "^2.6.0 || 3 || 4 || 5" } }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], + "node_modules/vite-tsconfig-paths": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", + "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } } }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { + "node_modules/vite/node_modules/@esbuild/linux-x64": { "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", "cpu": [ "x64" ], @@ -18947,7 +17880,7 @@ "license": "MIT", "optional": true, "os": [ - "win32" + "linux" ], "engines": { "node": ">=12" diff --git a/frontend/package.json b/frontend/package.json index 16ec10c36d..a94e7824fc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -37,7 +37,7 @@ "dependencies": { "@dnd-kit/core": "6.1.0", "@dnd-kit/modifiers": "6.0.1", - "@mtes-mct/monitor-ui": "23.1.3", + "@mtes-mct/monitor-ui": "23.3.0", "@reduxjs/toolkit": "2.2.7", "@sentry/react": "7.117.0", "@tanstack/react-table": "8.20.5", diff --git a/frontend/src/api/constants.ts b/frontend/src/api/constants.ts index 85b0fe785f..5dba5aaf87 100644 --- a/frontend/src/api/constants.ts +++ b/frontend/src/api/constants.ts @@ -37,6 +37,8 @@ export enum HttpStatusCode { export enum RtkCacheTagType { PriorNotification = 'PriorNotification', PriorNotificationDocuments = 'PriorNotificationDocuments', + PriorNotificationSentMessages = 'PriorNotificationSentMessages', + PriorNotificationSubscribers = 'PriorNotificationSubscribers', PriorNotificationTypes = 'PriorNotificationTypes', PriorNotifications = 'PriorNotifications', PriorNotificationsToVerify = 'PriorNotificationsToVerify', diff --git a/frontend/src/features/PriorNotification/PriorNotification.types.ts b/frontend/src/features/PriorNotification/PriorNotification.types.ts index 126c0073b3..a4d9c28f15 100644 --- a/frontend/src/features/PriorNotification/PriorNotification.types.ts +++ b/frontend/src/features/PriorNotification/PriorNotification.types.ts @@ -62,6 +62,7 @@ export namespace PriorNotification { reportId: string riskFactor: number | undefined state: State | undefined + vesselId: number } & ( | { asLogbookForm: LogbookForm @@ -159,6 +160,16 @@ export namespace PriorNotification { name: string } + export type SentMessage = { + communicationMeans: 'EMAIL' | 'FAX' | 'SMS' + dateTimeUtc: string + errorMessage: string | undefined + recipientAddressOrNumber: string + recipientName: string + recipientOrganization: string + success: boolean + } + export type Upload = { createdAt: string fileName: string diff --git a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx index 340df2e93f..33f77c1c35 100644 --- a/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx +++ b/frontend/src/features/PriorNotification/components/ManualPriorNotificationForm/Content.tsx @@ -21,8 +21,8 @@ import { getPartialComputationRequestData } from './utils' import { SideWindowCard } from '../../../../components/SideWindowCard' import { PriorNotification } from '../../PriorNotification.types' import { CardBanner } from '../shared/CardBanner' +import { CardBodyHead } from '../shared/CardBodyHead' import { DownloadButton } from '../shared/DownloadButton' -import { TagBar } from '../shared/TagBar' import { UploadFiles } from '../shared/UploadFiles' import type { ManualPriorNotificationFormValues } from './types' @@ -54,10 +54,8 @@ export function Content({ detail, isValidatingOnChange, onClose, onSubmit, onVer const isPendingSend = !!detail?.state && [PriorNotification.State.PENDING_AUTO_SEND, PriorNotification.State.PENDING_SEND].includes(detail?.state) - const isPendingVerification = detail?.state === PriorNotification.State.PENDING_VERIFICATION const isReadOnly = isPendingSend || isInvalidated const isVerifiedAndSent = detail?.state === PriorNotification.State.VERIFIED_AND_SENT - const hasDesignatedPorts = editedPriorNotificationComputedValues?.types?.find(type => type.hasDesignatedPorts) const priorNotificationIdentifier = getPriorNotificationIdentifier(detail) const closeCancellationConfirmationModal = () => { @@ -163,9 +161,11 @@ export function Content({ detail, isValidatingOnChange, onClose, onSubmit, onVer
- - {isNewPriorNotification && !editedPriorNotificationComputedValues && ( - - Veuillez renseigner les champs du formulaire pour définir le type de préavis et son statut, ainsi que le - segment de flotte et la note de risque du navire. - - )} - {!isNewPriorNotification && isPendingVerification && ( - Le préavis doit être vérifié par le CNSP avant sa diffusion. - )} - {(!!editedPriorNotificationComputedValues || !!detail) && ( - - Le navire doit respecter un délai d’envoi{hasDesignatedPorts && ' et débarquer dans un port désigné'}. - - )} -
@@ -318,14 +303,6 @@ const Body = styled.div` } ` -const Intro = styled.p<{ - $withTopMargin?: boolean -}>` - ${p => p.$withTopMargin && 'margin-top: 2px;'} - color: ${p => p.theme.color.slateGray}; - font-style: italic; -` - const Footer = styled.div` border-top: 1px solid ${p => p.theme.color.lightGray}; display: flex; diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx index 7447d6cb41..512e808255 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationCard/index.tsx @@ -20,8 +20,8 @@ import { Header } from './Header' import { SideWindowCard } from '../../../../components/SideWindowCard' import { priorNotificationActions } from '../../slice' import { CardBanner } from '../shared/CardBanner' +import { CardBodyHead } from '../shared/CardBodyHead' import { DownloadButton } from '../shared/DownloadButton' -import { TagBar } from '../shared/TagBar' type PriorNotificationCardProps = Readonly<{ bodyChildren?: React.ReactNode @@ -47,9 +47,6 @@ export function PriorNotificationCard({ const controlledDisplayedErrorKey = displayedError ? DisplayedErrorKey.SIDE_WINDOW_PRIOR_NOTIFICATION_CARD_ERROR : otherDisplayedErrorKey - const hasDesignatedPorts = detail?.logbookMessage.message.pnoTypes?.find(type => type.hasDesignatedPorts) - const isInvalidated = detail?.logbookMessage.message.isInvalidated - const isPendingVerification = detail?.state === PriorNotification.State.PENDING_VERIFICATION const close = () => { dispatch(priorNotificationActions.closePriorNotificationCardAndForm()) @@ -96,8 +93,10 @@ export function PriorNotificationCard({
- - {isPendingVerification && Le préavis doit être vérifié par le CNSP avant sa diffusion.} - - Le navire doit respecter un délai d’envoi{hasDesignatedPorts && ' et débarquer dans un port désigné'}. - -
` - ${p => p.$hasNoTopMargin && 'margin-top: 2px;'} - color: ${p => p.theme.color.slateGray}; - font-style: italic; -` - const Footer = styled.div` border-top: 1px solid ${p => p.theme.color.lightGray}; display: flex; diff --git a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx index bc68a1bd1b..cd0182884d 100644 --- a/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx +++ b/frontend/src/features/PriorNotification/components/PriorNotificationList/index.tsx @@ -302,14 +302,14 @@ const TableInnerWrapper = styled.div<{ $hasError: boolean }>` align-items: flex-start; - height: ${() => (isLegacyFirefox() ? 518 : 513)}px; /* = table height - 5px */ + height: 519px; /* = table height - 5px (negative margin-top) + 1px for Chrome compatibility */ min-width: 1407px; /* = table width + right padding + scrollbar width (8px) */ padding-right: 8px; overflow-y: scroll; width: auto; > table { - margin-top: -4.5px; + margin-top: -5px; } ${p => diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx new file mode 100644 index 0000000000..7cc63e6535 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/SentMessageList.tsx @@ -0,0 +1,149 @@ +import { useGetPriorNotificationSentNessagesQuery } from '@features/PriorNotification/priorNotificationApi' +import { Icon } from '@mtes-mct/monitor-ui' +import { Steps } from 'rsuite' +import styled from 'styled-components' + +import { SentMessagesBatchStatus } from './constants' +import { getSentMessagesBatches, getSubscribersFromSentMessages } from './utils' + +import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +type SentMessageListProps = Readonly<{ + detail: PriorNotification.Detail +}> +export function SentMessageList({ detail }: SentMessageListProps) { + const { data: sentMessages, isError } = useGetPriorNotificationSentNessagesQuery(detail.reportId) + + const sentMessagesBatches = sentMessages ? getSentMessagesBatches(sentMessages) : undefined + const lastSentMessagesBatch = sentMessagesBatches ? sentMessagesBatches[sentMessagesBatches.length - 1] : undefined + const subscribers = lastSentMessagesBatch ? getSubscribersFromSentMessages(lastSentMessagesBatch.messages) : undefined + + return ( + <> + Liste de diffusion du préavis + {isError &&

Impossible de récupérer la liste.

} + {!isError && ( + <> + {!subscribers &&

Chargement en cours...

} + {subscribers && subscribers.length === 0 &&

Aucun message n’a été envoyé pour ce préavis.

} + {subscribers?.map(subsriber => ( + +

+ {subsriber.name} ({subsriber.organization}) +

+ + {subsriber.email && {subsriber.email}} + {subsriber.phone && {subsriber.phone}} + +
+ ))} + + )} + + Historique de diffusion du préavis + {isError &&

Impossible de récupérer l’historique.

} + {!isError && ( + <> + {!sentMessagesBatches &&

Chargement en cours...

} + <> + {sentMessagesBatches && sentMessagesBatches.length === 0 && ( +

Aucun message n’a été envoyé pour ce préavis.

+ )} + + {sentMessagesBatches && ( + + {sentMessagesBatches.map(sentMessagesBatch => ( + + ) : ( + + ) + } + title={ + + {sentMessagesBatch.fistMessageHumanizedDate} + + + } + /> + ))} + + )} + + )} + + ) +} + +const Title = styled.p` + color: ${p => p.theme.color.slateGray}; + margin: 16px 0 0; +` + +const SubscriberRow = styled.address` + background-color: ${p => p.theme.color.gainsboro}; + display: flex; + flex-direction: column; + font-style: normal; + margin-top: 4px; + padding: 16px 12px; +` +const SubscriberRowBody = styled.p` + display: flex; + flex-direction: column; + margin-top: 2px; +` + +const History = styled(Steps)` + background-color: ${p => p.theme.color.gainsboro}; + margin-top: 4px; + min-height: unset; + padding: 12px 16px 0 8px; + + > .rs-steps-item:not(:first-child) { + padding-bottom: 12px; + + &:not(:first-child) { + margin-top: 0px; + } + } +` + +const HistoryItem = styled(Steps.Item)<{ + $isSuccess: boolean +}>` + padding-bottom: 16px; + padding-left: 34px; + + > .rs-steps-item-icon-wrapper { + border-radius: 0; + width: 16px; + } + + > .rs-steps-item-tail { + border-color: ${p => p.theme.color.slateGray}; + border-width: 2px; + left: 7px; + top: 24px; + } + + .rs-steps-item-custom-icon { + color: ${p => (p.$isSuccess ? p.theme.color.mediumSeaGreen : p.theme.color.maximumRed)}; + } +` + +const StepTitle = styled.div` + color: ${p => p.theme.color.gunMetal}; + line-height: 18px; +` +const StepDate = styled.p` + font-weight: 500; +` +const StepStatus = styled.p` + margin-top: 0; +` diff --git a/frontend/src/features/PriorNotification/components/shared/TagBar.tsx b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/TagBar.tsx similarity index 93% rename from frontend/src/features/PriorNotification/components/shared/TagBar.tsx rename to frontend/src/features/PriorNotification/components/shared/CardBodyHead/TagBar.tsx index 4feff4c2b8..e3f26bcba0 100644 --- a/frontend/src/features/PriorNotification/components/shared/TagBar.tsx +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/TagBar.tsx @@ -2,9 +2,9 @@ import { VesselRiskFactor } from '@features/Vessel/components/VesselRiskFactor' import { THEME } from '@mtes-mct/monitor-ui' import styled from 'styled-components' -import { PriorNotification } from '../../PriorNotification.types' -import { FixedTag } from '../PriorNotificationList/styles' -import { getColorsFromState } from '../PriorNotificationList/utils' +import { PriorNotification } from '../../../PriorNotification.types' +import { FixedTag } from '../../PriorNotificationList/styles' +import { getColorsFromState } from '../../PriorNotificationList/utils' import type { LogbookMessage } from '@features/Logbook/LogbookMessage.types' diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts new file mode 100644 index 0000000000..f84bdc680f --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSentMessagesBatches.test.ts @@ -0,0 +1,223 @@ +import { describe, expect, it } from '@jest/globals' + +import { SentMessagesBatchStatus } from '../constants' +import { getSentMessagesBatches } from '../utils' + +import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +describe('features/PriorNotification/components/shared/CardBodyHead > getSentMessagesBatches()', () => { + it('Should return empty array when input is empty', () => { + const sentMessages = [] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(0) + }) + + it('Shoudl return a single batch when input has one message', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + } + ] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(1) + + expect(result[0]!.fistMessageHumanizedDate).toEqual('Le 01/10/2023 à 10h00 (UTC)') + expect(result[0]!.messages).toEqual(sentMessages) + expect(result[0]!.sendStatus).toEqual(SentMessagesBatchStatus.SUCCESS) + expect(result[0]!.statusMessage).toEqual('Préavis diffusé avec succès à tous les contacts.') + }) + + it('Should group messages sent within 30s into one batch', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:20Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email2@example.com', + recipientName: 'Jane Smith', + recipientOrganization: 'Org B', + success: true + } + ] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(1) + + expect(result[0]!.fistMessageHumanizedDate).toEqual('Le 01/10/2023 à 10h00 (UTC)') + expect(result[0]!.messages).toEqual(sentMessages) + expect(result[0]!.sendStatus).toEqual(SentMessagesBatchStatus.SUCCESS) + expect(result[0]!.statusMessage).toEqual('Préavis diffusé avec succès à tous les contacts.') + }) + + it('Should split into batches when messages are sent more than 30s apart', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:31Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email2@example.com', + recipientName: 'Jane Smith', + recipientOrganization: 'Org B', + success: true + } + ] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(2) + + expect(result[0]!.fistMessageHumanizedDate).toEqual('Le 01/10/2023 à 10h00 (UTC)') + expect(result[0]!.messages).toEqual([sentMessages[1]]) + expect(result[0]!.sendStatus).toEqual(SentMessagesBatchStatus.SUCCESS) + + expect(result[1]!.fistMessageHumanizedDate).toEqual('Le 01/10/2023 à 10h00 (UTC)') + expect(result[1]!.messages).toEqual([sentMessages[0]]) + expect(result[1]!.sendStatus).toEqual(SentMessagesBatchStatus.SUCCESS) + }) + + it('Should set `sendStatus` to `PARTIAL_FAILURE` when some messages fail', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:20Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email2@example.com', + recipientName: 'Jane Smith', + recipientOrganization: 'Org B', + success: false + } + ] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(1) + + expect(result[0]!.sendStatus).toEqual(SentMessagesBatchStatus.PARTIAL_FAILURE) + expect(result[0]!.statusMessage).toEqual('Échec de la diffusion pour le contact: email2@example.com.') + }) + + it('Should set `sendStatus` to `TOTAL_FAILURE` when all messages fail', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: false + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:20Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email2@example.com', + recipientName: 'Jane Smith', + recipientOrganization: 'Org B', + success: false + } + ] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(1) + + expect(result[0]!.sendStatus).toEqual(SentMessagesBatchStatus.TOTAL_FAILURE) + expect(result[0]!.statusMessage).toEqual( + 'Échec de la diffusion pour tous les contacts: email1@example.com, email2@example.com.' + ) + }) + + it('Should handles multiple batches with varying success statuses', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:25Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email2@example.com', + recipientName: 'Jane Smith', + recipientOrganization: 'Org B', + success: false + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:01:05Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email3@example.com', + recipientName: 'Alice Johnson', + recipientOrganization: 'Org C', + success: false + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:01:25Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email4@example.com', + recipientName: 'Bob Brown', + recipientOrganization: 'Org D', + success: true + } + ] + + const result = getSentMessagesBatches(sentMessages) + + expect(result).toHaveLength(2) + + expect(result[0]!.fistMessageHumanizedDate).toEqual('Le 01/10/2023 à 10h01 (UTC)') + expect(result[0]!.messages).toEqual([sentMessages[2], sentMessages[3]]) + expect(result[0]!.sendStatus).toEqual(SentMessagesBatchStatus.PARTIAL_FAILURE) + expect(result[0]!.statusMessage).toEqual('Échec de la diffusion pour le contact: email3@example.com.') + + expect(result[1]!.fistMessageHumanizedDate).toEqual('Le 01/10/2023 à 10h00 (UTC)') + expect(result[1]!.messages).toEqual([sentMessages[0], sentMessages[1]]) + expect(result[1]!.sendStatus).toEqual(SentMessagesBatchStatus.PARTIAL_FAILURE) + expect(result[1]!.statusMessage).toEqual('Échec de la diffusion pour le contact: email2@example.com.') + }) +}) diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts new file mode 100644 index 0000000000..099b6c51b3 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/__tests__/getSubscribersFromSentMessages.test.ts @@ -0,0 +1,202 @@ +import { describe, expect, it } from '@jest/globals' + +import { getSubscribersFromSentMessages } from '../utils' + +import type { Subscriber } from '../types' +import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +describe('features/PriorNotification/components/shared/CardBodyHead > getSubscribersFromSentMessages()', () => { + it('Should return an empty array when input is empty', () => { + const sentMessages: PriorNotification.SentMessage[] = [] + + const result = getSubscribersFromSentMessages(sentMessages) + + expect(result).toEqual([]) + }) + + it('Should return a single subscriber when input has one message', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + } + ] + + const result = getSubscribersFromSentMessages(sentMessages) + + expect(result).toEqual([ + { + email: 'email@example.com', + name: 'John Doe', + organization: 'Org A' + } + ] satisfies Subscriber[]) + }) + + it('Should combine messages to the same subscriber with same organization & name', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'SMS', + dateTimeUtc: '2023-10-01T10:01:00Z', + errorMessage: undefined, + recipientAddressOrNumber: '1234567890', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + } + ] + + const result = getSubscribersFromSentMessages(sentMessages) + + expect(result).toEqual([ + { + email: 'email@example.com', + name: 'John Doe', + organization: 'Org A', + phone: '1234567890' + } + ] satisfies Subscriber[]) + }) + + it('Should handle multiple subscribers with different organizations and names', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'SMS', + dateTimeUtc: '2023-10-01T10:01:00Z', + errorMessage: undefined, + recipientAddressOrNumber: '1234567890', + recipientName: 'Jane Smith', + recipientOrganization: 'Org B', + success: true + }, + { + communicationMeans: 'FAX', + dateTimeUtc: '2023-10-01T10:02:00Z', + errorMessage: undefined, + recipientAddressOrNumber: '0987654321', + recipientName: 'Alice Johnson', + recipientOrganization: 'Org C', + success: true + } + ] + + const result = getSubscribersFromSentMessages(sentMessages) + + expect(result).toEqual([ + { + email: 'email1@example.com', + name: 'John Doe', + organization: 'Org A' + }, + { + name: 'Jane Smith', + organization: 'Org B', + phone: '1234567890' + }, + { + name: 'Alice Johnson', + organization: 'Org C', + phone: '0987654321' + } + ] satisfies Subscriber[]) + }) + + it('Should deduplicate subscribers by organization and name', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email1@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:01:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email2@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + } + ] + + const result = getSubscribersFromSentMessages(sentMessages) + + expect(result).toEqual([ + { + email: 'email2@example.com', + name: 'John Doe', + organization: 'Org A' + } + ] satisfies Subscriber[]) + }) + + it('Should set both email and phone when the same subscriber has messages with different communication means', () => { + const sentMessages: PriorNotification.SentMessage[] = [ + { + communicationMeans: 'EMAIL', + dateTimeUtc: '2023-10-01T10:00:00Z', + errorMessage: undefined, + recipientAddressOrNumber: 'email@example.com', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'SMS', + dateTimeUtc: '2023-10-01T10:01:00Z', + errorMessage: undefined, + recipientAddressOrNumber: '1234567890', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + }, + { + communicationMeans: 'FAX', + dateTimeUtc: '2023-10-01T10:02:00Z', + errorMessage: undefined, + recipientAddressOrNumber: '0987654321', + recipientName: 'John Doe', + recipientOrganization: 'Org A', + success: true + } + ] + + const result = getSubscribersFromSentMessages(sentMessages) + + expect(result).toEqual([ + { + email: 'email@example.com', + name: 'John Doe', + organization: 'Org A', + phone: '0987654321' + } + ] satisfies Subscriber[]) + }) +}) diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/constants.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/constants.ts new file mode 100644 index 0000000000..462a3811e1 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/constants.ts @@ -0,0 +1,5 @@ +export enum SentMessagesBatchStatus { + PARTIAL_FAILURE = 'PARTIAL_FAILURE', + SUCCESS = 'SUCCESS', + TOTAL_FAILURE = 'TOTAL_FAILURE' +} diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/index.tsx b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/index.tsx new file mode 100644 index 0000000000..5451e84d26 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/index.tsx @@ -0,0 +1,103 @@ +import { PriorNotification } from '@features/PriorNotification/PriorNotification.types' +import { LinkButton, type Undefine } from '@mtes-mct/monitor-ui' +import { useState } from 'react' +import styled from 'styled-components' + +import { SentMessageList } from './SentMessageList' +import { TagBar } from './TagBar' + +import type { LogbookMessage } from '@features/Logbook/LogbookMessage.types' + +type CardBodyHeadProps = Readonly<{ + detail: PriorNotification.Detail | undefined + editedPriorNotificationComputedValues?: Undefine | undefined + hasBeenComputed: boolean + isNewPriorNotification: boolean + isPriorNotificationZero: boolean | undefined + isVesselUnderCharter: boolean | undefined + riskFactor: number | undefined + state: PriorNotification.State | undefined + tripSegments: LogbookMessage.Segment[] | undefined + types: PriorNotification.Type[] | undefined +}> +export function CardBodyHead({ + detail, + editedPriorNotificationComputedValues, + hasBeenComputed, + isNewPriorNotification, + isPriorNotificationZero, + isVesselUnderCharter, + riskFactor, + state, + tripSegments, + types +}: CardBodyHeadProps) { + const [isSentMessageListExpanded, setIsSentMessageListExpanded] = useState(false) + + const hasDesignatedPorts = detail?.logbookMessage.message.pnoTypes?.find(type => type.hasDesignatedPorts) + const isInvalidated = detail?.logbookMessage.message.isInvalidated + const isPendingVerification = detail?.state === PriorNotification.State.PENDING_VERIFICATION + + const collapseSentMessageList = () => { + setIsSentMessageListExpanded(false) + } + + const expandSentMessageList = () => { + setIsSentMessageListExpanded(true) + } + + return ( + <> + + + {isNewPriorNotification && !editedPriorNotificationComputedValues && ( + + Veuillez renseigner les champs du formulaire pour définir le type de préavis et son statut, ainsi que le + segment de flotte et la note de risque du navire. + + )} + {!isNewPriorNotification && isPendingVerification && ( + Le préavis doit être vérifié par le CNSP avant sa diffusion. + )} + {(!!editedPriorNotificationComputedValues || !!detail) && ( + + Le navire doit respecter un délai d’envoi{hasDesignatedPorts && ' et débarquer dans un port désigné'}. + + )} + + {!isSentMessageListExpanded && !!detail && ( + Voir les détails de la diffusion du préavis + )} + {isSentMessageListExpanded && !!detail && ( + <> + + + + Masquer les détails de la diffusion du préavis + + + )} + + ) +} + +const Intro = styled.p<{ + $withTopMargin?: boolean +}>` + ${p => p.$withTopMargin && 'margin-top: 2px;'} + color: ${p => p.theme.color.slateGray}; + font-style: italic; +` + +const StyledLinkButton = styled(LinkButton)` + margin-top: 16px; +` diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/types.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/types.ts new file mode 100644 index 0000000000..ed39aa8247 --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/types.ts @@ -0,0 +1,16 @@ +import type { SentMessagesBatchStatus } from './constants' +import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +export type Subscriber = { + email?: string + name: string + organization: string + phone?: string +} + +export type SentMessageBatch = { + fistMessageHumanizedDate: string + messages: PriorNotification.SentMessage[] + sendStatus: SentMessagesBatchStatus + statusMessage: string +} diff --git a/frontend/src/features/PriorNotification/components/shared/CardBodyHead/utils.ts b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/utils.ts new file mode 100644 index 0000000000..acc7debafe --- /dev/null +++ b/frontend/src/features/PriorNotification/components/shared/CardBodyHead/utils.ts @@ -0,0 +1,114 @@ +import { customDayjs, pluralize } from '@mtes-mct/monitor-ui' +import dayjs from 'dayjs' + +import { SentMessagesBatchStatus } from './constants' + +import type { SentMessageBatch, Subscriber } from './types' +import type { PriorNotification } from '@features/PriorNotification/PriorNotification.types' + +export function getSubscribersFromSentMessages(sentMessages: PriorNotification.SentMessage[]): Subscriber[] { + const subscribersMap = sentMessages.reduce>((subscribersMapAccumulator, sentMessage) => { + const subscriberKey = `${sentMessage.recipientOrganization}-${sentMessage.recipientName}` + + if (!subscribersMapAccumulator[subscriberKey]) { + // eslint-disable-next-line no-param-reassign + subscribersMapAccumulator[subscriberKey] = { + name: sentMessage.recipientName, + organization: sentMessage.recipientOrganization + } + } + + const subscriber = subscribersMapAccumulator[subscriberKey] + if (sentMessage.communicationMeans === 'EMAIL') { + subscriber.email = sentMessage.recipientAddressOrNumber + } else if (sentMessage.communicationMeans === 'SMS' || sentMessage.communicationMeans === 'FAX') { + subscriber.phone = sentMessage.recipientAddressOrNumber + } + + return subscribersMapAccumulator + }, {}) + + return Object.values(subscribersMap) +} + +/** + * Get sent messages batches from a list of sent messages grouped by batch of 30s and ordered by date descending. + */ +export function getSentMessagesBatches(sentMessages: PriorNotification.SentMessage[]): SentMessageBatch[] { + const sentMessagesSortedByDateAsc = [...sentMessages].sort((a, b) => (a.dateTimeUtc < b.dateTimeUtc ? -1 : 1)) + + const sentMessageBatches: SentMessageBatch[] = [] + let currentBatch: PriorNotification.SentMessage[] = [] + let currentBatchFirstSentMessageDate: string | undefined + + sentMessagesSortedByDateAsc.forEach(sentMessage => { + if (!currentBatchFirstSentMessageDate) { + currentBatchFirstSentMessageDate = sentMessage.dateTimeUtc + currentBatch.push(sentMessage) + + return + } + + const timeDifference = dayjs(sentMessage.dateTimeUtc).diff(dayjs(currentBatchFirstSentMessageDate), 'second') + + // If this message was sent less than 30s after the first message of the current batch, + // we consider it as part of the same batch + if (timeDifference <= 30) { + currentBatch.push(sentMessage) + + return + } + + // Otherwise, we consider the current batch as complete + sentMessageBatches.push(processBatch(currentBatch)) + + // and we start a new one + currentBatch = [sentMessage] + currentBatchFirstSentMessageDate = sentMessage.dateTimeUtc + }) + + // Let's not forget to process the last batch since it's not followed by another batch + if (currentBatch.length > 0) { + sentMessageBatches.push(processBatch(currentBatch)) + } + + return sentMessageBatches.reverse() +} + +function processBatch(messages: PriorNotification.SentMessage[]): SentMessageBatch { + const fistMessageHumanizedDate = customDayjs + .utc(messages[0]!.dateTimeUtc) + .format('[Le] DD/MM/YYYY [à] HH[h]mm [(UTC)]') + const [sendStatus, statusMessage] = getStatusAndStatusMessage(messages) + + return { + fistMessageHumanizedDate, + messages, + sendStatus, + statusMessage + } +} + +function getStatusAndStatusMessage(messages: PriorNotification.SentMessage[]): [SentMessagesBatchStatus, string] { + const failedEmailsAndPhones = messages + .filter(({ success }) => !success) + .map(({ recipientAddressOrNumber }) => recipientAddressOrNumber) + const failedEmailsAndPhonesAsHtml = failedEmailsAndPhones.map(emailOrPhone => `${emailOrPhone}`).join(', ') + + switch (true) { + case failedEmailsAndPhones.length === messages.length: + return [ + SentMessagesBatchStatus.TOTAL_FAILURE, + `Échec de la diffusion pour tous les contacts: ${failedEmailsAndPhonesAsHtml}.` + ] + + case failedEmailsAndPhones.length > 0: + return [ + SentMessagesBatchStatus.PARTIAL_FAILURE, + `Échec de la diffusion pour ${pluralize('le', failedEmailsAndPhones.length)} ${pluralize('contact', failedEmailsAndPhones.length)}: ${failedEmailsAndPhonesAsHtml}.` + ] + + default: + return [SentMessagesBatchStatus.SUCCESS, 'Préavis diffusé avec succès à tous les contacts.'] + } +} diff --git a/frontend/src/features/PriorNotification/priorNotificationApi.ts b/frontend/src/features/PriorNotification/priorNotificationApi.ts index 5223d833ce..7f4f95bcd3 100644 --- a/frontend/src/features/PriorNotification/priorNotificationApi.ts +++ b/frontend/src/features/PriorNotification/priorNotificationApi.ts @@ -16,6 +16,8 @@ const CREATE_PRIOR_NOTIFICATION_ERROR_MESSAGE = "Nous n'avons pas pu créé le p const DELETE_PRIOR_NOTIFICATION_UPLOAD_ERROR_MESSAGE = "Nous n'avons pas pu supprimer ce document attaché." const GET_PRIOR_NOTIFICATION_UPLOADS_ERROR_MESSAGE = "Nous n'avons pas pu récupérer les documents attachés à ce préavis." +const GET_PRIOR_NOTIFICATION_SENT_MESSAGES_ERROR_MESSAGE = + "Nous n'avons pas pu récupérer la liste des envois correspondant à ce préavis." const UPDATE_PRIOR_NOTIFICATION_ERROR_MESSAGE = "Nous n'avons pas pu modifier le préavis." const GET_PRIOR_NOTIFICATION_DETAIL_ERROR_MESSAGE = "Nous n'avons pas pu récupérer le préavis." const GET_PRIOR_NOTIFICATIONS_ERROR_MESSAGE = "Nous n'avons pas pu récupérer la liste des préavis." @@ -128,6 +130,13 @@ export const priorNotificationApi = monitorfishApi.injectEndpoints({ transformErrorResponse: response => new FrontendApiError(GET_PRIOR_NOTIFICATIONS_ERROR_MESSAGE, response) }), + getPriorNotificationSentNessages: builder.query({ + providesTags: () => [{ type: RtkCacheTagType.PriorNotificationSentMessages }], + query: reportId => `/prior_notifications/${reportId}/sent_messages`, + transformErrorResponse: response => + new FrontendApiError(GET_PRIOR_NOTIFICATION_SENT_MESSAGES_ERROR_MESSAGE, response) + }), + getPriorNotificationsToVerify: builder.query({ providesTags: () => [{ type: RtkCacheTagType.PriorNotificationsToVerify }], query: () => '/prior_notifications/to_verify', @@ -230,6 +239,7 @@ export const priorNotificationApi = monitorfishApi.injectEndpoints({ export const { useGetPriorNotificationPdfExistenceQuery, + useGetPriorNotificationSentNessagesQuery, useGetPriorNotificationsQuery, useGetPriorNotificationsToVerifyQuery, useGetPriorNotificationTypesQuery,