diff --git a/.gitignore b/.gitignore index 50dbd5ccdd1..781c27d792f 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ target .classpath .settings work*/ +!workflows .DS_Store build .gradle diff --git a/Jenkinsfile b/Jenkinsfile index 664c0b751c7..c57e1f964d6 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -219,11 +219,15 @@ pipeline { post { always { recordIssues(tools: [kotlin(), javaDoc(), java()]) - // Build validation stamp + // Build validation stamps ontrackCliValidateTests( stamp: 'BUILD', pattern: '**/build/test-results/**/*.xml', ) + ontrackCliValidateTests( + stamp: 'UI_UNIT', + pattern: 'ontrack-web-core/reports/*.xml', + ) } } } diff --git a/ontrack-common/src/main/java/net/nemerosa/ontrack/common/ExceptionUtils.kt b/ontrack-common/src/main/java/net/nemerosa/ontrack/common/ExceptionUtils.kt new file mode 100644 index 00000000000..c134ac480b6 --- /dev/null +++ b/ontrack-common/src/main/java/net/nemerosa/ontrack/common/ExceptionUtils.kt @@ -0,0 +1,9 @@ +package net.nemerosa.ontrack.common + +import org.apache.commons.lang3.exception.ExceptionUtils + +private const val MAX_STACK_HEIGHT = 20 +private const val MAX_STACK_LENGTH = 2000 + +fun reducedStackTrace(error: Throwable) = + ExceptionUtils.getStackFrames(error).take(MAX_STACK_HEIGHT).joinToString("\n").take(MAX_STACK_LENGTH) diff --git a/ontrack-docs/src/docs/asciidoc/appendix-workflow-node-executors.adoc b/ontrack-docs/src/docs/asciidoc/appendix-workflow-node-executors.adoc new file mode 100644 index 00000000000..b16956efd08 --- /dev/null +++ b/ontrack-docs/src/docs/asciidoc/appendix-workflow-node-executors.adoc @@ -0,0 +1,6 @@ +[[appendix-workflow-node-executors]] +=== Workflow nodes executors + +Find below the list of all workflow node executors and their configurations. + +include::workflow-node-executors/index.adoc[] diff --git a/ontrack-docs/src/docs/asciidoc/appendixes.adoc b/ontrack-docs/src/docs/asciidoc/appendixes.adoc index 16d848b1a69..77b15d43950 100644 --- a/ontrack-docs/src/docs/asciidoc/appendixes.adoc +++ b/ontrack-docs/src/docs/asciidoc/appendixes.adoc @@ -9,6 +9,8 @@ include::appendix-events.adoc[] include::appendix-notifications.adoc[] +include::appendix-workflow-node-executors.adoc[] + // include::appendix-deprecations.adoc[] // include::appendix-roadmap.adoc[] diff --git a/ontrack-docs/src/docs/asciidoc/feature-workflows.adoc b/ontrack-docs/src/docs/asciidoc/feature-workflows.adoc new file mode 100644 index 00000000000..752d28cdd2e --- /dev/null +++ b/ontrack-docs/src/docs/asciidoc/feature-workflows.adoc @@ -0,0 +1,158 @@ +[[workflows]] +=== Workflows + +Workflows allow the execution of several actions orchestrated in a DAG (directed acyclic graph). + +[NOTE] +==== +As of version 4.8, workflows can only be triggered using the <>. + +There is already some partial and undocumented support through API calls to run some standalone workflows but this is very experimental. +==== + +[[workflow-definitions]] +==== Workflows definitions + +To run a workflow, you can define a notification whose channel is `workflow`. + +This can be done through the UI or as code. + +[NOTE] +==== +Workflows definitions in the UI is only supported in the Next UI of Ontrack and won't be supported in the legacy UI. +==== + +A workflow: + +* has a name, used for information and display purposes +* has a list of nodes + +Each node: + +* has an ID which must be unique inside the workflow +* an executor ID that points to a _workflow node executor_ +* some data for the _workflow node executor_ +* a list of parent nodes + +The list of parent nodes is what defines the workflow DAG. + +[NOTE] +==== +When defining or running workflows, graph cycles are automatically detected. +==== + +Workflows notifications can be defined as code, like all other <>. + +For example: + +[source,yaml] +---- +channel: workflow +channelConfig: + workflow: + name: My workflow + nodes: + - id: ticket + executorId: notification + data: + channel: jira-creation + channelConfig: + # Configuration for the ticket creation + - id: mail + executorId: notification + parents: + - id: ticket + data: + channel: mail + channelConfig: + # Configuration for the mail + template: | + Link to ticket: ${workflow.ticket?path=url} +---- + +[[workflow-executors]] +==== Workflows nodes executors + +A _workflow node executor_ is a component which is responsible to "run a node". + +See <> for a list of all existing workflow node executors. + +[[workflow-templates]] +==== Workflow templating + +Many elements in the workflow definition are subject to <>. + +The workflow name is itself considered as a template when being run as a notification (which is the default in 4.8). + +When using <>, the configuration elements are templates as usual. + +Note that for a workflow notification, the event is passed as a context element and all template functions and sources are available. + +Additionally, when a notification is run as part of a workflow, a new templating function is available: `workflow`. + +This function allows the access to the output data of any successful node in the workflow. + +For example, let's take a workflow which: + +* creates a ticket in Jira +* then send a link to this ticket with an email + + + +[source,yaml] +---- +channel: workflow +channelConfig: + workflow: + name: My workflow + nodes: + - id: ticket + executorId: notification + data: + channel: jira-creation + channelConfig: + # Configuration for the ticket creation + - id: mail + executorId: notification + parents: + - id: ticket + data: + channel: mail + channelConfig: + # Configuration for the mail + template: | + Link to ticket: ${workflow.ticket?path=url} +---- + +The `ticket` node runs and set some information in its output (see <> for the full details), including a `url` property. + +Then, the `mail` node is run and is using the `notification` _workflow node executor_ again, with the <> being configured to send a mail. + +This channel can use the `template` for the mail's body and is using the `workflow` function to get the output of the `ticket` node and the `url` property of its output. + +[[workflow-management]] +==== Workflows management + +The progress of running workflows can be accessed in _Information > Workflow audit_. + +Clicking on a workflow displays more details about its current status, node per node. + +When using the _workflow notification channel_, the workflow status link is also accessible from the _Information > Notification recordings_, when selecting the notification. + +[[workflow-settings]] +==== Workflows settings + +Workflow statuses are saved by default for 14 days. + +To change this value, you can go to _System > Settings > Workflows_. + +This can also be defined as code using <>: + +[source,yaml] +---- +ontrack: + config: + settings: + workflows: + retentionDuration: 1209600000 # 14 days in ms +---- diff --git a/ontrack-docs/src/docs/asciidoc/features.adoc b/ontrack-docs/src/docs/asciidoc/features.adoc index d061d780d91..1b79ad9f60e 100644 --- a/ontrack-docs/src/docs/asciidoc/features.adoc +++ b/ontrack-docs/src/docs/asciidoc/features.adoc @@ -7,6 +7,8 @@ include::feature-branches.adoc[] include::feature-scm.adoc[] +include::feature-workflows.adoc[] + //include::usage-validation-stamps.adoc[] // //include::usage-promotion-levels.adoc[] diff --git a/ontrack-docs/src/docs/asciidoc/notifications/index.adoc b/ontrack-docs/src/docs/asciidoc/notifications/index.adoc index ca864929595..81e82cbc88d 100644 --- a/ontrack-docs/src/docs/asciidoc/notifications/index.adoc +++ b/ontrack-docs/src/docs/asciidoc/notifications/index.adoc @@ -7,6 +7,7 @@ * <> * <> * <> +* <> include::notification-backend-jenkins.adoc[] include::notification-backend-jira-creation.adoc[] @@ -14,3 +15,4 @@ include::notification-backend-jira-service-desk.adoc[] include::notification-backend-mail.adoc[] include::notification-backend-slack.adoc[] include::notification-backend-webhook.adoc[] +include::notification-backend-workflow.adoc[] diff --git a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jenkins.adoc b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jenkins.adoc index 3b082793401..12cfbfd258f 100644 --- a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jenkins.adoc +++ b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jenkins.adoc @@ -3,6 +3,10 @@ This channel is used to trigger remote Jenkins jobs with some parameters. + + +_This channel does not use the custom template._ + Links: * <> diff --git a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jira-service-desk.adoc b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jira-service-desk.adoc index ddc82977533..83b252e9f36 100644 --- a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jira-service-desk.adoc +++ b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-jira-service-desk.adoc @@ -3,6 +3,10 @@ This channel is used to create a Jira Service Desk ticket. + + +_This channel does not use the custom template._ + Configuration: * **configName** - String - required - Name of the Jira configuration to use for the connection diff --git a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-webhook.adoc b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-webhook.adoc index 7f9a757d95e..2f4fd76d4a9 100644 --- a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-webhook.adoc +++ b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-webhook.adoc @@ -3,6 +3,10 @@ Calling an external webhook + + +_This channel does not use the custom template._ + Configuration: * **name** - String - required - Name of the webhook to use diff --git a/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-workflow.adoc b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-workflow.adoc new file mode 100644 index 00000000000..83f81fcddac --- /dev/null +++ b/ontrack-docs/src/docs/asciidoc/notifications/notification-backend-workflow.adoc @@ -0,0 +1,31 @@ +[[notification-backend-workflow]] +==== Workflow (`workflow`) + +Launches a workflow + + + +_This channel does not use the custom template._ + +Configuration: + +* **workflow** - Object - required - Workflow to run + +** **name** - String - required - Display name for the workflow + +** **nodes** - List - required - List of nodes in the workflow + +*** **data** - JSON - required - Raw data associated with the node, to be used by the node executor. + +*** **executorId** - String - required - ID of the executor to use + +*** **id** - String - required - Unique ID of the node in its workflow. + +*** **parents** - List - required - List of the IDs of the parents for this node + +**** **id** - String - required - ID of the parent node + +Output: + +* **workflowInstanceId** - String - required - ID of the workflow instance. Can be used to track the progress and outcome of the workflow. + diff --git a/ontrack-docs/src/docs/asciidoc/workflow-node-executors/index.adoc b/ontrack-docs/src/docs/asciidoc/workflow-node-executors/index.adoc new file mode 100644 index 00000000000..262c1e226e0 --- /dev/null +++ b/ontrack-docs/src/docs/asciidoc/workflow-node-executors/index.adoc @@ -0,0 +1,8 @@ +[[appendix-workflow-node-executors-index]] +==== List of workflow node executors + +* <> +* <> + +include::workflow-node-executor-mock.adoc[] +include::workflow-node-executor-notification.adoc[] diff --git a/ontrack-docs/src/docs/asciidoc/workflow-node-executors/workflow-node-executor-mock.adoc b/ontrack-docs/src/docs/asciidoc/workflow-node-executors/workflow-node-executor-mock.adoc new file mode 100644 index 00000000000..b0d91f21c9f --- /dev/null +++ b/ontrack-docs/src/docs/asciidoc/workflow-node-executors/workflow-node-executor-mock.adoc @@ -0,0 +1,27 @@ +[[workflow-node-executor-mock]] +==== Mock (mock) + +Executor used to mock some actions for the nodes. Mostly used for testing. + +Configuration: + +* **error** - Boolean - required - Raising an error during the execution of the node + +* **text** - String - required - Text associated with the node + +* **waitMs** - Long - required - Time to wait for the execution of the node + +Output: + +* **text** - String - required - text field + +Example: + +[source] +---- +executorId: mock +data: + text: Some text to store + waitMs: 500 + error: false +---- diff --git a/ontrack-docs/src/docs/asciidoc/workflow-node-executors/workflow-node-executor-notification.adoc b/ontrack-docs/src/docs/asciidoc/workflow-node-executors/workflow-node-executor-notification.adoc new file mode 100644 index 00000000000..10ea0ed1c33 --- /dev/null +++ b/ontrack-docs/src/docs/asciidoc/workflow-node-executors/workflow-node-executor-notification.adoc @@ -0,0 +1,28 @@ +[[workflow-node-executor-notification]] +==== Notification (notification) + +Wraps a notification in a workflow node. + +The output of this execution is exactly the output +of the notification channel. + +Configuration: + +* **channel** - String - required - Notification channel ID + +* **channelConfig** - JSON - required - Notification channel configuration + +* **template** - String - optional - Optional template for the notification + +Example: + +[source] +---- +executorId: notification +data: + channel: slack + channelConfig: + channel: "#my-channel" + template: | + Message template +---- diff --git a/ontrack-extension-auto-versioning/build.gradle.kts b/ontrack-extension-auto-versioning/build.gradle.kts index b2bf91c32f8..fa75814c3dd 100644 --- a/ontrack-extension-auto-versioning/build.gradle.kts +++ b/ontrack-extension-auto-versioning/build.gradle.kts @@ -16,7 +16,7 @@ dependencies { implementation(project(":ontrack-repository-support")) implementation(project(":ontrack-rabbitmq")) implementation("io.micrometer:micrometer-core") - implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") // TODO Remove when removing the Yaml class implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.apache.commons:commons-lang3") implementation("jakarta.annotation:jakarta.annotation-api") diff --git a/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/audit/AbstractAutoVersioningAuditService.kt b/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/audit/AbstractAutoVersioningAuditService.kt index 753c5eac576..65eb70127b2 100644 --- a/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/audit/AbstractAutoVersioningAuditService.kt +++ b/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/audit/AbstractAutoVersioningAuditService.kt @@ -1,7 +1,7 @@ package net.nemerosa.ontrack.extension.av.audit +import net.nemerosa.ontrack.common.reducedStackTrace import net.nemerosa.ontrack.extension.av.dispatcher.AutoVersioningOrder -import org.apache.commons.lang3.exception.ExceptionUtils import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -11,14 +11,6 @@ abstract class AbstractAutoVersioningAuditService( protected val logger: Logger = LoggerFactory.getLogger(AutoVersioningAuditService::class.java) - companion object { - private const val MAX_STACK_HEIGHT = 20 - private const val MAX_STACK_LENGTH = 2000 - - fun reducedStackTrace(error: Throwable) = - ExceptionUtils.getStackFrames(error).take(MAX_STACK_HEIGHT).joinToString("\n").take(MAX_STACK_LENGTH) - } - override fun onQueuing(order: AutoVersioningOrder, routing: String, cancelling: Boolean) { if (cancelling) { store.cancelQueuedOrders(order) diff --git a/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/properties/yaml/Yaml.kt b/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/properties/yaml/Yaml.kt index 9c37b01498a..50bc3f255d3 100644 --- a/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/properties/yaml/Yaml.kt +++ b/ontrack-extension-auto-versioning/src/main/java/net/nemerosa/ontrack/extension/av/properties/yaml/Yaml.kt @@ -8,6 +8,7 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule import com.fasterxml.jackson.module.kotlin.readValues import java.io.StringWriter +@Deprecated("Will be removed in V5. Use the Yaml class from the ontrack-json module") class Yaml { private val yamlFactory = YAMLFactory().apply { diff --git a/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/audit/AutoVersioningAuditServiceIT.kt b/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/audit/AutoVersioningAuditServiceIT.kt index 00733340dcd..44b5885aafa 100644 --- a/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/audit/AutoVersioningAuditServiceIT.kt +++ b/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/audit/AutoVersioningAuditServiceIT.kt @@ -1,5 +1,6 @@ package net.nemerosa.ontrack.extension.av.audit +import net.nemerosa.ontrack.common.reducedStackTrace import net.nemerosa.ontrack.extension.av.AbstractAutoVersioningTestSupport import net.nemerosa.ontrack.extension.av.AutoVersioningTestFixtures.createOrder import net.nemerosa.ontrack.extension.av.audit.AutoVersioningAuditTestFixtures.assertAudit @@ -162,7 +163,7 @@ class AutoVersioningAuditServiceIT : AbstractAutoVersioningTestSupport() { entry, audit( AutoVersioningAuditState.ERROR, - "error" to AbstractAutoVersioningAuditService.reducedStackTrace(error) + "error" to reducedStackTrace(error) ), audit(AutoVersioningAuditState.PR_CREATING, "branch" to "feature/version-2.0.0"), audit( diff --git a/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/config/AutoVersioningConfigurationServiceIT.kt b/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/config/AutoVersioningConfigurationServiceIT.kt index 218b79ad6a9..868c001674a 100644 --- a/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/config/AutoVersioningConfigurationServiceIT.kt +++ b/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/config/AutoVersioningConfigurationServiceIT.kt @@ -643,6 +643,7 @@ internal class AutoVersioningConfigurationServiceIT : AbstractAutoVersioningTest channel = "mock", channelConfig = mapOf( "target" to target, + "data" to null, ).asJson(), disabled = false, origin = "test", diff --git a/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/event/AutoVersioningEventsIT.kt b/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/event/AutoVersioningEventsIT.kt index d2c9bcbfa8c..5120580906f 100644 --- a/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/event/AutoVersioningEventsIT.kt +++ b/ontrack-extension-auto-versioning/src/test/java/net/nemerosa/ontrack/extension/av/event/AutoVersioningEventsIT.kt @@ -38,7 +38,11 @@ internal class AutoVersioningEventsIT : AbstractDSLTestSupport() { link = "https://job.link", ) ) - val text = eventTemplatingService.renderEvent(event, renderer = htmlNotificationEventRenderer) + val text = eventTemplatingService.renderEvent( + event, + context = emptyMap(), + renderer = htmlNotificationEventRenderer + ) assertEquals( """ Auto versioning post-processing of ${target.project.name}/${target.name} for dependency ${project.name} version "1.1.0" has failed. @@ -72,7 +76,11 @@ internal class AutoVersioningEventsIT : AbstractDSLTestSupport() { merged = true, ) ) - val text = eventTemplatingService.renderEvent(event, renderer = htmlNotificationEventRenderer) + val text = eventTemplatingService.renderEvent( + event, + context = emptyMap(), + renderer = htmlNotificationEventRenderer + ) assertEquals( """ Auto versioning of ${target.project.name}/${target.name} for dependency ${project.name} version "1.1.0" has been done. @@ -103,7 +111,11 @@ internal class AutoVersioningEventsIT : AbstractDSLTestSupport() { message = "Processing failed.", error = RuntimeException("Processing failed because of this error.") ) - val text = eventTemplatingService.renderEvent(event, renderer = htmlNotificationEventRenderer) + val text = eventTemplatingService.renderEvent( + event, + context = emptyMap(), + renderer = htmlNotificationEventRenderer + ) assertEquals( """ Auto versioning of ${target.project.name}/${target.name} for dependency ${project.name} version "1.1.0" has failed. @@ -138,7 +150,11 @@ internal class AutoVersioningEventsIT : AbstractDSLTestSupport() { merged = true, ) ) - val text = eventTemplatingService.renderEvent(event, renderer = htmlNotificationEventRenderer) + val text = eventTemplatingService.renderEvent( + event, + context = emptyMap(), + renderer = htmlNotificationEventRenderer + ) assertEquals( """ Auto versioning of ${target.project.name}/${target.name} for dependency ${project.name} version "1.1.0" has failed. diff --git a/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/MetaInfoPropertyTemplatingSourceIT.kt b/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/MetaInfoPropertyTemplatingSourceIT.kt index 90e8a709048..e71f66dc997 100644 --- a/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/MetaInfoPropertyTemplatingSourceIT.kt +++ b/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/MetaInfoPropertyTemplatingSourceIT.kt @@ -41,6 +41,7 @@ class MetaInfoPropertyTemplatingSourceIT : AbstractDSLTestSupport() { eventTemplatingService.render( template = "Link to ticket: ${'$'}{build.meta?name=meta-key&category=my-cat&link=true}", event = event, + context = emptyMap(), renderer = HtmlNotificationEventRenderer(OntrackConfigProperties()) ) ) diff --git a/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/ReleasePropertyTemplatingSourceIT.kt b/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/ReleasePropertyTemplatingSourceIT.kt index e137c1c2cfb..2c85bfbe7e1 100644 --- a/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/ReleasePropertyTemplatingSourceIT.kt +++ b/ontrack-extension-general/src/test/java/net/nemerosa/ontrack/extension/general/ReleasePropertyTemplatingSourceIT.kt @@ -32,6 +32,7 @@ class ReleasePropertyTemplatingSourceIT : AbstractDSLTestSupport() { eventTemplatingService.render( template = "Release: ${'$'}{build.release} for ${'$'}{build}", event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) ) @@ -56,6 +57,7 @@ class ReleasePropertyTemplatingSourceIT : AbstractDSLTestSupport() { eventTemplatingService.render( template = "Release: ${'$'}{build.release} for ${'$'}{build}", event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) ) diff --git a/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/AbstractJenkinsNotificationChannel.kt b/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/AbstractJenkinsNotificationChannel.kt index 82cb1fe9181..b20700cea7e 100644 --- a/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/AbstractJenkinsNotificationChannel.kt +++ b/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/AbstractJenkinsNotificationChannel.kt @@ -21,6 +21,7 @@ abstract class AbstractJenkinsNotificationChannel( override fun publish( config: JenkinsNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: JenkinsNotificationChannelOutput) -> JenkinsNotificationChannelOutput ): NotificationResult { @@ -33,12 +34,14 @@ abstract class AbstractJenkinsNotificationChannel( val job = eventTemplatingService.render( template = config.job, event = event, + context = context, renderer = PlainEventRenderer.INSTANCE, ) val parameters = config.parameters.associate { it.name to eventTemplatingService.render( template = it.value, event = event, + context = context, renderer = PlainEventRenderer.INSTANCE ) } diff --git a/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannel.kt b/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannel.kt index fdd6c4ecc61..4142bfa0602 100644 --- a/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannel.kt +++ b/ontrack-extension-jenkins/src/main/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannel.kt @@ -4,6 +4,7 @@ import net.nemerosa.ontrack.extension.jenkins.JenkinsConfiguration import net.nemerosa.ontrack.extension.jenkins.JenkinsConfigurationService import net.nemerosa.ontrack.extension.jenkins.client.JenkinsClient import net.nemerosa.ontrack.extension.jenkins.client.JenkinsClientFactory +import net.nemerosa.ontrack.extension.notifications.channels.NoTemplate import net.nemerosa.ontrack.model.annotations.APIDescription import net.nemerosa.ontrack.model.docs.Documentation import net.nemerosa.ontrack.model.docs.DocumentationLink @@ -14,6 +15,7 @@ import org.springframework.stereotype.Component @Documentation(JenkinsNotificationChannelConfig::class) @Documentation(JenkinsNotificationChannelOutput::class, section = "output") @DocumentationLink(value = "integration-jenkins-notifications", name = "Jenkins notifications") +@NoTemplate @Component class JenkinsNotificationChannel( jenkinsConfigurationService: JenkinsConfigurationService, diff --git a/ontrack-extension-jenkins/src/test/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannelTest.kt b/ontrack-extension-jenkins/src/test/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannelTest.kt index 9377e83cf92..e16b430b110 100644 --- a/ontrack-extension-jenkins/src/test/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannelTest.kt +++ b/ontrack-extension-jenkins/src/test/java/net/nemerosa/ontrack/extension/jenkins/notifications/JenkinsNotificationChannelTest.kt @@ -71,7 +71,7 @@ class JenkinsNotificationChannelTest { every { jenkinsClient.fireAndForgetJob(JOB, emptyMap()) } returns URI("uri:queue") - val result = jenkinsNotificationChannel.publish(config, event, null) { it } + val result = jenkinsNotificationChannel.publish(config, event, emptyMap(), null) { it } assertEquals(NotificationResultType.OK, result.type) } @@ -93,7 +93,7 @@ class JenkinsNotificationChannelTest { ) } returns URI("uri:queue") - val result = jenkinsNotificationChannel.publish(config, event, null) { it } + val result = jenkinsNotificationChannel.publish(config, event, emptyMap(), null) { it } assertEquals(NotificationResultType.OK, result.type) } @@ -105,7 +105,7 @@ class JenkinsNotificationChannelTest { every { jenkinsClient.fireAndForgetJob(JOB, emptyMap()) } returns null - val result = jenkinsNotificationChannel.publish(config, event, null) { it } + val result = jenkinsNotificationChannel.publish(config, event, emptyMap(), null) { it } assertEquals(NotificationResultType.ERROR, result.type) } @@ -126,7 +126,7 @@ class JenkinsNotificationChannelTest { every { jenkinsClient.runJob(JOB, emptyMap(), any(), any()) } returns jenkinsBuild - val result = jenkinsNotificationChannel.publish(config, event, null) { it } + val result = jenkinsNotificationChannel.publish(config, event, emptyMap(), null) { it } assertEquals(NotificationResultType.OK, result.type) } @@ -147,7 +147,7 @@ class JenkinsNotificationChannelTest { every { jenkinsClient.runJob(JOB, emptyMap(), any(), any()) } returns jenkinsBuild - val result = jenkinsNotificationChannel.publish(config, event, null) { it } + val result = jenkinsNotificationChannel.publish(config, event, emptyMap(), null) { it } assertEquals(NotificationResultType.ERROR, result.type) } @@ -173,7 +173,7 @@ class JenkinsNotificationChannelTest { val event = EventFactoryImpl().newPromotionRun(promotionRun) every { - eventTemplatingService.render(any(), any(), any()) + eventTemplatingService.render(any(), any(), any(), any()) } answers { // Unchanged path it.invocation.args.first() as String diff --git a/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/notifications/JiraCreationNotificationChannel.kt b/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/notifications/JiraCreationNotificationChannel.kt index 6e60dfbfa8b..32046069cb7 100644 --- a/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/notifications/JiraCreationNotificationChannel.kt +++ b/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/notifications/JiraCreationNotificationChannel.kt @@ -40,6 +40,7 @@ class JiraCreationNotificationChannel( override fun publish( config: JiraCreationNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: JiraCreationNotificationChannelOutput) -> JiraCreationNotificationChannelOutput, ): NotificationResult { @@ -53,6 +54,7 @@ class JiraCreationNotificationChannel( val expandedLabels = config.labels.map { eventTemplatingService.renderEvent( event = event, + context = context, template = it, renderer = PlainEventRenderer.INSTANCE, ) @@ -81,6 +83,7 @@ class JiraCreationNotificationChannel( // Title val title = eventTemplatingService.renderEvent( event = event, + context = context, template = config.titleTemplate, renderer = PlainEventRenderer.INSTANCE ) @@ -92,6 +95,7 @@ class JiraCreationNotificationChannel( ?.let { eventTemplatingService.renderEvent( event = event, + context = context, template = it, renderer = PlainEventRenderer.INSTANCE ) @@ -103,6 +107,7 @@ class JiraCreationNotificationChannel( JiraCustomField(name, value.transform { text -> eventTemplatingService.renderEvent( event = event, + context = context, template = text, renderer = PlainEventRenderer.INSTANCE ) @@ -113,6 +118,7 @@ class JiraCreationNotificationChannel( // Body val body = eventTemplatingService.renderEvent( event = event, + context = context, template = template, renderer = jiraNotificationEventRenderer, ) diff --git a/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/servicedesk/JiraServiceDeskNotificationChannel.kt b/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/servicedesk/JiraServiceDeskNotificationChannel.kt index 16d5b90e3ce..8db4cd87125 100644 --- a/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/servicedesk/JiraServiceDeskNotificationChannel.kt +++ b/ontrack-extension-jira/src/main/java/net/nemerosa/ontrack/extension/jira/servicedesk/JiraServiceDeskNotificationChannel.kt @@ -8,6 +8,7 @@ import net.nemerosa.ontrack.extension.jira.notifications.JiraCustomField import net.nemerosa.ontrack.extension.jira.notifications.JiraNotificationEventRenderer import net.nemerosa.ontrack.extension.jira.tx.JIRASessionFactory import net.nemerosa.ontrack.extension.notifications.channels.AbstractNotificationChannel +import net.nemerosa.ontrack.extension.notifications.channels.NoTemplate import net.nemerosa.ontrack.extension.notifications.channels.NotificationResult import net.nemerosa.ontrack.json.transform import net.nemerosa.ontrack.model.annotations.APIDescription @@ -25,6 +26,7 @@ import org.springframework.stereotype.Component @APIDescription("This channel is used to create a Jira Service Desk ticket.") @Documentation(JiraServiceDeskNotificationChannelConfig::class) @Documentation(JiraServiceDeskNotificationChannelOutput::class, section = "output") +@NoTemplate class JiraServiceDeskNotificationChannel( private val jiraConfigurationService: JIRAConfigurationService, private val jiraSessionFactory: JIRASessionFactory, @@ -43,6 +45,7 @@ class JiraServiceDeskNotificationChannel( override fun publish( config: JiraServiceDeskNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: JiraServiceDeskNotificationChannelOutput) -> JiraServiceDeskNotificationChannelOutput ): NotificationResult { @@ -67,6 +70,7 @@ class JiraServiceDeskNotificationChannel( // Rendering the search term val searchTerm = eventTemplatingService.renderEvent( event = event, + context = context, template = config.searchTerm, renderer = PlainEventRenderer.INSTANCE, ) @@ -101,6 +105,7 @@ class JiraServiceDeskNotificationChannel( JiraCustomField(name, value.transform { text -> eventTemplatingService.renderEvent( event = event, + context = context, template = text, renderer = renderer, ) diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NoTemplate.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NoTemplate.kt new file mode 100644 index 00000000000..72719cf36de --- /dev/null +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NoTemplate.kt @@ -0,0 +1,10 @@ +package net.nemerosa.ontrack.extension.notifications.channels + +/** + * Used to annotate a notification channel for the documentation, indicating that + * it does not use the provided template. + */ +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +@MustBeDocumented +annotation class NoTemplate diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NotificationChannel.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NotificationChannel.kt index 4c9632b11d3..c2ccbe15191 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NotificationChannel.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/channels/NotificationChannel.kt @@ -19,6 +19,7 @@ interface NotificationChannel { * * @param config Configuration for the channel * @param event Event to send notification about + * @param context Notification template context * @param template Alternative template to the default event message * @param outputProgressCallback Gives the opportunity to the channel to register some progress on its output * @return Response by the channel @@ -26,6 +27,7 @@ interface NotificationChannel { fun publish( config: C, event: Event, + context: Map, template: String?, outputProgressCallback: (current: R) -> R, ): NotificationResult diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannel.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannel.kt index 128452925ae..37c856bb6e1 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannel.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannel.kt @@ -39,16 +39,18 @@ class InMemoryNotificationChannel( override fun publish( config: InMemoryNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: InMemoryNotificationChannelOutput) -> InMemoryNotificationChannelOutput ): NotificationResult { val text = eventTemplatingService.renderEvent( event, + context, template, PlainEventRenderer() ) messages.getOrPut(config.group) { mutableListOf() }.add(text) - return NotificationResult.ok(InMemoryNotificationChannelOutput(sent = true)) + return NotificationResult.ok(InMemoryNotificationChannelOutput(sent = true, data = config.data)) } override fun toSearchCriteria(text: String): JsonNode = InMemoryNotificationChannelConfig(text).asJson() diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelConfig.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelConfig.kt index f89f4a1ddf3..cdf271ee15e 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelConfig.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelConfig.kt @@ -7,4 +7,6 @@ data class InMemoryNotificationChannelConfig( @APILabel("Group") @APIDescription("Group of messages") val group: String, + @APIDescription("Optional data to pass along to the output") + val data: String? = null, ) \ No newline at end of file diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelOutput.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelOutput.kt index a2bede0e1a6..133020b83c1 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelOutput.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/inmemory/InMemoryNotificationChannelOutput.kt @@ -2,4 +2,5 @@ package net.nemerosa.ontrack.extension.notifications.inmemory data class InMemoryNotificationChannelOutput( val sent: Boolean, + val data: String?, ) \ No newline at end of file diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/mail/MailNotificationChannel.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/mail/MailNotificationChannel.kt index e74489d0c8a..3e89076702b 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/mail/MailNotificationChannel.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/mail/MailNotificationChannel.kt @@ -55,6 +55,7 @@ class MailNotificationChannel( override fun publish( config: MailNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: MailNotificationChannelOutput) -> MailNotificationChannelOutput ): NotificationResult { @@ -62,11 +63,13 @@ class MailNotificationChannel( val subject = eventTemplatingService.render( template = config.subject, event = event, + context = context, renderer = PlainEventRenderer.INSTANCE, // Using plain text for the subject ) // Formatting the message val message = eventTemplatingService.renderEvent( event = event, + context = context, template = template, renderer = htmlNotificationEventRenderer, ) diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/DefaultNotificationProcessingService.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/DefaultNotificationProcessingService.kt index 81103e60a84..9a457aecefe 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/DefaultNotificationProcessingService.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/DefaultNotificationProcessingService.kt @@ -27,20 +27,21 @@ class DefaultNotificationProcessingService( private val meterRegistry: MeterRegistry, ) : NotificationProcessingService { - override fun process(item: Notification) { + override fun process(item: Notification, context: Map): Any? { meterRegistry.incrementForProcessing(NotificationsMetrics.event_processing_started, item) val channel = notificationChannelRegistry.findChannel(item.channel) if (channel != null) { meterRegistry.incrementForProcessing(NotificationsMetrics.event_processing_channel_started, item) - process(channel, item) + return process(channel, item, context) } else { meterRegistry.incrementForProcessing(NotificationsMetrics.event_processing_channel_unknown, item) + return null } } - private fun process(channel: NotificationChannel, item: Notification) { + private fun process(channel: NotificationChannel, item: Notification, context: Map): R? { val validatedConfig = channel.validate(item.channelConfig) - if (validatedConfig.config != null) { + return if (validatedConfig.config != null) { // Current output progress var output: R? = null @@ -55,6 +56,7 @@ class DefaultNotificationProcessingService( val result = channel.publish( config = validatedConfig.config, event = item.event, + context = context, template = item.template, outputProgressCallback = outputProgressCallback, ) @@ -65,6 +67,7 @@ class DefaultNotificationProcessingService( event = item.event, result = result, ) + result.output } catch (any: Exception) { meterRegistry.incrementForProcessing(NotificationsMetrics.event_processing_channel_error, item) record( @@ -74,6 +77,7 @@ class DefaultNotificationProcessingService( error = any, output = output, // Using the current output, even for errors ) + output } } else { meterRegistry.incrementForProcessing(NotificationsMetrics.event_processing_channel_invalid, item) @@ -82,6 +86,7 @@ class DefaultNotificationProcessingService( invalidChannelConfig = item.channelConfig, event = item.event, ) + null } } diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/NotificationProcessingService.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/NotificationProcessingService.kt index 2806ead87d6..7878e4c8280 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/NotificationProcessingService.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/processing/NotificationProcessingService.kt @@ -4,6 +4,11 @@ import net.nemerosa.ontrack.extension.notifications.model.Notification interface NotificationProcessingService { - fun process(item: Notification) + /** + * @param item Notification to process + * @param context Extra context to pass for the templating + * @return Notification output + */ + fun process(item: Notification, context: Map,): Any? } \ No newline at end of file diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/AsyncNotificationQueueListener.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/AsyncNotificationQueueListener.kt index 527b356c285..112328177a5 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/AsyncNotificationQueueListener.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/AsyncNotificationQueueListener.kt @@ -67,7 +67,7 @@ class AsyncNotificationQueueListener( "channel" to notification.channel, "queue" to queue, ) - notificationProcessingService.process(notification) + notificationProcessingService.process(notification, emptyMap()) } } catch (any: Throwable) { applicationLogService.log( diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/SyncNotificationQueue.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/SyncNotificationQueue.kt index 0f2efc4288d..cc7e5cad0cd 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/SyncNotificationQueue.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/queue/SyncNotificationQueue.kt @@ -19,9 +19,10 @@ class SyncNotificationQueue( override fun publish(item: Notification): Boolean { notificationProcessingService.process( - notificationQueueItemConverter.convertFromQueue( + item = notificationQueueItemConverter.convertFromQueue( notificationQueueItemConverter.convertForQueue(item) - ) + ), + context = emptyMap() ) // OK return true diff --git a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/webhooks/WebhookNotificationChannel.kt b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/webhooks/WebhookNotificationChannel.kt index ca1afccddbf..01d733b4e20 100644 --- a/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/webhooks/WebhookNotificationChannel.kt +++ b/ontrack-extension-notifications/src/main/java/net/nemerosa/ontrack/extension/notifications/webhooks/WebhookNotificationChannel.kt @@ -2,6 +2,7 @@ package net.nemerosa.ontrack.extension.notifications.webhooks import com.fasterxml.jackson.databind.JsonNode import net.nemerosa.ontrack.extension.notifications.channels.AbstractNotificationChannel +import net.nemerosa.ontrack.extension.notifications.channels.NoTemplate import net.nemerosa.ontrack.extension.notifications.channels.NotificationResult import net.nemerosa.ontrack.json.asJson import net.nemerosa.ontrack.model.annotations.APIDescription @@ -17,6 +18,7 @@ import org.springframework.stereotype.Component @APIDescription("Calling an external webhook") @Documentation(WebhookNotificationChannelConfig::class) @Documentation(WebhookNotificationChannelOutput::class, section = "output") +@NoTemplate class WebhookNotificationChannel( private val webhookAdminService: WebhookAdminService, private val webhookExecutionService: WebhookExecutionService, @@ -29,6 +31,7 @@ class WebhookNotificationChannel( override fun publish( config: WebhookNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: WebhookNotificationChannelOutput) -> WebhookNotificationChannelOutput ): NotificationResult { diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannel.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannel.kt index 83f60431941..412ace18720 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannel.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannel.kt @@ -22,20 +22,27 @@ class MockNotificationChannel( */ val messages = mutableMapOf>() + /** + * Utility method to get the list of messages for a given target + */ + fun targetMessages(target: String) = messages[target]?.toList() ?: emptyList() + override fun publish( config: MockNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: MockNotificationChannelOutput) -> MockNotificationChannelOutput ): NotificationResult { val text = eventTemplatingService.renderEvent( event, + context, template, PlainEventRenderer.INSTANCE, ) messages.getOrPut(config.target) { mutableListOf() }.add(text) return NotificationResult.ok( - output = MockNotificationChannelOutput(text = text) + output = MockNotificationChannelOutput(text = text, data = config.data) ) } diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelConfig.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelConfig.kt index 10f44fbac20..c2bc3d7fc45 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelConfig.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelConfig.kt @@ -4,7 +4,9 @@ package net.nemerosa.ontrack.extension.notifications.mock * Configuration for the [MockNotificationChannel] channel. * * @property target Pseudo-address or channel to target + * @property data Optional data to pass along to the output */ data class MockNotificationChannelConfig( val target: String, + val data: String? = null, ) diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelOutput.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelOutput.kt index 3c142084883..c3b81db3cd9 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelOutput.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/MockNotificationChannelOutput.kt @@ -2,4 +2,5 @@ package net.nemerosa.ontrack.extension.notifications.mock data class MockNotificationChannelOutput( val text: String, + val data: String?, ) diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/OtherMockNotificationChannel.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/OtherMockNotificationChannel.kt index 89219ed644e..f570ad3a810 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/OtherMockNotificationChannel.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/mock/OtherMockNotificationChannel.kt @@ -25,17 +25,19 @@ class OtherMockNotificationChannel( override fun publish( config: MockNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: MockNotificationChannelOutput) -> MockNotificationChannelOutput ): NotificationResult { val text = eventTemplatingService.renderEvent( event, + context, template, PlainEventRenderer.INSTANCE, ) messages.getOrPut(config.target) { mutableListOf() }.add(text) return NotificationResult.ok( - output = MockNotificationChannelOutput(text = text) + output = MockNotificationChannelOutput(text = text, data = config.data) ) } diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/recording/GQLRootQueryNotificationRecordsIT.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/recording/GQLRootQueryNotificationRecordsIT.kt index 6a2d563454f..91df8a9996e 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/recording/GQLRootQueryNotificationRecordsIT.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/recording/GQLRootQueryNotificationRecordsIT.kt @@ -37,7 +37,7 @@ internal class GQLRootQueryNotificationRecordsIT : AbstractNotificationTestSuppo channelConfig = MockNotificationChannelConfig("#target").asJson(), event = event.asJson(), result = NotificationResult.ok( - output = MockNotificationChannelOutput(text = "The actual text") + output = MockNotificationChannelOutput(text = "The actual text", data = null) ).toNotificationRecordResult(), ) ) @@ -83,7 +83,7 @@ internal class GQLRootQueryNotificationRecordsIT : AbstractNotificationTestSuppo channelConfig = MockNotificationChannelConfig("#target").asJson(), event = event.asJson(), result = NotificationResult.ok( - output = MockNotificationChannelOutput(text = "The actual text") + output = MockNotificationChannelOutput(text = "The actual text", data = null) ).toNotificationRecordResult(), ) ) diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/HtmlNotificationEventRendererIT.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/HtmlNotificationEventRendererIT.kt index f0d38953694..be8c5a7a329 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/HtmlNotificationEventRendererIT.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/HtmlNotificationEventRendererIT.kt @@ -39,6 +39,7 @@ class HtmlNotificationEventRendererIT : AbstractDSLTestSupport() { Build ${'$'}{build.release} for ${'$'}{branch} at ${'$'}{project} has been promoted to ${'$'}{promotionLevel}. """.trimIndent(), + context = emptyMap(), renderer = htmlNotificationEventRenderer, ) diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/PlainNotificationEventRendererIT.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/PlainNotificationEventRendererIT.kt index 8aba0870a33..0baa69ef21d 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/PlainNotificationEventRendererIT.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/rendering/PlainNotificationEventRendererIT.kt @@ -32,6 +32,7 @@ class PlainNotificationEventRendererIT : AbstractDSLTestSupport() { template = """ Project ${'$'}{projectx} has been created. """.trimIndent(), + context = emptyMap(), renderer = plainEventRenderer, ) @@ -63,6 +64,7 @@ class PlainNotificationEventRendererIT : AbstractDSLTestSupport() { Build ${'$'}{build.release} for ${'$'}{branch} at ${'$'}{project} has been promoted to ${'$'}{promotionLevel}. """.trimIndent(), + context = emptyMap(), renderer = plainEventRenderer, ) diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/EventSubscriptionServiceIT.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/EventSubscriptionServiceIT.kt index 3b2aa77874c..502f7d89c72 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/EventSubscriptionServiceIT.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/EventSubscriptionServiceIT.kt @@ -118,7 +118,10 @@ internal class EventSubscriptionServiceIT : AbstractNotificationTestSupport() { subscription.channel ) assertEquals( - mapOf("target" to targetBranch).asJson(), + mapOf( + "target" to targetBranch, + "data" to null, + ).asJson(), subscription.channelConfig ) assertEquals(setOf("new_promotion_run"), subscription.events) @@ -131,7 +134,10 @@ internal class EventSubscriptionServiceIT : AbstractNotificationTestSupport() { subscription.channel ) assertEquals( - mapOf("target" to targetProject).asJson(), + mapOf( + "target" to targetProject, + "data" to null, + ).asJson(), subscription.channelConfig ) assertEquals(setOf("new_promotion_run"), subscription.events) diff --git a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/GQLRootQueryEventSubscriptionsIT.kt b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/GQLRootQueryEventSubscriptionsIT.kt index 85883929013..b0674da66af 100644 --- a/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/GQLRootQueryEventSubscriptionsIT.kt +++ b/ontrack-extension-notifications/src/test/java/net/nemerosa/ontrack/extension/notifications/subscriptions/GQLRootQueryEventSubscriptionsIT.kt @@ -123,7 +123,8 @@ internal class GQLRootQueryEventSubscriptionsIT : AbstractNotificationTestSuppor mapOf( "channel" to "mock", "channelConfig" to mapOf( - "target" to "#one" + "target" to "#one", + "data" to null, ), "events" to listOf( "new_promotion_run" @@ -269,7 +270,8 @@ internal class GQLRootQueryEventSubscriptionsIT : AbstractNotificationTestSuppor mapOf( "channel" to "mock", "channelConfig" to mapOf( - "target" to "#one" + "target" to "#one", + "data" to null, ), "events" to listOf( "new_promotion_run" diff --git a/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/dispatching/QueueDispatcher.kt b/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/dispatching/QueueDispatcher.kt index 1b4e1f48388..78fa1eefec7 100644 --- a/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/dispatching/QueueDispatcher.kt +++ b/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/dispatching/QueueDispatcher.kt @@ -11,6 +11,13 @@ import net.nemerosa.ontrack.extension.queue.source.QueueSource */ interface QueueDispatcher { + /** + * Puts a message (payload) onto a queue. + * + * @param queueProcessor Processor used for the processing of messages + * @param payload Message to post + * @param source Information about the source of the message + */ fun dispatch( queueProcessor: QueueProcessor, payload: T, diff --git a/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/source/PostQueueSourceExtension.kt b/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/source/PostQueueSourceExtension.kt index 2772ec57078..410b8c5e109 100644 --- a/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/source/PostQueueSourceExtension.kt +++ b/ontrack-extension-queue/src/main/java/net/nemerosa/ontrack/extension/queue/source/PostQueueSourceExtension.kt @@ -4,6 +4,9 @@ import net.nemerosa.ontrack.extension.queue.QueueExtensionFeature import net.nemerosa.ontrack.extension.support.AbstractExtension import org.springframework.stereotype.Component +/** + * Sources of messages which are posted using the API. + */ @Component class PostQueueSourceExtension( extensionFeature: QueueExtensionFeature, diff --git a/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/PromotionRunChangeLogTemplatingSourceIT.kt b/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/PromotionRunChangeLogTemplatingSourceIT.kt index 58a28f03794..ca51317b2c8 100644 --- a/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/PromotionRunChangeLogTemplatingSourceIT.kt +++ b/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/PromotionRunChangeLogTemplatingSourceIT.kt @@ -151,6 +151,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -196,6 +197,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -241,6 +243,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -288,6 +291,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -333,6 +337,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -382,6 +387,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -472,6 +478,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -526,6 +533,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -587,6 +595,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE ) @@ -666,6 +675,7 @@ class PromotionRunChangeLogTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = template, event = event, + context = emptyMap(), renderer = renderer ) diff --git a/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/SCMBranchTemplatingSourceIT.kt b/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/SCMBranchTemplatingSourceIT.kt index a1c368efd9b..a35a306f9c7 100644 --- a/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/SCMBranchTemplatingSourceIT.kt +++ b/ontrack-extension-scm/src/test/java/net/nemerosa/ontrack/extension/scm/service/SCMBranchTemplatingSourceIT.kt @@ -35,6 +35,7 @@ class SCMBranchTemplatingSourceIT : AbstractDSLTestSupport() { val text = eventTemplatingService.render( template = "Branch ${'$'}{branch.scmBranch|urlencode} has been promoted to ${'$'}{promotionLevel}", event = event, + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE, ) diff --git a/ontrack-extension-slack/src/main/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannel.kt b/ontrack-extension-slack/src/main/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannel.kt index cf1705c6558..3f1fcfef20a 100644 --- a/ontrack-extension-slack/src/main/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannel.kt +++ b/ontrack-extension-slack/src/main/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannel.kt @@ -34,11 +34,12 @@ class SlackNotificationChannel( override fun publish( config: SlackNotificationChannelConfig, event: Event, + context: Map, template: String?, outputProgressCallback: (current: SlackNotificationChannelOutput) -> SlackNotificationChannelOutput ): NotificationResult { // Formatting the message - val message = format(event, template) + val message = format(event, context, template) // Sending the message val sent = slackService.sendNotification(config.channel, message, config.type) // Result @@ -54,10 +55,11 @@ class SlackNotificationChannel( } } - private fun format(event: Event, template: String?): String = eventTemplatingService.renderEvent( - event, - template, - slackNotificationEventRenderer, + private fun format(event: Event, context: Map, template: String?): String = eventTemplatingService.renderEvent( + event = event, + context = context, + template = template, + renderer = slackNotificationEventRenderer, ) override fun toSearchCriteria(text: String): JsonNode = diff --git a/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannelTest.kt b/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannelTest.kt index f888889201e..6d32e6aff95 100644 --- a/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannelTest.kt +++ b/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationChannelTest.kt @@ -48,6 +48,7 @@ class SlackNotificationChannelTest { eventTemplatingService.renderEvent( event = event, template = null, + context = emptyMap(), renderer = slackNotificationEventRenderer, ) } returns event.eventType.template @@ -69,7 +70,13 @@ class SlackNotificationChannelTest { every { slackService.sendNotification(any(), any(), any()) } returns true val config = SlackNotificationChannelConfig(channel = "#test", type = SlackNotificationType.SUCCESS) - val result = channel.publish(config, event, template = null, outputProgressCallback = { it }) + val result = channel.publish( + config, + event, + context = emptyMap(), + template = null, + outputProgressCallback = { it } + ) verify { slackService.sendNotification( "#test", @@ -88,7 +95,13 @@ class SlackNotificationChannelTest { ) every { slackService.sendNotification(any(), any(), any()) } returns false // <== returning an error val config = SlackNotificationChannelConfig(channel = "#test") - val result = channel.publish(config, event, template = null, outputProgressCallback = { it }) + val result = channel.publish( + config, + event, + context = emptyMap(), + template = null, + outputProgressCallback = { it } + ) assertEquals(NotificationResultType.ERROR, result.type) assertEquals("Slack message could not be sent. Check the operational logs.", result.message) } diff --git a/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationEventRendererIT.kt b/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationEventRendererIT.kt index a09d8c54b61..a628e34f131 100644 --- a/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationEventRendererIT.kt +++ b/ontrack-extension-slack/src/test/java/net/nemerosa/ontrack/extension/slack/notifications/SlackNotificationEventRendererIT.kt @@ -38,6 +38,7 @@ class SlackNotificationEventRendererIT : AbstractDSLTestSupport() { Build ${'$'}{build.release} for ${'$'}{branch} at ${'$'}{project} has been promoted to ${'$'}{promotionLevel}. """.trimIndent(), + context = emptyMap(), renderer = slackNotificationEventRenderer, ) diff --git a/ontrack-extension-stash/src/test/java/net/nemerosa/ontrack/extension/stash/scm/BitbucketServerSCMExtensionIT.kt b/ontrack-extension-stash/src/test/java/net/nemerosa/ontrack/extension/stash/scm/BitbucketServerSCMExtensionIT.kt index efe9768472d..91ff1cde56e 100644 --- a/ontrack-extension-stash/src/test/java/net/nemerosa/ontrack/extension/stash/scm/BitbucketServerSCMExtensionIT.kt +++ b/ontrack-extension-stash/src/test/java/net/nemerosa/ontrack/extension/stash/scm/BitbucketServerSCMExtensionIT.kt @@ -43,6 +43,7 @@ class BitbucketServerSCMExtensionIT : AbstractDSLTestSupport() { val path = eventTemplatingService.renderEvent( event = event, template = "/my/path/{ScmBranch|urlencode}", + context = emptyMap(), renderer = PlainEventRenderer.INSTANCE, ) // Check @@ -76,6 +77,7 @@ class BitbucketServerSCMExtensionIT : AbstractDSLTestSupport() { // Rendering val path = eventTemplatingService.renderEvent( event = event, + context = emptyMap(), template = "/my/path/${'$'}{branch.scmBranch|urlencode}", renderer = PlainEventRenderer.INSTANCE, ) diff --git a/ontrack-extension-workflows/build.gradle.kts b/ontrack-extension-workflows/build.gradle.kts new file mode 100644 index 00000000000..a0889cefa06 --- /dev/null +++ b/ontrack-extension-workflows/build.gradle.kts @@ -0,0 +1,52 @@ +import net.nemerosa.ontrack.gradle.extension.OntrackExtensionPlugin + +plugins { + `java-library` +} + +apply() + +dependencies { + api(project(":ontrack-extension-support")) + api(project(":ontrack-ui-support")) + + implementation(project(":ontrack-extension-queue")) + implementation(project(":ontrack-extension-notifications")) + implementation(project(":ontrack-ui-graphql")) + implementation("org.springframework:spring-context") + implementation("org.slf4j:slf4j-api") + implementation("io.micrometer:micrometer-core") + implementation("jakarta.annotation:jakarta.annotation-api") + implementation(project(":ontrack-extension-casc")) + + testImplementation(project(path = ":ontrack-model", configuration = "tests")) + testImplementation(project(path = ":ontrack-ui-support", configuration = "tests")) + testImplementation(project(path = ":ontrack-ui-graphql", configuration = "tests")) + testImplementation(project(path = ":ontrack-extension-api", configuration = "tests")) + testImplementation(project(path = ":ontrack-extension-casc", configuration = "tests")) + testImplementation(project(path = ":ontrack-extension-notifications", configuration = "tests")) + testImplementation(project(":ontrack-it-utils")) + + testRuntimeOnly(project(":ontrack-service")) + testRuntimeOnly(project(":ontrack-repository-impl")) +} + +val testJar by tasks.registering(Jar::class) { + archiveClassifier.set("tests") + from(sourceSets["test"].output) +} + +configure { + publications { + maybeCreate("mavenCustom").artifact(tasks["testJar"]) + } +} + +tasks["assemble"].dependsOn("testJar") + +val tests by configurations.creating + +artifacts { + add("tests", testJar) +} + diff --git a/ontrack-extension-workflows/docs/workflows.puml b/ontrack-extension-workflows/docs/workflows.puml new file mode 100644 index 00000000000..718070884fa --- /dev/null +++ b/ontrack-extension-workflows/docs/workflows.puml @@ -0,0 +1,63 @@ +@startuml + +== Definition == + +actor User +participant Workflow + +create Workflow +User -> Workflow: defines and stores + +== Starting == + +control Event +participant WorkflowChannel + +Event -> WorkflowChannel: publish +WorkflowChannel -> Workflow: reads + +participant WorkflowEngine +database WorkflowInstance + +WorkflowChannel -> WorkflowEngine: start(workflow) +create WorkflowInstance +WorkflowEngine -> WorkflowInstance: stores(workflow) + +database WorkflowQueue + +WorkflowEngine -\ WorkflowQueue: push(start nodes) + +== Information == + +User -> WorkflowEngine: gets information +WorkflowEngine -> WorkflowInstance: gets info +WorkflowInstance --> WorkflowEngine: info +WorkflowEngine --> User: info + +== Execution == + +WorkflowQueue -\ WorkflowEngine: message +WorkflowEngine -> WorkflowInstance: gets info +WorkflowInstance --> WorkflowEngine: node info + +WorkflowEngine -> WorkflowChannel: runs node +note left + The workflow channel is accessed through + a ""WorkflowNodeExecutor"" interface. + + It must be accessible statically through + an ID and the node configuration. +end note +WorkflowChannel --> WorkflowEngine: output +WorkflowEngine -> WorkflowInstance: stores outcome +WorkflowEngine -> WorkflowInstance: gets next nodes +WorkflowInstance --> WorkflowEngine: next nodes +note right + The workflow engine, based on the outcomes + of all the nodes of the workflow, decides + which nodes can be executed next based on + the nodes conditions & parents. +end note +WorkflowEngine -> WorkflowQueue: push(next nodes) + +@enduml \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/WorkflowsExtensionFeature.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/WorkflowsExtensionFeature.kt new file mode 100644 index 00000000000..cc7eaac0277 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/WorkflowsExtensionFeature.kt @@ -0,0 +1,13 @@ +package net.nemerosa.ontrack.extension.workflows + +import net.nemerosa.ontrack.extension.support.AbstractExtensionFeature +import net.nemerosa.ontrack.model.extension.ExtensionFeatureOptions +import org.springframework.stereotype.Component + +@Component +class WorkflowsExtensionFeature : AbstractExtensionFeature( + "workflows", + "Workflows", + "Definition of workflows", + ExtensionFeatureOptions.DEFAULT +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowAudit.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowAudit.kt new file mode 100644 index 00000000000..cbc5fb19774 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowAudit.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.acl + +import net.nemerosa.ontrack.model.security.GlobalFunction + +/** + * Right to see and manage the audit of the workflows (workflow instances). + */ +interface WorkflowAudit: GlobalFunction diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowRegistration.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowRegistration.kt new file mode 100644 index 00000000000..4f151039da4 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowRegistration.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.acl + +import net.nemerosa.ontrack.model.security.GlobalFunction + +/** + * Right to manage global workflows + */ +interface WorkflowRegistration: GlobalFunction diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowRoleContributor.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowRoleContributor.kt new file mode 100644 index 00000000000..bb2437fc10a --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/acl/WorkflowRoleContributor.kt @@ -0,0 +1,19 @@ +package net.nemerosa.ontrack.extension.workflows.acl + +import net.nemerosa.ontrack.model.security.GlobalFunction +import net.nemerosa.ontrack.model.security.RoleContributor +import net.nemerosa.ontrack.model.security.Roles +import org.springframework.stereotype.Component + +@Component +class WorkflowRoleContributor : RoleContributor { + + override fun getGlobalFunctionContributionsForGlobalRoles(): Map>> = + mapOf( + Roles.GLOBAL_ADMINISTRATOR to listOf( + WorkflowRegistration::class.java, + WorkflowAudit::class.java, + ), + ) + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/Workflow.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/Workflow.kt new file mode 100644 index 00000000000..3aa06790d04 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/Workflow.kt @@ -0,0 +1,43 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowNodeNotFoundException +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.DocumentationList +import net.nemerosa.ontrack.model.docs.SelfDocumented + +/** + * Definition of a workflow by another extension. + * + * @property name Display name for the workflow + * @property nodes List of nodes in the workflow + */ +@SelfDocumented +data class Workflow( + @APIDescription("Display name for the workflow") + val name: String, + @APIDescription("List of nodes in the workflow") + @DocumentationList + val nodes: List, +) { + /** + * Given the ID of a parent, returns the next nodes in the workflow. + */ + fun getNextNodes(parentId: String?): List = + if (parentId.isNullOrBlank()) { + nodes.filter { it.parents.isEmpty() }.map { it.id } + } else { + nodes.filter { it.parents.any { ref -> ref.id == parentId } }.map { it.id } + } + + /** + * Rename the template + */ + fun rename(code: (name: String) -> String) = Workflow( + name = code(name), + nodes = nodes, + ) + + fun getNode(nodeId: String) = nodes.firstOrNull { it.id == nodeId } + ?: throw WorkflowNodeNotFoundException(nodeId) +} diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowNode.kt new file mode 100644 index 00000000000..36e03acc909 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowNode.kt @@ -0,0 +1,27 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.DocumentationList +import net.nemerosa.ontrack.model.docs.SelfDocumented + +/** + * Definition of a node in a workflow. + * + * @property id Unique ID of the node in its workflow. + * @property executorId ID of the executor to use + * @property data Raw data associated with the node, to be used by the node executor. + * @property parents List of the IDs of the parents for this node + */ +@SelfDocumented +data class WorkflowNode( + @APIDescription("Unique ID of the node in its workflow.") + val id: String, + @APIDescription("ID of the executor to use") + val executorId: String, + @APIDescription("Raw data associated with the node, to be used by the node executor.") + val data: JsonNode, + @APIDescription("List of the IDs of the parents for this node") + @DocumentationList + val parents: List = emptyList(), +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowParentNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowParentNode.kt new file mode 100644 index 00000000000..321a9608261 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowParentNode.kt @@ -0,0 +1,13 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.SelfDocumented + +/** + * Reference to a parent node + */ +@SelfDocumented +data class WorkflowParentNode( + @APIDescription("ID of the parent node") + val id: String, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowValidation.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowValidation.kt new file mode 100644 index 00000000000..032c8b3b9ea --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowValidation.kt @@ -0,0 +1,72 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +/** + * Result for the validation of a workflow + */ +data class WorkflowValidation( + val errors: List, +) { + fun throwErrorIfAny() { + if (errors.isNotEmpty()) { + throw WorkflowValidationException( + "Validation of the workflow returned the following errors:\n${errors.joinToString("\n") { "* $it" }}" + ) + } + } + + val error: Boolean = errors.isNotEmpty() + + companion object { + + fun validateWorkflow(workflow: Workflow): WorkflowValidation { + // Name is required + if (workflow.name.isBlank()) { + return WorkflowValidation.error("Workflow name is required.") + } + // One node required + if (workflow.nodes.isEmpty()) { + return WorkflowValidation.error("At least one node is required.") + } + // Cycle detection + if (isCyclic(workflow.nodes)) { + return WorkflowValidation.error("The workflow contains at least one cycle.") + } + // OK + return WorkflowValidation.ok() + } + + private fun isCyclic(nodes: List): Boolean { + val visited = mutableSetOf() + val recStack = mutableSetOf() + + fun dfs(nodeId: String): Boolean { + if (recStack.contains(nodeId)) return true + if (visited.contains(nodeId)) return false + + visited.add(nodeId) + recStack.add(nodeId) + + nodes.find { it.id == nodeId }?.parents?.forEach { parent -> + if (dfs(parent.id)) return true + } + + recStack.remove(nodeId) + return false + } + + return nodes.any { dfs(it.id) } + } + + fun error(message: String) = WorkflowValidation( + errors = listOf(message), + ) + + fun error(ex: Exception) = error( + ex.message ?: ex.javaClass.simpleName + ) + + fun ok() = WorkflowValidation( + errors = emptyList(), + ) + } +} diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowValidationException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowValidationException.kt new file mode 100644 index 00000000000..15ae9455725 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowValidationException.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +import net.nemerosa.ontrack.model.exceptions.InputException + +class WorkflowValidationException( + message: String, +) : InputException(message) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/DatabaseWorkflowInstanceStore.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/DatabaseWorkflowInstanceStore.kt new file mode 100644 index 00000000000..ebcba9bef54 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/DatabaseWorkflowInstanceStore.kt @@ -0,0 +1,65 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.common.Time +import net.nemerosa.ontrack.extension.workflows.mgt.WorkflowSettings +import net.nemerosa.ontrack.model.pagination.PaginatedList +import net.nemerosa.ontrack.model.settings.CachedSettingsService +import net.nemerosa.ontrack.model.support.StorageService +import net.nemerosa.ontrack.model.tx.TransactionHelper +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Component +import org.springframework.transaction.annotation.Transactional +import java.time.Duration +import java.time.temporal.ChronoUnit + +@Component +@ConditionalOnProperty( + prefix = "net.nemerosa.ontrack.extension.workflows", + name = ["store"], + havingValue = "database", + matchIfMissing = true, +) +@Transactional +class DatabaseWorkflowInstanceStore( + private val storageService: StorageService, + private val cachedSettingsService: CachedSettingsService, + private val transactionHelper: TransactionHelper, +) : WorkflowInstanceStore { + + companion object { + private val STORE = WorkflowInstance::class.java.name + } + + override fun store(instance: WorkflowInstance): WorkflowInstance = + transactionHelper.inNewTransaction { + storageService.store(STORE, instance.id, instance) + instance + } + + override fun cleanup() { + val settings = cachedSettingsService.getCachedSettings(WorkflowSettings::class.java) + val time = Time.now - Duration.of(settings.retentionDuration, ChronoUnit.MILLIS) + storageService.deleteWithFilter( + store = STORE, + query = "data->>'timestamp' < :timestamp", + queryVariables = mapOf("timestamp" to Time.store(time)) + ) + } + + override fun findById(id: String): WorkflowInstance? = + storageService.find(STORE, id, WorkflowInstance::class) + + override fun findByFilter(workflowInstanceFilter: WorkflowInstanceFilter): PaginatedList { + return storageService.paginatedFilter( + store = STORE, + type = WorkflowInstance::class, + offset = workflowInstanceFilter.offset, + size = workflowInstanceFilter.size, + orderQuery = "ORDER BY data::jsonb->>'id' DESC", + ) + } + + override fun clearAll() { + storageService.clear(STORE) + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/InMemoryWorkflowInstanceStore.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/InMemoryWorkflowInstanceStore.kt new file mode 100644 index 00000000000..7029bfca451 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/InMemoryWorkflowInstanceStore.kt @@ -0,0 +1,41 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.model.pagination.PaginatedList +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Component + +@Component +@ConditionalOnProperty( + prefix = "net.nemerosa.ontrack.extension.workflows", + name = ["store"], + havingValue = "memory", + matchIfMissing = false, +) +class InMemoryWorkflowInstanceStore : WorkflowInstanceStore { + + private val instances = mutableMapOf() + + override fun store(instance: WorkflowInstance): WorkflowInstance { + instances[instance.id] = instance + return instance + } + + override fun findById(id: String): WorkflowInstance? = instances[id] + + override fun findByFilter(workflowInstanceFilter: WorkflowInstanceFilter): PaginatedList { + val values = instances.values.sortedByDescending { it.startTime } + return PaginatedList.create( + items = values, + offset = workflowInstanceFilter.offset, + pageSize = workflowInstanceFilter.size, + ) + } + + override fun cleanup() { + instances.clear() + } + + override fun clearAll() { + instances.clear() + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContext.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContext.kt new file mode 100644 index 00000000000..7b164151fb6 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContext.kt @@ -0,0 +1,33 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.json.parse + +data class WorkflowContext( + val data: List, +) { + + constructor(key: String, value: JsonNode) : this( + listOf( + WorkflowContextData(key, value) + ) + ) + + private val index = data.associate { it.key to it.value } + + inline fun parse(key: String): T { + val value = getValue(key) + return value.parse() + } + + fun getValue(key: String): JsonNode { + return findValue(key) ?: throw WorkflowContextKeyNotFoundException(key) + } + + private fun findValue(key: String): JsonNode? = index[key] + + companion object { + fun noContext() = WorkflowContext(emptyList()) + } + +} diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextData.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextData.kt new file mode 100644 index 00000000000..7e65079a929 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextData.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.JsonNode + +data class WorkflowContextData( + val key: String, + val value: JsonNode, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextKeyNotFoundException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextKeyNotFoundException.kt new file mode 100644 index 00000000000..1a65ae3321c --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextKeyNotFoundException.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.common.BaseException + +class WorkflowContextKeyNotFoundException(key: String) : BaseException( + "Workflow context key not found: $key" +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngine.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngine.kt new file mode 100644 index 00000000000..ac4e52e379b --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngine.kt @@ -0,0 +1,31 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutor + +/** + * Engine used to orchestrate the execution of workflows. + */ +interface WorkflowEngine { + + /** + * Starts the execution of a workflow. + * + * @param workflow Workflow to run + * @param context Execution context + * @return Initial state of the workflow instance + */ + fun startWorkflow(workflow: Workflow, context: WorkflowContext): WorkflowInstance + + /** + * Given the ID of a [WorkflowInstance], returns this instance or null if not found. + */ + fun findWorkflowInstance(id: String): WorkflowInstance? + + /** + * Processing one node in a workflow + */ + fun processNode(workflowInstanceId: String, workflowNodeId: String) + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineExtensions.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineExtensions.kt new file mode 100644 index 00000000000..349ec268f0c --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineExtensions.kt @@ -0,0 +1,5 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +fun WorkflowEngine.getWorkflowInstance(id: String): WorkflowInstance = + findWorkflowInstance(id) + ?: throw WorkflowInstanceNotFoundException(id) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineImpl.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineImpl.kt new file mode 100644 index 00000000000..183058acbf3 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineImpl.kt @@ -0,0 +1,122 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeoutOrNull +import net.nemerosa.ontrack.extension.queue.dispatching.QueueDispatcher +import net.nemerosa.ontrack.extension.queue.source.createQueueSource +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidation +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutorService +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import java.time.Duration + +@Service +@Transactional +class WorkflowEngineImpl( + private val workflowInstanceStore: WorkflowInstanceStore, + private val queueDispatcher: QueueDispatcher, + private val workflowQueueProcessor: WorkflowQueueProcessor, + private val workflowNodeExecutorService: WorkflowNodeExecutorService, + private val workflowQueueSourceExtension: WorkflowQueueSourceExtension, +) : WorkflowEngine { + + override fun startWorkflow( + workflow: Workflow, + context: WorkflowContext, + ): WorkflowInstance { + // Checks the workflow consistency (cycles, etc.) - use a public method, usable by extensions + WorkflowValidation.validateWorkflow(workflow).throwErrorIfAny() + // Creating the instance + val instance = createInstance(workflow, context) + // Storing the instance + workflowInstanceStore.store(instance) + // Getting the starting nodes + val nodes = instance.workflow.getNextNodes(null) + // Scheduling the nodes + for (nodeId in nodes) { + queueNode(instance, nodeId) + } + // Returning the instance + return instance + } + + private fun queueNode( + instance: WorkflowInstance, + nodeId: String + ) { + val node = instance.workflow.getNode(nodeId) + queueDispatcher.dispatch( + queueProcessor = workflowQueueProcessor, + payload = WorkflowQueuePayload( + workflowInstanceId = instance.id, + workflowNodeId = node.id, + workflowNodeExecutorId = node.executorId, + ), + source = workflowQueueSourceExtension.createQueueSource( + WorkflowQueueSourceData( + workflowInstanceId = instance.id, + workflowNodeId = node.id, + workflowNodeExecutorId = node.executorId, + ) + ) + ) + } + + override fun processNode(workflowInstanceId: String, workflowNodeId: String) { + // Getting the instance & the node + var instance = getWorkflowInstance(workflowInstanceId) + val node = instance.workflow.getNode(workflowNodeId) + try { + // Starting the node + instance = workflowInstanceStore.store(instance.startNode(node.id)) + // Getting the node executor + val executor = workflowNodeExecutorService.getExecutor(node.executorId) + // Timeout (hard-coded for now, can be set at node level) + val timeout = Duration.ofMinutes(5) + // Running the executor + val output = runBlocking { + withTimeoutOrNull(timeout.toMillis()) { + executor.execute(instance, node.id) + } + } + // Timeout? + if (output == null) { + throw WorkflowExecutionTimeoutException(timeout) + } + // Stores the output back into the instance and progresses the node's status + instance = workflowInstanceStore.store(instance.successNode(node.id, output)) + // Getting the next nodes + val nextNodes = instance.workflow.getNextNodes(node.id) + for (nextNode in nextNodes) { + // For each next node, checks if it can be scheduled or not + if (canRunNode(instance, nextNode)) { + // Schedule the node + queueNode(instance, nextNode) + } + } + } catch (any: Throwable) { + // Stores the node error status + workflowInstanceStore.store(instance.errorNode(node.id, any)) + } + } + + private fun canRunNode(instance: WorkflowInstance, nodeId: String): Boolean { + // Getting the instance node state + val instanceNode = instance.getNode(nodeId) + // Getting the workflow node + val workflowNode = instance.workflow.getNode(nodeId) + // Running all the checks + // 1. node must be idle + return instanceNode.status == WorkflowInstanceNodeStatus.IDLE && + // 2. all its parents must be in SUCCESS state + workflowNode.parents.all { parent -> + val parentNode = instance.getNode(parent.id) + parentNode.status == WorkflowInstanceNodeStatus.SUCCESS + } + } + + override fun findWorkflowInstance(id: String): WorkflowInstance? = + workflowInstanceStore.findById(id) + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowExecutionTimeoutException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowExecutionTimeoutException.kt new file mode 100644 index 00000000000..0d5aca79de0 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowExecutionTimeoutException.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.common.BaseException +import java.time.Duration + +class WorkflowExecutionTimeoutException(timeout: Duration) : BaseException( + "Workflow node execution timed out after $timeout." +) \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstance.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstance.kt new file mode 100644 index 00000000000..1666387fdd4 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstance.kt @@ -0,0 +1,113 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.common.Time +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import java.time.Duration +import java.time.LocalDateTime + +/** + * Information about the execution of a workflow. + * + * @property id Unique ID for this workflow instance. + * @property timestamp Last time the instance was updated. + * @property workflow Associated workflow + * @property context Mutable index of context objects used by the workflow + * @property nodesExecutions Information about the node executions + * @property status Status of the execution of this workflow + */ +data class WorkflowInstance( + val id: String, + val timestamp: LocalDateTime, + val workflow: Workflow, + val context: WorkflowContext, + val nodesExecutions: List, +) { + + @get:JsonIgnore + val startTime: LocalDateTime? by lazy { + nodesExecutions.mapNotNull { it.startTime }.minOrNull() + } + + @get:JsonIgnore + val endTime: LocalDateTime? by lazy { + nodesExecutions.mapNotNull { it.endTime }.maxOrNull() + } + + @get:JsonIgnore + val durationMs: Long by lazy { + if (startTime != null && endTime != null) { + Duration.between(startTime, endTime).toMillis() + } else { + 0 + } + } + + @get:JsonIgnore + val status: WorkflowInstanceStatus + get() { + val nodes = nodesExecutions.map { it.status } + return if (nodes.any { it == WorkflowInstanceNodeStatus.ERROR }) { + WorkflowInstanceStatus.ERROR + } else if (nodes.all { it == WorkflowInstanceNodeStatus.SUCCESS }) { + WorkflowInstanceStatus.SUCCESS + } else if (nodes.any { it == WorkflowInstanceNodeStatus.STARTED }) { + WorkflowInstanceStatus.RUNNING + } else { + WorkflowInstanceStatus.STARTED + } + } + + private fun updateNode(nodeId: String, update: (node: WorkflowInstanceNode) -> WorkflowInstanceNode) = + WorkflowInstance( + id = id, + timestamp = Time.now, + workflow = workflow, + context = context, + nodesExecutions = nodesExecutions.map { node -> + if (node.id == nodeId) { + update(node) + } else { + node + } + }, + ) + + fun startNode(nodeId: String) = updateNode(nodeId) { node -> + node.start() + } + + fun successNode(nodeId: String, output: JsonNode) = updateNode(nodeId) { node -> + node.success(output) + } + + fun errorNode(nodeId: String, throwable: Throwable) = updateNode(nodeId) { node -> + node.error(throwable) + } + + fun getNode(nodeId: String) = nodesExecutions.firstOrNull { it.id == nodeId } + ?: throw WorkflowNodeNotFoundException(nodeId) + + private fun collectParentsData(results: MutableMap, workflowNodeId: String, depth: Int) { + val instanceNode = getNode(workflowNodeId) + val workflowNode = workflow.getNode(workflowNodeId) + if (depth > 0) { + results[workflowNode.id] = instanceNode.output + } + workflowNode.parents.forEach { parent -> + collectParentsData(results, parent.id, depth + 1) + } + } + + /** + * Starting from a node, gets the index of all its parent's data + */ + fun getParentsData(workflowNodeId: String): Map { + val results = mutableMapOf() + collectParentsData(results, workflowNodeId, 0) + return results.toMap() + } + +} + diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceExtensions.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceExtensions.kt new file mode 100644 index 00000000000..4266dc626a9 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceExtensions.kt @@ -0,0 +1,35 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.common.Time +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowNode +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.* + +fun createInstanceId( + timestamp: LocalDateTime = Time.now(), +): String { + val timestampText = DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(timestamp) + val uuid = UUID.randomUUID().toString() + return "${timestampText}-${uuid}" +} + +fun createInstance( + workflow: Workflow, + context: WorkflowContext, + timestamp: LocalDateTime = Time.now(), +) = WorkflowInstance( + id = createInstanceId(timestamp), + timestamp = timestamp, + workflow = workflow, + context = context, + nodesExecutions = workflow.nodes.map { it.toStartExecution() }, +) + +private fun WorkflowNode.toStartExecution() = WorkflowInstanceNode( + id = id, + status = WorkflowInstanceNodeStatus.IDLE, + output = null, + error = null, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceFilter.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceFilter.kt new file mode 100644 index 00000000000..f779b0a513c --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceFilter.kt @@ -0,0 +1,6 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +data class WorkflowInstanceFilter( + val offset: Int = 0, + val size: Int = 10, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNode.kt new file mode 100644 index 00000000000..54b6722debd --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNode.kt @@ -0,0 +1,59 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.annotation.JsonIgnore +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.common.Time +import net.nemerosa.ontrack.common.reducedStackTrace +import java.time.Duration +import java.time.LocalDateTime + +/** + * Execution information about a node + * + * @property id ID of the node + */ +data class WorkflowInstanceNode( + val id: String, + val status: WorkflowInstanceNodeStatus, + val startTime: LocalDateTime? = null, + val endTime: LocalDateTime? = null, + val output: JsonNode?, + val error: String?, +) { + + @get:JsonIgnore + val durationMs: Long by lazy { + if (startTime != null && endTime != null) { + Duration.between(startTime, endTime).toMillis() + } else { + 0 + } + } + + fun start(time: LocalDateTime = Time.now) = WorkflowInstanceNode( + id = id, + status = WorkflowInstanceNodeStatus.STARTED, + startTime = time, + endTime = endTime, + output = output, + error = error, + ) + + fun success(output: JsonNode, time: LocalDateTime = Time.now) = WorkflowInstanceNode( + id = id, + status = WorkflowInstanceNodeStatus.SUCCESS, + startTime = startTime, + endTime = time, + output = output, + error = null, + ) + + fun error(throwable: Throwable, time: LocalDateTime = Time.now) = WorkflowInstanceNode( + id = id, + status = WorkflowInstanceNodeStatus.ERROR, + startTime = startTime, + endTime = time, + output = null, + error = throwable.message ?: "Unknown error in $id node", + ) +} diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNodeStatus.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNodeStatus.kt new file mode 100644 index 00000000000..f735c344e11 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNodeStatus.kt @@ -0,0 +1,10 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +enum class WorkflowInstanceNodeStatus { + + IDLE, + STARTED, + ERROR, + SUCCESS, + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNotFoundException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNotFoundException.kt new file mode 100644 index 00000000000..4b8ea5fd570 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNotFoundException.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.model.exceptions.NotFoundException + +class WorkflowInstanceNotFoundException(id: String) : NotFoundException( + "Workflows instance with id: $id was not found" +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceStatus.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceStatus.kt new file mode 100644 index 00000000000..b1848c5c384 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceStatus.kt @@ -0,0 +1,20 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +enum class WorkflowInstanceStatus( + val finished: Boolean, +) { + + STARTED( + finished = false, + ), + RUNNING( + finished = false, + ), + ERROR( + finished = true, + ), + SUCCESS( + finished = true, + ), + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceStore.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceStore.kt new file mode 100644 index 00000000000..288d3c20924 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceStore.kt @@ -0,0 +1,19 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.model.pagination.PaginatedList + +interface WorkflowInstanceStore { + + fun store(instance: WorkflowInstance): WorkflowInstance + + fun findById(id: String): WorkflowInstance? + + fun findByFilter( + workflowInstanceFilter: WorkflowInstanceFilter = WorkflowInstanceFilter(), + ): PaginatedList + + fun clearAll() + + fun cleanup() + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowNodeNotFoundException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowNodeNotFoundException.kt new file mode 100644 index 00000000000..cda1101be97 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowNodeNotFoundException.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.model.exceptions.NotFoundException + +class WorkflowNodeNotFoundException(id: String) : NotFoundException( + "Workflows node with id: $id was not found" +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueuePayload.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueuePayload.kt new file mode 100644 index 00000000000..ab85290d039 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueuePayload.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +data class WorkflowQueuePayload( + val workflowInstanceId: String, + val workflowNodeId: String, + val workflowNodeExecutorId: String, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueProcessor.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueProcessor.kt new file mode 100644 index 00000000000..34345f124ea --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueProcessor.kt @@ -0,0 +1,31 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.extension.queue.QueueProcessor +import org.springframework.context.ApplicationContext +import org.springframework.stereotype.Component +import kotlin.reflect.KClass + +@Component +class WorkflowQueueProcessor( + private val applicationContext: ApplicationContext, +) : QueueProcessor { + + private val workflowEngine: WorkflowEngine by lazy { + applicationContext.getBean(WorkflowEngine::class.java) + } + + override val id: String = "workflows" + + override val payloadType: KClass = WorkflowQueuePayload::class + + override fun isCancelled(payload: WorkflowQueuePayload): String? = null + + override fun process(payload: WorkflowQueuePayload) { + workflowEngine.processNode( + workflowInstanceId = payload.workflowInstanceId, + workflowNodeId = payload.workflowNodeId, + ) + } + + override fun getRoutingIdentifier(payload: WorkflowQueuePayload): String = payload.workflowInstanceId +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueSourceData.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueSourceData.kt new file mode 100644 index 00000000000..d2c2c6cf87e --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueSourceData.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +data class WorkflowQueueSourceData( + val workflowInstanceId: String, + val workflowNodeId: String, + val workflowNodeExecutorId: String, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueSourceExtension.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueSourceExtension.kt new file mode 100644 index 00000000000..ca0a8f55f40 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowQueueSourceExtension.kt @@ -0,0 +1,15 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.extension.queue.source.QueueSourceExtension +import net.nemerosa.ontrack.extension.support.AbstractExtension +import net.nemerosa.ontrack.extension.workflows.WorkflowsExtensionFeature +import org.springframework.stereotype.Component + +@Component +class WorkflowQueueSourceExtension( + workflowsExtensionFeature: WorkflowsExtensionFeature, +) : AbstractExtension(workflowsExtensionFeature), QueueSourceExtension { + + override val id: String = "workflow" + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutor.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutor.kt new file mode 100644 index 00000000000..6b9e8b4434a --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutor.kt @@ -0,0 +1,34 @@ +package net.nemerosa.ontrack.extension.workflows.execution + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.model.extension.Extension + +/** + * Registerable workflow callback for the execution of the nodes. + */ +interface WorkflowNodeExecutor : Extension { + + /** + * ID of the executor + */ + val id: String + + /** + * Display name for the executor + */ + val displayName: String + + /** + * Runs some action for a given workflow node. + * + * @param workflowInstance Workflow to run + * @param workflowNodeId Workflow node + * @return Outcome for the node execution + */ + fun execute( + workflowInstance: WorkflowInstance, + workflowNodeId: String, + ): JsonNode + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorNotFoundException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorNotFoundException.kt new file mode 100644 index 00000000000..67cafc9ca41 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorNotFoundException.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.extension.workflows.execution + +import net.nemerosa.ontrack.model.exceptions.NotFoundException + +class WorkflowNodeExecutorNotFoundException(id: String) : NotFoundException( + "Workflow node executor $id not found" +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorService.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorService.kt new file mode 100644 index 00000000000..187f423dc78 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorService.kt @@ -0,0 +1,9 @@ +package net.nemerosa.ontrack.extension.workflows.execution + +interface WorkflowNodeExecutorService { + + val executors: List + + fun getExecutor(executorId: String): WorkflowNodeExecutor + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorServiceImpl.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorServiceImpl.kt new file mode 100644 index 00000000000..e0cd224ef1f --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/execution/WorkflowNodeExecutorServiceImpl.kt @@ -0,0 +1,19 @@ +package net.nemerosa.ontrack.extension.workflows.execution + +import net.nemerosa.ontrack.extension.api.ExtensionManager +import org.springframework.stereotype.Service + +@Service +class WorkflowNodeExecutorServiceImpl( + private val extensionManager: ExtensionManager, +) : WorkflowNodeExecutorService { + + override val executors: List by lazy { + extensionManager.getExtensions(WorkflowNodeExecutor::class.java).sortedBy { it.displayName } + } + + override fun getExecutor(executorId: String): WorkflowNodeExecutor = + executors.find { it.id == executorId } + ?: throw WorkflowNodeExecutorNotFoundException(executorId) + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLEnumWorkflowInstanceNodeStatus.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLEnumWorkflowInstanceNodeStatus.kt new file mode 100644 index 00000000000..87ab218a0f1 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLEnumWorkflowInstanceNodeStatus.kt @@ -0,0 +1,12 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceNodeStatus +import net.nemerosa.ontrack.graphql.schema.AbstractGQLEnum +import org.springframework.stereotype.Component + +@Component +class GQLEnumWorkflowInstanceNodeStatus : AbstractGQLEnum( + type = WorkflowInstanceNodeStatus::class, + values = WorkflowInstanceNodeStatus.values(), + description = "Status of a node in a workflow", +) \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLEnumWorkflowInstanceStatus.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLEnumWorkflowInstanceStatus.kt new file mode 100644 index 00000000000..200ea83d335 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLEnumWorkflowInstanceStatus.kt @@ -0,0 +1,12 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceStatus +import net.nemerosa.ontrack.graphql.schema.AbstractGQLEnum +import org.springframework.stereotype.Component + +@Component +class GQLEnumWorkflowInstanceStatus : AbstractGQLEnum( + type = WorkflowInstanceStatus::class, + values = WorkflowInstanceStatus.values(), + description = "Status of a running workflow", +) \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstance.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstance.kt new file mode 100644 index 00000000000..93c16cb864b --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstance.kt @@ -0,0 +1,25 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLFieldDefinition +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowEngine +import net.nemerosa.ontrack.graphql.schema.GQLRootQuery +import net.nemerosa.ontrack.graphql.support.stringArgument +import org.springframework.stereotype.Component + +@Component +class GQLRootQueryWorkflowInstance( + private val gqlTypeWorkflowInstance: GQLTypeWorkflowInstance, + private val workflowEngine: WorkflowEngine, +) : GQLRootQuery { + override fun getFieldDefinition(): GraphQLFieldDefinition = + GraphQLFieldDefinition.newFieldDefinition() + .name("workflowInstance") + .description("Gets an existing workflow instance using its ID") + .type(gqlTypeWorkflowInstance.typeRef) + .argument(stringArgument("id", "ID of the workflow instance")) + .dataFetcher { env -> + val id: String = env.getArgument("id") + workflowEngine.findWorkflowInstance(id) + } + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstances.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstances.kt new file mode 100644 index 00000000000..d5b1987072f --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstances.kt @@ -0,0 +1,33 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLFieldDefinition +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceFilter +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceStore +import net.nemerosa.ontrack.graphql.schema.GQLRootQuery +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.pagination.GQLPaginatedListFactory +import org.springframework.stereotype.Component + +@Component +class GQLRootQueryWorkflowInstances( + private val gqlPaginatedListFactory: GQLPaginatedListFactory, + private val gqlTypeWorkflowInstance: GQLTypeWorkflowInstance, + private val workflowInstanceStore: WorkflowInstanceStore, +) : GQLRootQuery { + override fun getFieldDefinition(): GraphQLFieldDefinition = + gqlPaginatedListFactory.createPaginatedField( + cache = GQLTypeCache(), + fieldName = "workflowInstances", + fieldDescription = "List of workflow instances", + itemType = gqlTypeWorkflowInstance.typeName, + itemPaginatedListProvider = { _, _, offset, size -> + workflowInstanceStore.findByFilter( + WorkflowInstanceFilter( + offset = offset, + size = size, + ) + ) + } + ) +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowNodeExecutors.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowNodeExecutors.kt new file mode 100644 index 00000000000..421411cd4d8 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowNodeExecutors.kt @@ -0,0 +1,28 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLFieldDefinition +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceFilter +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceStore +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutorService +import net.nemerosa.ontrack.graphql.schema.GQLRootQuery +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.listType +import net.nemerosa.ontrack.graphql.support.pagination.GQLPaginatedListFactory +import org.springframework.stereotype.Component + +@Component +class GQLRootQueryWorkflowNodeExecutors( + private val gqlTypeWorkflowNodeExecutor: GQLTypeWorkflowNodeExecutor, + private val workflowNodeExecutorService: WorkflowNodeExecutorService, +) : GQLRootQuery { + override fun getFieldDefinition(): GraphQLFieldDefinition = + GraphQLFieldDefinition.newFieldDefinition() + .name("workflowNodeExecutors") + .description("List of all workflow node executors") + .type(listType(gqlTypeWorkflowNodeExecutor.typeRef)) + .dataFetcher { + workflowNodeExecutorService.executors + } + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflow.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflow.kt new file mode 100644 index 00000000000..e3578bbad89 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflow.kt @@ -0,0 +1,23 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.listField +import net.nemerosa.ontrack.graphql.support.stringField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflow : GQLType { + + override fun getTypeName(): String = Workflow::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Workflow") + .stringField(Workflow::name) + .listField(Workflow::nodes) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowContext.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowContext.kt new file mode 100644 index 00000000000..b469727fafd --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowContext.kt @@ -0,0 +1,24 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContext +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContextData +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.jsonField +import net.nemerosa.ontrack.graphql.support.listField +import net.nemerosa.ontrack.graphql.support.stringField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowContext : GQLType { + + override fun getTypeName(): String = WorkflowContext::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Workflow context, data which is passed to the workflow initially") + .listField(WorkflowContext::data) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowContextData.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowContextData.kt new file mode 100644 index 00000000000..9fe1b1fa766 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowContextData.kt @@ -0,0 +1,23 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContextData +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.jsonField +import net.nemerosa.ontrack.graphql.support.stringField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowContextData : GQLType { + + override fun getTypeName(): String = WorkflowContextData::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Data in a workflow context") + .stringField(WorkflowContextData::key) + .jsonField(WorkflowContextData::value) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowInstance.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowInstance.kt new file mode 100644 index 00000000000..be3ae5edf19 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowInstance.kt @@ -0,0 +1,50 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.* +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowInstance( + private val gqlTypeWorkflowInstanceNode: GQLTypeWorkflowInstanceNode, +) : GQLType { + + override fun getTypeName(): String = WorkflowInstance::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Running workflow instance") + // ID + .stringField(WorkflowInstance::id) + // Timestamp + .localDateTimeField(WorkflowInstance::timestamp) + // Status + .enumField(WorkflowInstance::status) + // Finished (status) + .booleanFieldFunction( + name = "finished", + description = "Is the workflow finished?", + ) { + it.status.finished + } + // Context of the workflow execution + .field(WorkflowInstance::context) + // Node executions + .field { + it.name(WorkflowInstance::nodesExecutions.name) + .description("List of node statuses in the workflow") + .type(listType(gqlTypeWorkflowInstanceNode.typeRef)) + } + // Workflow + .field(WorkflowInstance::workflow) + // Timing + .localDateTimeField(WorkflowInstance::startTime) + .localDateTimeField(WorkflowInstance::endTime) + .longField(WorkflowInstance::durationMs) + // OK + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowInstanceNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowInstanceNode.kt new file mode 100644 index 00000000000..bb778318da0 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowInstanceNode.kt @@ -0,0 +1,27 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceNode +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.* +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowInstanceNode : GQLType { + + override fun getTypeName(): String = WorkflowInstanceNode::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Status of a node execution in a workflow") + .stringField(WorkflowInstanceNode::id) + .enumField(WorkflowInstanceNode::status) + .jsonField(WorkflowInstanceNode::output) + .stringField(WorkflowInstanceNode::error) + .localDateTimeField(WorkflowInstanceNode::startTime) + .localDateTimeField(WorkflowInstanceNode::endTime) + .longField(WorkflowInstanceNode::durationMs) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowNode.kt new file mode 100644 index 00000000000..985dafa98f4 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowNode.kt @@ -0,0 +1,26 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowNode +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.jsonField +import net.nemerosa.ontrack.graphql.support.listField +import net.nemerosa.ontrack.graphql.support.stringField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowNode : GQLType { + + override fun getTypeName(): String = WorkflowNode::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Workflow node") + .stringField(WorkflowNode::id) + .stringField(WorkflowNode::executorId) + .jsonField(WorkflowNode::data) + .listField(WorkflowNode::parents) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowNodeExecutor.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowNodeExecutor.kt new file mode 100644 index 00000000000..44fe8267ff1 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowNodeExecutor.kt @@ -0,0 +1,22 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutor +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.stringField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowNodeExecutor : GQLType { + + override fun getTypeName(): String = WorkflowNodeExecutor::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Workflow node executor") + .stringField(WorkflowNodeExecutor::id) + .stringField(WorkflowNodeExecutor::displayName) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowParentNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowParentNode.kt new file mode 100644 index 00000000000..7e90cc0f564 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowParentNode.kt @@ -0,0 +1,21 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowParentNode +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.stringField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowParentNode : GQLType { + + override fun getTypeName(): String = WorkflowParentNode::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Workflow parent node") + .stringField(WorkflowParentNode::id) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowValidation.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowValidation.kt new file mode 100644 index 00000000000..1b8cb7b2913 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLTypeWorkflowValidation.kt @@ -0,0 +1,23 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import graphql.schema.GraphQLObjectType +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidation +import net.nemerosa.ontrack.graphql.schema.GQLType +import net.nemerosa.ontrack.graphql.schema.GQLTypeCache +import net.nemerosa.ontrack.graphql.support.booleanField +import net.nemerosa.ontrack.graphql.support.stringListField +import org.springframework.stereotype.Component + +@Component +class GQLTypeWorkflowValidation : GQLType { + + override fun getTypeName(): String = WorkflowValidation::class.java.simpleName + + override fun createType(cache: GQLTypeCache): GraphQLObjectType = + GraphQLObjectType.newObject() + .name(typeName) + .description("Workflow validation") + .stringListField(WorkflowValidation::errors) + .booleanField(WorkflowValidation::error) + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/WorkflowsMutations.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/WorkflowsMutations.kt new file mode 100644 index 00000000000..e61a490966b --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/graphql/WorkflowsMutations.kt @@ -0,0 +1,83 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidation +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContext +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContextData +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowEngine +import net.nemerosa.ontrack.extension.workflows.registry.WorkflowRegistry +import net.nemerosa.ontrack.graphql.schema.Mutation +import net.nemerosa.ontrack.graphql.support.ListRef +import net.nemerosa.ontrack.graphql.support.TypedMutationProvider +import org.springframework.stereotype.Component + +@Component +class WorkflowsMutations( + private val workflowRegistry: WorkflowRegistry, + private val workflowEngine: WorkflowEngine, +) : TypedMutationProvider() { + + override val mutations: List = listOf( + simpleMutation( + name = "validateJsonWorkflow", + description = "Validates a workflow which is defined as JSON", + input = ValidateJsonWorkflowInput::class, + outputName = "validation", + outputDescription = "Result of the validation", + outputType = WorkflowValidation::class + ) { input -> + workflowRegistry.validateJsonWorkflow(input.workflow) + }, + simpleMutation( + name = "saveYamlWorkflow", + description = "Saves a workflow which is defined as YAML", + input = SaveYamlWorkflowInput::class, + outputName = "workflowId", + outputDescription = "Saved workflow ID", + outputType = String::class + ) { input -> + workflowRegistry.saveYamlWorkflow(input.workflow) + }, + simpleMutation( + name = "launchWorkflow", + description = "Launches an existing workflow", + input = LaunchWorkflowInput::class, + outputName = "workflowInstanceId", + outputDescription = "Workflow instance ID", + outputType = String::class + ) { input -> + val workflowRecord = workflowRegistry.findWorkflow(input.workflowId) + if (workflowRecord != null) { + workflowEngine.startWorkflow( + workflow = workflowRecord.workflow, + context = WorkflowContext( + input.context.map { + WorkflowContextData(it.key, it.value) + } + ), + ).id + } else { + null + } + }, + ) +} + +data class ValidateJsonWorkflowInput( + val workflow: JsonNode, +) + +data class SaveYamlWorkflowInput( + val workflow: String, +) + +data class LaunchWorkflowInput( + val workflowId: String, + @ListRef(embedded = true) + val context: List, +) + +data class LaunchWorkflowInputContext( + val key: String, + val value: JsonNode, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowInstanceCleanupJob.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowInstanceCleanupJob.kt new file mode 100644 index 00000000000..baf24fd1c94 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowInstanceCleanupJob.kt @@ -0,0 +1,36 @@ +package net.nemerosa.ontrack.extension.workflows.mgt + +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceStore +import net.nemerosa.ontrack.job.* +import net.nemerosa.ontrack.model.support.JobProvider +import org.springframework.stereotype.Component + +@Component +class WorkflowInstanceCleanupJob( + private val workflowInstanceStore: WorkflowInstanceStore, +) : JobProvider { + override fun getStartingJobs(): Collection = + listOf( + createWorkflowInstanceCleanupJobRegistration() + ) + + private fun createWorkflowInstanceCleanupJobRegistration() = JobRegistration( + job = createWorkflowInstanceCleanupJob(), + schedule = Schedule.EVERY_DAY, + ) + + private fun createWorkflowInstanceCleanupJob() = object : Job { + + override fun getKey(): JobKey = + WorkflowJobs.TYPE_CLEANUP.getKey("main") + + override fun getTask() = JobRun { + workflowInstanceStore.cleanup() + } + + override fun getDescription(): String = "Cleanup of workflow instances past their retention time" + + override fun isDisabled(): Boolean = false + + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowJobs.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowJobs.kt new file mode 100644 index 00000000000..e4888e2ae8d --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowJobs.kt @@ -0,0 +1,11 @@ +package net.nemerosa.ontrack.extension.workflows.mgt + +import net.nemerosa.ontrack.job.JobCategory + +object WorkflowJobs { + + private val CATEGORY = JobCategory.of("workflows").withName("Workflows") + + val TYPE_CLEANUP = CATEGORY.getType("cleanup-instances").withName("Cleanup of instances") + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettings.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettings.kt new file mode 100644 index 00000000000..62d423d7d3d --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettings.kt @@ -0,0 +1,15 @@ +package net.nemerosa.ontrack.extension.workflows.mgt + +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.annotations.APILabel +import java.time.Duration + +data class WorkflowSettings( + @APILabel("Retention duration") + @APIDescription("Number of milliseconds before workflow instances are removed") + val retentionDuration: Long = DEFAULT_RETENTION_DURATION, +) { + companion object { + val DEFAULT_RETENTION_DURATION = Duration.ofDays(14).toMillis() + } +} diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsCasc.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsCasc.kt new file mode 100644 index 00000000000..bfed88a2c86 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsCasc.kt @@ -0,0 +1,26 @@ +package net.nemerosa.ontrack.extension.workflows.mgt + +import net.nemerosa.ontrack.extension.casc.context.settings.AbstractSubSettingsContext +import net.nemerosa.ontrack.extension.casc.schema.CascType +import net.nemerosa.ontrack.extension.casc.schema.cascField +import net.nemerosa.ontrack.extension.casc.schema.cascObject +import net.nemerosa.ontrack.model.settings.CachedSettingsService +import net.nemerosa.ontrack.model.settings.SettingsManagerService +import org.springframework.stereotype.Component + +@Component +class WorkflowSettingsCasc( + settingsManagerService: SettingsManagerService, + cachedSettingsService: CachedSettingsService, +) : AbstractSubSettingsContext( + "workflows", + WorkflowSettings::class, + settingsManagerService, + cachedSettingsService +) { + + override val type: CascType = cascObject( + "Global settings for the management of workflows", + cascField(WorkflowSettings::retentionDuration), + ) +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsManager.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsManager.kt new file mode 100644 index 00000000000..f10b09ca0ff --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsManager.kt @@ -0,0 +1,37 @@ +package net.nemerosa.ontrack.extension.workflows.mgt + +import net.nemerosa.ontrack.model.form.Form +import net.nemerosa.ontrack.model.form.longField +import net.nemerosa.ontrack.model.security.SecurityService +import net.nemerosa.ontrack.model.settings.AbstractSettingsManager +import net.nemerosa.ontrack.model.settings.CachedSettingsService +import net.nemerosa.ontrack.model.support.SettingsRepository +import net.nemerosa.ontrack.model.support.setLong +import org.springframework.stereotype.Component + +@Component +class WorkflowSettingsManager( + cachedSettingsService: CachedSettingsService, + securityService: SecurityService, + private val settingsRepository: SettingsRepository, +) : AbstractSettingsManager( + WorkflowSettings::class.java, + cachedSettingsService, + securityService, +) { + override fun doSaveSettings(settings: WorkflowSettings) { + settingsRepository.setLong(settings::retentionDuration) + } + + override fun getId(): String = "workflows" + + override fun getTitle(): String = "Workflows" + + @Deprecated("Deprecated in Java") + override fun getSettingsForm(settings: WorkflowSettings?): Form = + Form.create() + .longField( + WorkflowSettings::retentionDuration, + settings?.retentionDuration + ) +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsProvider.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsProvider.kt new file mode 100644 index 00000000000..694248fe8a2 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mgt/WorkflowSettingsProvider.kt @@ -0,0 +1,21 @@ +package net.nemerosa.ontrack.extension.workflows.mgt + +import net.nemerosa.ontrack.model.settings.SettingsProvider +import net.nemerosa.ontrack.model.support.SettingsRepository +import net.nemerosa.ontrack.model.support.getLong +import org.springframework.stereotype.Component + +@Component +class WorkflowSettingsProvider( + private val settingsRepository: SettingsRepository, +) : SettingsProvider { + + override fun getSettings() = WorkflowSettings( + retentionDuration = settingsRepository.getLong( + WorkflowSettings::retentionDuration, + WorkflowSettings.DEFAULT_RETENTION_DURATION + ), + ) + + override fun getSettingsClass(): Class = WorkflowSettings::class.java +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/GQLRootQueryMockWorkflowTexts.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/GQLRootQueryMockWorkflowTexts.kt new file mode 100644 index 00000000000..ec1137b960b --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/GQLRootQueryMockWorkflowTexts.kt @@ -0,0 +1,29 @@ +package net.nemerosa.ontrack.extension.workflows.mock + +import graphql.Scalars.GraphQLString +import graphql.schema.GraphQLFieldDefinition +import net.nemerosa.ontrack.common.RunProfile +import net.nemerosa.ontrack.graphql.schema.GQLRootQuery +import net.nemerosa.ontrack.graphql.support.listType +import net.nemerosa.ontrack.graphql.support.stringArgument +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Component + +@Component +@Profile(RunProfile.ACC, RunProfile.UNIT_TEST, RunProfile.DEV) +class GQLRootQueryMockWorkflowTexts( + private val mockWorkflowNodeExecutor: MockWorkflowNodeExecutor, +) : GQLRootQuery { + + override fun getFieldDefinition(): GraphQLFieldDefinition = + GraphQLFieldDefinition.newFieldDefinition() + .name("mockWorkflowTexts") + .description("Getting a list of texts generated for a mock workflow") + .type(listType(GraphQLString)) + .argument(stringArgument("instanceId", "ID of the workflow instance")) + .dataFetcher { env -> + val instanceId: String = env.getArgument("instanceId") + mockWorkflowNodeExecutor.getTextsByInstanceId(instanceId) + } + .build() +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockNodeData.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockNodeData.kt new file mode 100644 index 00000000000..96e03e1bcf2 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockNodeData.kt @@ -0,0 +1,12 @@ +package net.nemerosa.ontrack.extension.workflows.mock + +import net.nemerosa.ontrack.model.annotations.APIDescription + +data class MockNodeData( + @APIDescription("Text associated with the node") + val text: String, + @APIDescription("Time to wait for the execution of the node") + val waitMs: Long = 0, + @APIDescription("Raising an error during the execution of the node") + val error: Boolean = false, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockNodeOutput.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockNodeOutput.kt new file mode 100644 index 00000000000..4927e120d1c --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockNodeOutput.kt @@ -0,0 +1,5 @@ +package net.nemerosa.ontrack.extension.workflows.mock + +data class MockNodeOutput( + val text: String, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockWorkflowNodeExecutor.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockWorkflowNodeExecutor.kt new file mode 100644 index 00000000000..24e4a5b1047 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/mock/MockWorkflowNodeExecutor.kt @@ -0,0 +1,93 @@ +package net.nemerosa.ontrack.extension.workflows.mock + +import com.fasterxml.jackson.databind.JsonNode +import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking +import net.nemerosa.ontrack.common.RunProfile +import net.nemerosa.ontrack.extension.support.AbstractExtension +import net.nemerosa.ontrack.extension.workflows.WorkflowsExtensionFeature +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutor +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.json.parse +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.Documentation +import net.nemerosa.ontrack.model.docs.DocumentationExampleCode +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Component + +@Component +@Profile(RunProfile.ACC, RunProfile.UNIT_TEST, RunProfile.DEV) +@APIDescription("Executor used to mock some actions for the nodes. Mostly used for testing.") +@Documentation(MockNodeData::class) +@Documentation(MockNodeOutput::class, section = "output") +@DocumentationExampleCode(""" + executorId: mock + data: + text: Some text to store + waitMs: 500 + error: false +""") +class MockWorkflowNodeExecutor( + workflowsExtensionFeature: WorkflowsExtensionFeature, +) : AbstractExtension(workflowsExtensionFeature), WorkflowNodeExecutor { + + override val id: String = "mock" + override val displayName: String = "Mock" + + private val texts = mutableMapOf>() + + fun getTextsByInstanceId(instanceId: String): List = texts[instanceId] ?: emptyList() + + override fun execute(workflowInstance: WorkflowInstance, workflowNodeId: String): JsonNode { + // Gets the node & its data + val nodeRawData = workflowInstance.workflow.getNode(workflowNodeId).data + val nodeData = if (nodeRawData.isTextual) { + MockNodeData(nodeRawData.asText()) + } else { + nodeRawData.parse() + } + // Error? + if (nodeData.error) { + error("Error in $workflowNodeId node") + } + // Gets the parent outputs in an index + val parentsData = workflowInstance.getParentsData(workflowNodeId) + // Using the context + val execContext = workflowInstance.context.getValue("mock") + val context = if (execContext.has("text")) { + execContext.path("text").asText() + } else { + execContext.asText() + } + // Initial text + val initialText = nodeData.text + // Replacements by parents references + val replacedText = "#([a-zA-Z][a-zA-Z0-9_-]*)".toRegex().replace(initialText) { m -> + val parentId = m.groupValues[1] + val parentOutput = parentsData[parentId] + if (parentOutput != null) { + val output = parentOutput.parse() + output.text + } else { + // Parent has no data + "#none" + } + } + // Returning some new text + val text = "Processed: $replacedText for $context" + // Waiting time + if (nodeData.waitMs > 0) { + runBlocking { + delay(nodeData.waitMs) + } + } + // Recording + val old = texts[workflowInstance.id] + texts[workflowInstance.id] = if (old != null) old + text else listOf(text) + // OK + return MockNodeOutput( + text = text + ).asJson() + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannel.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannel.kt new file mode 100644 index 00000000000..6150c9372a8 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannel.kt @@ -0,0 +1,82 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.NullNode +import net.nemerosa.ontrack.extension.notifications.channels.AbstractNotificationChannel +import net.nemerosa.ontrack.extension.notifications.channels.NoTemplate +import net.nemerosa.ontrack.extension.notifications.channels.NotificationResult +import net.nemerosa.ontrack.extension.notifications.model.Notification +import net.nemerosa.ontrack.extension.notifications.queue.NotificationQueueItemConverter +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowNode +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContext +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowEngine +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.Documentation +import net.nemerosa.ontrack.model.events.Event +import net.nemerosa.ontrack.model.events.EventTemplatingService +import net.nemerosa.ontrack.model.events.PlainEventRenderer +import net.nemerosa.ontrack.model.form.Form +import org.springframework.stereotype.Component + +@Component +@APIDescription("Launches a workflow") +@NoTemplate +@Documentation(WorkflowNotificationChannelConfig::class) +@Documentation(WorkflowNotificationChannelOutput::class, section = "output") +class WorkflowNotificationChannel( + private val workflowEngine: WorkflowEngine, + private val workflowNotificationItemConverter: WorkflowNotificationItemConverter, + private val eventTemplatingService: EventTemplatingService, +) : AbstractNotificationChannel( + WorkflowNotificationChannelConfig::class +) { + + override fun publish( + config: WorkflowNotificationChannelConfig, + event: Event, + context: Map, + template: String?, // Not used for this notification channel + outputProgressCallback: (current: WorkflowNotificationChannelOutput) -> WorkflowNotificationChannelOutput + ): NotificationResult { + // Converting the event to a suitable format + val item = workflowNotificationItemConverter.convertForQueue(event) + // Templating for the workflow name + val workflow = config.workflow.rename { + eventTemplatingService.renderEvent( + event = event, + context = context, + template = it, + renderer = PlainEventRenderer.INSTANCE, + ) + } + // Launching the workflow (with the event as context, template is not used) + val instance = workflowEngine.startWorkflow( + workflow = workflow, + context = WorkflowContext(WorkflowNotificationChannelNodeExecutor.CONTEXT_EVENT, item.asJson()), + ) + // Output contains only the instance ID + return NotificationResult.ok( + WorkflowNotificationChannelOutput( + workflowInstanceId = instance.id, + ) + ) + } + + override fun toSearchCriteria(text: String): JsonNode = mapOf( + "workflow" to mapOf( + "name" to text + ) + ).asJson() + + override val type: String = "workflow" + override val displayName: String = "Workflow" + override val enabled: Boolean = true + + @Deprecated("Will be removed in V5. Only Next UI is used.") + override fun getForm(c: WorkflowNotificationChannelConfig?): Form = Form.create() + + @Deprecated("Will be removed in V5. Only Next UI is used.") + override fun toText(config: WorkflowNotificationChannelConfig): String = config.workflow.name +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelConfig.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelConfig.kt new file mode 100644 index 00000000000..6ea69545aae --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelConfig.kt @@ -0,0 +1,11 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.DocumentationField + +data class WorkflowNotificationChannelConfig( + @APIDescription("Workflow to run") + @DocumentationField + val workflow: Workflow, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelConfigNode.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelConfigNode.kt new file mode 100644 index 00000000000..4da874fe2c9 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelConfigNode.kt @@ -0,0 +1,12 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowParentNode + +data class WorkflowNotificationChannelConfigNode( + val id: String, + val parents: List, + val channel: String, + val channelConfig: JsonNode, + val template: String?, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeData.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeData.kt new file mode 100644 index 00000000000..6c42a25ebda --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeData.kt @@ -0,0 +1,13 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.model.annotations.APIDescription + +data class WorkflowNotificationChannelNodeData( + @APIDescription("Notification channel ID") + val channel: String, + @APIDescription("Notification channel configuration") + val channelConfig: JsonNode, + @APIDescription("Optional template for the notification") + val template: String?, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeExecutor.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeExecutor.kt new file mode 100644 index 00000000000..3767e20a52f --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeExecutor.kt @@ -0,0 +1,73 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.notifications.model.Notification +import net.nemerosa.ontrack.extension.notifications.processing.NotificationProcessingService +import net.nemerosa.ontrack.extension.notifications.queue.NotificationQueueItem +import net.nemerosa.ontrack.extension.support.AbstractExtension +import net.nemerosa.ontrack.extension.workflows.WorkflowsExtensionFeature +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutor +import net.nemerosa.ontrack.extension.workflows.templating.WorkflowTemplatingRenderable +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.json.parse +import net.nemerosa.ontrack.model.annotations.APIDescription +import net.nemerosa.ontrack.model.docs.Documentation +import net.nemerosa.ontrack.model.docs.DocumentationExampleCode +import net.nemerosa.ontrack.model.events.Event +import org.springframework.stereotype.Component + +@Component +@APIDescription(""" + Wraps a notification in a workflow node. + + The output of this execution is exactly the output + of the notification channel. +""") +@DocumentationExampleCode(""" + executorId: notification + data: + channel: slack + channelConfig: + channel: "#my-channel" + template: | + Message template +""") +@Documentation(WorkflowNotificationChannelNodeData::class) +class WorkflowNotificationChannelNodeExecutor( + workflowsExtensionFeature: WorkflowsExtensionFeature, + private val notificationProcessingService: NotificationProcessingService, + private val workflowNotificationItemConverter: WorkflowNotificationItemConverter, +) : AbstractExtension(workflowsExtensionFeature), WorkflowNodeExecutor { + + companion object { + const val ID: String = "notification" + + const val CONTEXT_EVENT = "event" + } + + override val id: String = ID + override val displayName: String = "Notification" + + override fun execute(workflowInstance: WorkflowInstance, workflowNodeId: String): JsonNode { + // Gets the node's data + val (channel, channelConfig, template) = workflowInstance.workflow.getNode(workflowNodeId).data.parse() + // Gets the context + val queueItem = workflowInstance.context.parse(CONTEXT_EVENT) + // Creating the notification item + val notification = workflowNotificationItemConverter.convertFromQueue( + channel = channel, + channelConfig = channelConfig, + template = template, + queueItem = queueItem + ) + // Enriches the context + val context = mapOf( + "workflow" to WorkflowTemplatingRenderable(workflowInstance), + ) + // Processing + val output = notificationProcessingService.process(notification, context) + // Returning the output + return output.asJson() + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelOutput.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelOutput.kt new file mode 100644 index 00000000000..c10af308a7d --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelOutput.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import net.nemerosa.ontrack.model.annotations.APIDescription + +data class WorkflowNotificationChannelOutput( + @APIDescription("ID of the workflow instance. Can be used to track the progress and outcome of the workflow.") + val workflowInstanceId: String, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationItemConverter.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationItemConverter.kt new file mode 100644 index 00000000000..7ecab52bf87 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationItemConverter.kt @@ -0,0 +1,19 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.notifications.model.Notification +import net.nemerosa.ontrack.extension.notifications.queue.NotificationQueueItem +import net.nemerosa.ontrack.model.events.Event + +interface WorkflowNotificationItemConverter { + + fun convertForQueue(event: Event): NotificationQueueItem + + fun convertFromQueue( + channel: String, + channelConfig: JsonNode, + template: String?, + queueItem: NotificationQueueItem, + ): Notification + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationItemConverterImpl.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationItemConverterImpl.kt new file mode 100644 index 00000000000..60d7f945b48 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationItemConverterImpl.kt @@ -0,0 +1,46 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.NullNode +import net.nemerosa.ontrack.extension.notifications.model.Notification +import net.nemerosa.ontrack.extension.notifications.queue.NotificationQueueItem +import net.nemerosa.ontrack.extension.notifications.queue.NotificationQueueItemConverter +import net.nemerosa.ontrack.model.events.Event +import org.springframework.stereotype.Component + +@Component +class WorkflowNotificationItemConverterImpl( + private val notificationQueueItemConverter: NotificationQueueItemConverter, +) : WorkflowNotificationItemConverter { + + companion object { + private const val CHANNEL = "workflow" + } + + override fun convertForQueue(event: Event): NotificationQueueItem { + return notificationQueueItemConverter.convertForQueue( + Notification( + channel = CHANNEL, + channelConfig = NullNode.instance, + event = event, + template = null, + ) + ) + } + + override fun convertFromQueue( + channel: String, + channelConfig: JsonNode, + template: String?, + queueItem: NotificationQueueItem, + ): Notification { + return notificationQueueItemConverter.convertFromQueue(queueItem).run { + Notification( + channel = channel, + channelConfig = channelConfig, + event = event, + template = template, + ) + } + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParser.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParser.kt new file mode 100644 index 00000000000..7e743242a6c --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParser.kt @@ -0,0 +1,20 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.json.parseOrNull +import net.nemerosa.ontrack.yaml.Yaml + +object WorkflowParser { + + fun parseJsonWorkflow(json: JsonNode): Workflow = + json.parseOrNull() + ?: throw WorkflowParsingException() + + fun parseYamlWorkflow(workflowYaml: String): Workflow = + Yaml().read(workflowYaml) + .firstOrNull() + ?.let { parseJsonWorkflow(it) } + ?: throw WorkflowParsingException() + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParsingException.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParsingException.kt new file mode 100644 index 00000000000..4700126c38e --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParsingException.kt @@ -0,0 +1,5 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import net.nemerosa.ontrack.model.exceptions.InputException + +class WorkflowParsingException : InputException("Cannot parse workflow") diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRecord.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRecord.kt new file mode 100644 index 00000000000..d4721fe9a81 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRecord.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import net.nemerosa.ontrack.extension.workflows.definition.Workflow + +data class WorkflowRecord( + val id: String, + val workflow: Workflow, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistry.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistry.kt new file mode 100644 index 00000000000..558e8cea890 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistry.kt @@ -0,0 +1,14 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidation + +interface WorkflowRegistry { + + fun validateJsonWorkflow(workflow: JsonNode): WorkflowValidation + + fun saveYamlWorkflow(workflow: String): String + + fun findWorkflow(workflowId: String): WorkflowRecord? + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistryImpl.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistryImpl.kt new file mode 100644 index 00000000000..7249e8f642f --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistryImpl.kt @@ -0,0 +1,68 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.acl.WorkflowRegistration +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowNode +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidation +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidation.Companion.validateWorkflow +import net.nemerosa.ontrack.model.security.SecurityService +import net.nemerosa.ontrack.model.support.StorageService +import org.springframework.stereotype.Service +import java.util.* + +@Service +class WorkflowRegistryImpl( + private val storageService: StorageService, + private val securityService: SecurityService, +) : WorkflowRegistry { + + companion object { + private val STORE = WorkflowRegistry::class.java.name + } + + override fun validateJsonWorkflow(workflow: JsonNode): WorkflowValidation { + // Parsing of the workflow + val workflowObj: Workflow = try { + WorkflowParser.parseJsonWorkflow(workflow) + } catch (ex: Exception) { + return WorkflowValidation.error(ex) + } + // Validation + return validateWorkflow(workflowObj) + } + + override fun saveYamlWorkflow(workflow: String): String { + // Checking the access right + securityService.checkGlobalFunction(WorkflowRegistration::class.java) + // Parsing of the workflow + val workflowObj: Workflow = WorkflowParser.parseYamlWorkflow(workflow) + // Validation + validateWorkflow(workflowObj).throwErrorIfAny() + // Generating an ID + val id = UUID.randomUUID().toString() + // Record to save + val record = InternalRecord( + workflow = workflowObj, + ) + // Saving the record + storageService.store(STORE, id, record) + // OK + return id + } + + override fun findWorkflow(workflowId: String): WorkflowRecord? { + securityService.checkGlobalFunction(WorkflowRegistration::class.java) + return storageService.find(STORE, workflowId, InternalRecord::class) + ?.run { + WorkflowRecord( + id = workflowId, + workflow = workflow, + ) + } + } + + private data class InternalRecord( + val workflow: Workflow, + ) +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/templating/WorkflowTemplatingRenderable.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/templating/WorkflowTemplatingRenderable.kt new file mode 100644 index 00000000000..74d8be829e7 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/templating/WorkflowTemplatingRenderable.kt @@ -0,0 +1,43 @@ +package net.nemerosa.ontrack.extension.workflows.templating + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceNodeStatus +import net.nemerosa.ontrack.json.JsonPathUtils +import net.nemerosa.ontrack.model.events.EventRenderer +import net.nemerosa.ontrack.model.templating.TemplatingGeneralException +import net.nemerosa.ontrack.model.templating.TemplatingRenderable +import net.nemerosa.ontrack.model.templating.TemplatingRenderableFieldRequiredException +import net.nemerosa.ontrack.model.templating.getRequiredTemplatingParam + +class WorkflowTemplatingRenderable( + private val workflowInstance: WorkflowInstance, +) : TemplatingRenderable { + + override fun render(field: String?, configMap: Map, renderer: EventRenderer): String = + if (field.isNullOrBlank()) { + throw TemplatingRenderableFieldRequiredException() + } else { + // Field == node ID + val node = workflowInstance.getNode(field) + // Checking the node state + if (node.status != WorkflowInstanceNodeStatus.SUCCESS) { + throw TemplatingGeneralException("Node $field is not in SUCCESS state and cannot be used.") + } else if (node.output == null) { + throw TemplatingGeneralException("Node $field has no output.") + } + // We require the path to the data to get + val path = configMap.getRequiredTemplatingParam(WorkflowTemplatingRenderableParameters::path.name) + // Getting the raw JSON data from the node output + val data: JsonNode? = JsonPathUtils.get(node.output, path) + // Only text is supported + if (data == null || data.isNull) { + "" + } else if (data.isTextual) { + data.asText() + } else { + throw TemplatingGeneralException("Node $field output does not contain a text node at $path") + } + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/templating/WorkflowTemplatingRenderableParameters.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/templating/WorkflowTemplatingRenderableParameters.kt new file mode 100644 index 00000000000..c5e0230c8bc --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/templating/WorkflowTemplatingRenderableParameters.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.extension.workflows.templating + +import net.nemerosa.ontrack.model.annotations.APIDescription + +data class WorkflowTemplatingRenderableParameters( + @APIDescription("JSON path to the data to render") + val path: String, +) diff --git a/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/ui/WorkflowInstancesUserMenuItemExtension.kt b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/ui/WorkflowInstancesUserMenuItemExtension.kt new file mode 100644 index 00000000000..ad3f055e167 --- /dev/null +++ b/ontrack-extension-workflows/src/main/java/net/nemerosa/ontrack/extension/workflows/ui/WorkflowInstancesUserMenuItemExtension.kt @@ -0,0 +1,34 @@ +package net.nemerosa.ontrack.extension.workflows.ui + +import net.nemerosa.ontrack.extension.api.UserMenuItemExtension +import net.nemerosa.ontrack.extension.support.AbstractExtension +import net.nemerosa.ontrack.extension.workflows.WorkflowsExtensionFeature +import net.nemerosa.ontrack.extension.workflows.acl.WorkflowAudit +import net.nemerosa.ontrack.model.security.SecurityService +import net.nemerosa.ontrack.model.security.isGlobalFunctionGranted +import net.nemerosa.ontrack.model.support.CoreUserMenuGroups +import net.nemerosa.ontrack.model.support.UserMenuItem +import org.springframework.stereotype.Component + +@Component +class WorkflowInstancesUserMenuItemExtension( + workflowsExtensionFeature: WorkflowsExtensionFeature, + private val securityService: SecurityService, +) : AbstractExtension(workflowsExtensionFeature), UserMenuItemExtension { + + override val items: List + get() { + val list = mutableListOf() + + if (securityService.isGlobalFunctionGranted()) { + list += UserMenuItem( + groupId = CoreUserMenuGroups.INFORMATION, + extension = feature, + id = "audit", + name = "Workflows audit", + ) + } + + return list.toList() + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/AbstractWorkflowTestSupport.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/AbstractWorkflowTestSupport.kt new file mode 100644 index 00000000000..1148b07eb26 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/AbstractWorkflowTestSupport.kt @@ -0,0 +1,18 @@ +package net.nemerosa.ontrack.extension.workflows + +import net.nemerosa.ontrack.graphql.AbstractQLKTITSupport +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.test.context.TestPropertySource + +@TestPropertySource( + properties = [ + "net.nemerosa.ontrack.extension.workflows.store=memory", + "ontrack.extension.queue.general.async=false", + ] +) +abstract class AbstractWorkflowTestSupport : AbstractQLKTITSupport() { + + @Autowired + protected lateinit var workflowTestSupport: WorkflowTestSupport + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/WorkflowTestSupport.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/WorkflowTestSupport.kt new file mode 100644 index 00000000000..6e290fe6155 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/WorkflowTestSupport.kt @@ -0,0 +1,87 @@ +package net.nemerosa.ontrack.extension.workflows + +import com.fasterxml.jackson.databind.node.TextNode +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContext +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowContextData +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowEngine +import net.nemerosa.ontrack.extension.workflows.engine.getWorkflowInstance +import net.nemerosa.ontrack.extension.workflows.notifications.WorkflowNotificationChannelNodeExecutor +import net.nemerosa.ontrack.extension.workflows.notifications.WorkflowNotificationItemConverter +import net.nemerosa.ontrack.extension.workflows.registry.WorkflowRegistry +import net.nemerosa.ontrack.it.waitUntil +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.model.events.Event +import net.nemerosa.ontrack.model.security.SecurityService +import org.springframework.stereotype.Component +import java.util.concurrent.TimeoutException +import kotlin.test.fail +import kotlin.time.Duration.Companion.seconds +import kotlin.time.ExperimentalTime + +@Component +class WorkflowTestSupport( + private val workflowEngine: WorkflowEngine, + private val workflowRegistry: WorkflowRegistry, + private val workflowNotificationItemConverter: WorkflowNotificationItemConverter, + private val securityService: SecurityService, +) { + + private fun displayInstance(instanceId: String) { + val workflowInstance = workflowEngine.getWorkflowInstance(instanceId) + workflowInstance.nodesExecutions.forEach { node -> + println("node = ${node.id}") + println(" * status = ${node.status}") + println(" * start = ${node.startTime}") + println(" * end = ${node.endTime}") + println(" * output = ${node.output}") + println(" * error = ${node.error}") + } + } + + @OptIn(ExperimentalTime::class) + fun registerLaunchAndWaitForWorkflow( + yaml: String, + workflowContextName: String? = null, + event: Event? = null, + display: Boolean = false, + ): String { + return securityService.asAdmin { + val workflowId = workflowRegistry.saveYamlWorkflow(yaml) + // Getting the workflow + val record = workflowRegistry.findWorkflow(workflowId) ?: fail("No workflow found for $workflowId") + + // Context + val contextData = mutableListOf() + if (!workflowContextName.isNullOrBlank()) { + contextData += WorkflowContextData("mock", TextNode(workflowContextName)) + } + if (event != null) { + val item = workflowNotificationItemConverter.convertForQueue(event) + contextData += WorkflowContextData(WorkflowNotificationChannelNodeExecutor.CONTEXT_EVENT, item.asJson()) + } + val context = WorkflowContext(contextData) + + // Launching the workflow + val instance = workflowEngine.startWorkflow(record.workflow, context) + // Waiting until the workflow is completed (error or success) + try { + waitUntil("Waiting until workflow is complete", timeout = 10.seconds) { + val workflowInstance = workflowEngine.getWorkflowInstance(instance.id) + println("workflowInstance = $workflowInstance") + workflowInstance.status.finished + } + } catch (any: TimeoutException) { + // Displaying the state of the instance + displayInstance(instance.id) + // Going on with the error + throw any + } + // Displaying + if (display) { + displayInstance(instance.id) + } + // OK + instance.id + } + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowFixtures.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowFixtures.kt new file mode 100644 index 00000000000..975cb2c1a51 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowFixtures.kt @@ -0,0 +1,90 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +import com.fasterxml.jackson.databind.node.NullNode +import com.fasterxml.jackson.databind.node.TextNode + +object WorkflowFixtures { + + fun simpleLinearWorkflow() = + Workflow( + name = "Simple linear", + nodes = listOf( + WorkflowNode( + id = "start", + executorId = "mock", + data = TextNode("Start node"), + parents = emptyList(), + ), + WorkflowNode( + id = "end", + executorId = "mock", + data = TextNode("End node"), + parents = listOf( + WorkflowParentNode( + id = "start" + ) + ), + ), + ) + ) + + fun cyclicWorkflow() = + Workflow( + name = "Simple cyclic", + nodes = listOf( + WorkflowNode( + id = "start", + executorId = "mock", + data = TextNode("Start node"), + parents = listOf( + WorkflowParentNode( + id = "end", + ) + ), + ), + WorkflowNode( + id = "end", + executorId = "mock", + data = TextNode("End node"), + parents = listOf( + WorkflowParentNode( + id = "start" + ) + ), + ), + ) + ) + + fun twoParallelAndJoin() = + Workflow( + name = "Parallel with join", + nodes = listOf( + WorkflowNode( + id = "start-a", + executorId = "mock", + data = TextNode("Start node A"), + parents = emptyList(), + ), + WorkflowNode( + id = "start-b", + executorId = "mock", + data = TextNode("Start node B"), + parents = emptyList(), + ), + WorkflowNode( + id = "end", + executorId = "mock", + data = TextNode("End node"), + parents = listOf( + WorkflowParentNode( + id = "start-a", + ), + WorkflowParentNode( + id = "start-b", + ), + ), + ), + ) + ) + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowTest.kt new file mode 100644 index 00000000000..9ac5ad1baa9 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/definition/WorkflowTest.kt @@ -0,0 +1,26 @@ +package net.nemerosa.ontrack.extension.workflows.definition + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class WorkflowTest { + + @Test + fun `One single start node`() { + val workflow = WorkflowFixtures.simpleLinearWorkflow() + assertEquals( + listOf("start"), + workflow.getNextNodes(null) + ) + } + + @Test + fun `Two start nodes`() { + val workflow = WorkflowFixtures.twoParallelAndJoin() + assertEquals( + listOf("start-a", "start-b"), + workflow.getNextNodes(null) + ) + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/DatabaseWorkflowInstanceStoreIT.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/DatabaseWorkflowInstanceStoreIT.kt new file mode 100644 index 00000000000..92d5b1c9708 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/DatabaseWorkflowInstanceStoreIT.kt @@ -0,0 +1,69 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.common.Time +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowFixtures +import net.nemerosa.ontrack.extension.workflows.mgt.WorkflowSettings +import net.nemerosa.ontrack.it.AbstractDSLTestSupport +import net.nemerosa.ontrack.json.asJson +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import java.time.Duration +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertNull + +class DatabaseWorkflowInstanceStoreIT : AbstractDSLTestSupport() { + + @Autowired + private lateinit var databaseWorkflowInstanceStore: DatabaseWorkflowInstanceStore + + @Test + fun `Saving and retrieving one workflow instance from a database`() { + val instance = createInstance( + workflow = WorkflowFixtures.simpleLinearWorkflow(), + context = WorkflowContext( + key = "mock", + value = mapOf("text" to "Some text").asJson() + ) + ) + databaseWorkflowInstanceStore.store(instance) + + assertNotNull(databaseWorkflowInstanceStore.findById(instance.id)) { saved -> + assertEquals(instance.asJson(), saved.asJson()) + } + } + + @Test + fun `Cleaning of workflow instances`() { + asAdmin { + withCleanSettings { + // Retention period to one day + settingsManagerService.saveSettings( + WorkflowSettings( + retentionDuration = Duration.ofDays(1).toMillis(), + ) + ) + // Removing all previous instances for the test + databaseWorkflowInstanceStore.clearAll() + // Reference time + val now = Time.now + // Saving an instance two days ago + val old = WorkflowInstanceFixtures.simpleLinear( + timestamp = now - Duration.ofDays(2) + ) + databaseWorkflowInstanceStore.store(old) + // Saving an instance now + val recent = WorkflowInstanceFixtures.simpleLinear( + timestamp = now + ) + databaseWorkflowInstanceStore.store(recent) + // Launching the cleanup + databaseWorkflowInstanceStore.cleanup() + // Only the most recent instance is present + assertNull(databaseWorkflowInstanceStore.findById(old.id), "Old instance is gone") + assertNotNull(databaseWorkflowInstanceStore.findById(recent.id), "Recent instance has been kept") + } + } + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextTest.kt new file mode 100644 index 00000000000..74a5035aaf2 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowContextTest.kt @@ -0,0 +1,31 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import net.nemerosa.ontrack.json.asJson +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class WorkflowContextTest { + + @Test + fun `Json representation`() { + val context = WorkflowContext( + key = "mock", + value = mapOf("text" to "Some text").asJson() + ) + val json = context.asJson() + assertEquals( + mapOf( + "data" to listOf( + mapOf( + "key" to "mock", + "value" to mapOf( + "text" to "Some text" + ) + ) + ) + ).asJson(), + json + ) + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineIT.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineIT.kt new file mode 100644 index 00000000000..ddf0bd61e1e --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowEngineIT.kt @@ -0,0 +1,284 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.node.TextNode +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowFixtures +import net.nemerosa.ontrack.extension.workflows.mock.MockWorkflowNodeExecutor +import net.nemerosa.ontrack.extension.workflows.AbstractWorkflowTestSupport +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidationException +import net.nemerosa.ontrack.it.waitUntil +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.time.Duration.Companion.seconds +import kotlin.time.ExperimentalTime + +class WorkflowEngineIT : AbstractWorkflowTestSupport() { + + @Autowired + private lateinit var workflowEngine: WorkflowEngine + + @Autowired + private lateinit var mockWorkflowNodeExecutor: MockWorkflowNodeExecutor + + @OptIn(ExperimentalTime::class) + @Test + fun `Simple linear workflow`() { + // Defining a workflow + val workflow = WorkflowFixtures.simpleLinearWorkflow() + // Running the workflow + val instance = workflowEngine.startWorkflow(workflow, WorkflowContext("mock", TextNode("Linear"))) + // Waiting until the workflow is completed (error or success) + waitUntil("Waiting until workflow is complete", timeout = 10.seconds) { + val workflowInstance = workflowEngine.getWorkflowInstance(instance.id) + println("workflowInstance = $workflowInstance") + workflowInstance.status.finished + } + // Checks the results + val texts = mockWorkflowNodeExecutor.getTextsByInstanceId(instance.id) + assertEquals( + listOf( + "Processed: Start node for Linear", + "Processed: End node for Linear", + ), + texts + ) + } + + @Test + fun `Launching a workflow with an error`() { + // Defining a workflow + val workflow = WorkflowFixtures.cyclicWorkflow() + // Running the workflow + assertFailsWith { + workflowEngine.startWorkflow(workflow, WorkflowContext("mock", TextNode("Cyclic"))) + } + } + + @OptIn(ExperimentalTime::class) + @Test + fun `Parallel with join`() { + // Defining a workflow + val workflow = WorkflowFixtures.twoParallelAndJoin() + // Running the workflow + val instance = workflowEngine.startWorkflow(workflow, WorkflowContext("mock", TextNode("Parallel / Join"))) + // Waiting until the workflow is completed (error or success) + waitUntil("Waiting until workflow is complete", timeout = 10.seconds) { + val workflowInstance = workflowEngine.getWorkflowInstance(instance.id) + println("workflowInstance = $workflowInstance") + workflowInstance.status.finished + } + // Checks the results + val texts = mockWorkflowNodeExecutor.getTextsByInstanceId(instance.id) + assertEquals( + setOf( + "Processed: Start node A for Parallel / Join", + "Processed: Start node B for Parallel / Join", + "Processed: End node for Parallel / Join", + ), + texts.toSet() + ) + } + + @Test + fun `Complex workflow with waiting times`() { + // Defining a workflow using YAML + val yaml = """ + name: Complex workflow with waiting times + nodes: + - id: start + executorId: mock + data: + text: Starting + waitMs: 500 + - id: parallel-a + executorId: mock + data: + text: Parallel A + waitMs: 500 + parents: + - id: start + - id: parallel-b + executorId: mock + data: + text: Parallel B + waitMs: 2000 + parents: + - id: start + - id: end + executorId: mock + data: + text: End + parents: + - id: parallel-a + - id: parallel-b + """.trimIndent() + // Registering the workflow, launching it & waiting for its completion + val instanceId = workflowTestSupport.registerLaunchAndWaitForWorkflow(yaml, "Complex") + // Checks the results + val texts = mockWorkflowNodeExecutor.getTextsByInstanceId(instanceId) + assertEquals( + setOf( + "Processed: Starting for Complex", + "Processed: Parallel A for Complex", + "Processed: Parallel B for Complex", + "Processed: End for Complex", + ), + texts.toSet() + ) + } + + @Test + fun `Complex workflow with reusing parent outputs`() { + // Defining a workflow using YAML + val yaml = """ + name: Complex workflow with waiting times + nodes: + - id: start + executorId: mock + data: + text: Starting + waitMs: 500 + - id: parallel-a + executorId: mock + data: + text: Parallel A + waitMs: 500 + parents: + - id: start + - id: parallel-b + executorId: mock + data: + text: Parallel B + waitMs: 2000 + parents: + - id: start + - id: end + executorId: mock + data: + text: End of (#parallel-a) and (#parallel-b) + parents: + - id: parallel-a + - id: parallel-b + """.trimIndent() + // Registering the workflow, launching it & waiting for its completion + val instanceId = workflowTestSupport.registerLaunchAndWaitForWorkflow(yaml, "Complex") + // Checks the results + val texts = mockWorkflowNodeExecutor.getTextsByInstanceId(instanceId) + assertEquals( + setOf( + "Processed: Starting for Complex", + "Processed: Parallel A for Complex", + "Processed: Parallel B for Complex", + "Processed: End of (Processed: Parallel A for Complex) and (Processed: Parallel B for Complex) for Complex", + ), + texts.toSet() + ) + } + + @Test + fun `Asymetric workflow`() { + // Defining a workflow using YAML + val yaml = """ + name: Complex workflow with waiting times + nodes: + - id: start + executorId: mock + data: + text: Starting + waitMs: 500 + - id: parallel-a-1 + executorId: mock + data: + text: Parallel A1 + waitMs: 1000 + parents: + - id: start + - id: parallel-a-2 + executorId: mock + data: + text: Parallel A2 + waitMs: 1000 + parents: + - id: parallel-a-1 + - id: parallel-b + executorId: mock + data: + text: Parallel B + waitMs: 500 + parents: + - id: start + - id: end + executorId: mock + data: + text: End + parents: + - id: parallel-a-2 + - id: parallel-b + """.trimIndent() + // Registering the workflow, launching it & waiting for its completion + val instanceId = workflowTestSupport.registerLaunchAndWaitForWorkflow(yaml, "Complex") + // Checks the results + val texts = mockWorkflowNodeExecutor.getTextsByInstanceId(instanceId) + assertEquals( + setOf( + "Processed: Starting for Complex", + "Processed: Parallel A1 for Complex", + "Processed: Parallel A2 for Complex", + "Processed: Parallel B for Complex", + "Processed: End for Complex", + ), + texts.toSet() + ) + } + + /** + * Testing a workflow looking like: + * + * ``` + * s + * |\ + * | p + * |/ + * e + * ``` + */ + @Test + fun `SPE workflow`() { + // Defining a workflow using YAML + val yaml = """ + name: SPE workflow + nodes: + - id: start + executorId: mock + data: + text: Start + - id: parallel + executorId: mock + data: + text: Parallel + parents: + - id: start + - id: end + executorId: mock + data: + text: End + parents: + - id: start + - id: parallel + """.trimIndent() + // Registering the workflow, launching it & waiting for its completion + val instanceId = workflowTestSupport.registerLaunchAndWaitForWorkflow(yaml, "SPE") + // Checks the results + val texts = mockWorkflowNodeExecutor.getTextsByInstanceId(instanceId) + assertEquals( + setOf( + "Processed: Start for SPE", + "Processed: Parallel for SPE", + "Processed: End for SPE", + ), + texts.toSet() + ) + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceFixtures.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceFixtures.kt new file mode 100644 index 00000000000..dba196b08e0 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceFixtures.kt @@ -0,0 +1,22 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.node.NullNode +import net.nemerosa.ontrack.common.Time +import net.nemerosa.ontrack.extension.workflows.WorkflowsExtensionFeature +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowFixtures +import net.nemerosa.ontrack.extension.workflows.mock.MockWorkflowNodeExecutor +import java.time.LocalDateTime + +object WorkflowInstanceFixtures { + + fun simpleLinear( + timestamp: LocalDateTime = Time.now(), + ): WorkflowInstance { + val workflow = WorkflowFixtures.simpleLinearWorkflow() + return createInstance( + workflow = workflow, + context = WorkflowContext.noContext(), + timestamp = timestamp, + ) + } +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNodeTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNodeTest.kt new file mode 100644 index 00000000000..f7c5ee6dbc5 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceNodeTest.kt @@ -0,0 +1,23 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.node.TextNode +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class WorkflowInstanceNodeTest { + + @Test + fun `Success node`() { + val node = WorkflowInstanceNode( + id = "node", + status = WorkflowInstanceNodeStatus.STARTED, + output = null, + error = null, + ) + val next = node.success(TextNode("test")) + assertEquals(node.id, next.id) + assertEquals(WorkflowInstanceNodeStatus.SUCCESS, next.status) + assertEquals("test", next.output?.asText()) + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceTest.kt new file mode 100644 index 00000000000..8e6ddaf407d --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/engine/WorkflowInstanceTest.kt @@ -0,0 +1,19 @@ +package net.nemerosa.ontrack.extension.workflows.engine + +import com.fasterxml.jackson.databind.node.TextNode +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class WorkflowInstanceTest { + + @Test + fun `Success node`() { + val workflowInstance = WorkflowInstanceFixtures.simpleLinear() + val next = workflowInstance.successNode("start", TextNode("Processing")) + assertEquals(workflowInstance.id, next.id) + assertEquals(workflowInstance.workflow, next.workflow) + val output = next.nodesExecutions.find { it.id == "start" }?.output + assertEquals("Processing", output?.asText()) + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstancesIT.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstancesIT.kt new file mode 100644 index 00000000000..a64fcc8c8a4 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowInstancesIT.kt @@ -0,0 +1,44 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceFixtures +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstanceStore +import net.nemerosa.ontrack.graphql.AbstractQLKTITSupport +import net.nemerosa.ontrack.json.getRequiredTextField +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import kotlin.test.assertEquals + +class GQLRootQueryWorkflowInstancesIT : AbstractQLKTITSupport() { + + @Autowired + private lateinit var workflowInstanceStore: WorkflowInstanceStore + + @Test + fun `Getting a list of workflow instances using the GraphQL API`() { + asAdmin { + workflowInstanceStore.clearAll() + + val instance = WorkflowInstanceFixtures.simpleLinear() + workflowInstanceStore.store(instance) + + run( + """{ + workflowInstances { + pageItems { + id + } + } + }""" + ) { data -> + val ids = data.path("workflowInstances") + .path("pageItems") + .map { it.getRequiredTextField("id") } + assertEquals( + listOf(instance.id), + ids + ) + } + } + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowNodeExecutorsIT.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowNodeExecutorsIT.kt new file mode 100644 index 00000000000..575ddd39e61 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/GQLRootQueryWorkflowNodeExecutorsIT.kt @@ -0,0 +1,33 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import net.nemerosa.ontrack.graphql.AbstractQLKTITSupport +import net.nemerosa.ontrack.json.getRequiredTextField +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +class GQLRootQueryWorkflowNodeExecutorsIT : AbstractQLKTITSupport() { + + @Test + fun `Getting the list of executors`() { + asAdmin { + run( + """ + { + workflowNodeExecutors { + id + displayName + } + } + """ + ) { data -> + assertNotNull( + data.path("workflowNodeExecutors").find { it.getRequiredTextField("id") == "notification" } + ) { + assertEquals("Notification", it.getRequiredTextField("displayName")) + } + } + } + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/WorkflowsMutationsIT.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/WorkflowsMutationsIT.kt new file mode 100644 index 00000000000..6a1291001a8 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/graphql/WorkflowsMutationsIT.kt @@ -0,0 +1,190 @@ +package net.nemerosa.ontrack.extension.workflows.graphql + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.extension.workflows.AbstractWorkflowTestSupport +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.json.getRequiredBooleanField +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class WorkflowsMutationsIT : AbstractWorkflowTestSupport() { + + @Test + fun `No cycles`() { + val json = mapOf( + "name" to "Cycles", + "nodes" to listOf( + mapOf( + "id" to "start", + "executorId" to "mock", + "data" to mapOf( + "text" to "Start" + ), + "parents" to listOf( + mapOf("id" to "end") + ) + ), + mapOf( + "id" to "middle", + "executorId" to "mock", + "data" to mapOf( + "text" to "Middle" + ), + "parents" to listOf( + mapOf("id" to "start") + ) + ), + mapOf( + "id" to "end", + "executorId" to "mock", + "data" to mapOf( + "text" to "End" + ), + "parents" to listOf( + mapOf("id" to "middle") + ) + ), + ) + ).asJson() + + asAdmin { + run( + """ + mutation Validate(${'$'}workflow: JSON!) { + validateJsonWorkflow(input: { + workflow: ${'$'}workflow, + }) { + errors { + message + } + validation { + error + errors + } + } + } + """, + mapOf("workflow" to json) + ) { data -> + checkGraphQLUserErrors(data, "validateJsonWorkflow") { node -> + val validation = node.path("validation") + assertTrue(validation.getRequiredBooleanField("error")) + assertEquals( + "The workflow contains at least one cycle.", + validation.path("errors").path(0).asText() + ) + } + } + } + } + + @Test + fun `No error`() { + val json = mapOf( + "name" to "No error", + "nodes" to listOf( + mapOf( + "id" to "start", + "executorId" to "mock", + "data" to mapOf( + "text" to "Start" + ), + "parents" to emptyList() + ), + mapOf( + "id" to "middle", + "executorId" to "mock", + "data" to mapOf( + "text" to "Middle" + ), + "parents" to listOf( + mapOf("id" to "start") + ) + ), + mapOf( + "id" to "end", + "executorId" to "mock", + "data" to mapOf( + "text" to "End" + ), + "parents" to listOf( + mapOf("id" to "middle") + ) + ), + ) + ).asJson() + + asAdmin { + run( + """ + mutation Validate(${'$'}workflow: JSON!) { + validateJsonWorkflow(input: { + workflow: ${'$'}workflow, + }) { + errors { + message + } + validation { + error + errors + } + } + } + """, + mapOf("workflow" to json) + ) { data -> + checkGraphQLUserErrors(data, "validateJsonWorkflow") { node -> + val validation = node.path("validation") + assertFalse(validation.getRequiredBooleanField("error")) + assertTrue( + validation.path("errors").isEmpty, + "No error message" + ) + } + } + } + } + +// @Test +// fun `No error`() { +// val json = mapOf( +// "name" to "No error", +// "nodes" to listOf( +// mapOf( +// "id" to "start", +// "executorId" to "mock", +// "data" to mapOf( +// "text" to "Start" +// ), +// "parents" to emptyList() +// ), +// mapOf( +// "id" to "middle", +// "executorId" to "mock", +// "data" to mapOf( +// "text" to "Middle" +// ), +// "parents" to listOf( +// mapOf("id" to "start") +// ) +// ), +// mapOf( +// "id" to "end", +// "executorId" to "mock", +// "data" to mapOf( +// "text" to "End" +// ), +// "parents" to listOf( +// mapOf("id" to "middle") +// ) +// ), +// ) +// ).asJson() +// val validation = workflowRegistry.validateJsonWorkflow(json) +// assertFalse(validation.error) +// assertTrue(validation.errors.isEmpty()) +// } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeExecutorIT.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeExecutorIT.kt new file mode 100644 index 00000000000..952496ee7c7 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelNodeExecutorIT.kt @@ -0,0 +1,66 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import net.nemerosa.ontrack.extension.notifications.mock.MockNotificationChannel +import net.nemerosa.ontrack.extension.workflows.AbstractWorkflowTestSupport +import net.nemerosa.ontrack.model.events.EventFactory +import net.nemerosa.ontrack.test.TestUtils.uid +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import kotlin.test.assertEquals + +class WorkflowNotificationChannelNodeExecutorIT : AbstractWorkflowTestSupport() { + + @Autowired + private lateinit var mockNotificationChannel: MockNotificationChannel + + @Autowired + private lateinit var eventFactory: EventFactory + + @Test + fun `Notifications in a workflow can reuse the output of the parent nodes in their templates`() { + val targetTicket = uid("t-") + val ticketData = uid("PRJ-") + val targetMail = uid("m-") + val yaml = """ + name: Notifications in a workflow can reuse the output of the parent nodes in their templates + nodes: + - id: ticket-creation + executorId: notification + data: + channel: mock + channelConfig: + target: $targetTicket + data: $ticketData + template: Creating the ticket + - id: mail + executorId: notification + parents: + - id: ticket-creation + data: + channel: mock + channelConfig: + target: $targetMail + template: | + Ticket created: ${'$'}{workflow.ticket-creation?path=data} + """.trimIndent() + + project { + + val event = eventFactory.newProject(this) + + // Registering the workflow, launching it & waiting for its completion + workflowTestSupport.registerLaunchAndWaitForWorkflow(yaml, event = event, display = true) + // Checks all messages have been recorded + assertEquals( + listOf("Creating the ticket"), + mockNotificationChannel.targetMessages(targetTicket) + ) + assertEquals( + listOf("Ticket created: $ticketData"), + mockNotificationChannel.targetMessages(targetMail) + ) + + } + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelTest.kt new file mode 100644 index 00000000000..4edcf081ca7 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/notifications/WorkflowNotificationChannelTest.kt @@ -0,0 +1,102 @@ +package net.nemerosa.ontrack.extension.workflows.notifications + +import com.fasterxml.jackson.databind.node.NullNode +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import net.nemerosa.ontrack.extension.notifications.queue.NotificationQueueItem +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowNode +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowEngine +import net.nemerosa.ontrack.extension.workflows.engine.WorkflowInstance +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.model.events.Event +import net.nemerosa.ontrack.model.events.EventTemplatingService +import net.nemerosa.ontrack.model.events.PlainEventRenderer +import org.junit.jupiter.api.Test + +class WorkflowNotificationChannelTest { + + @Test + fun `Workflow is renamed before being launched`() { + + val workflowEngine = mockk() + val workflowNotificationItemConverter = mockk() + val eventTemplatingService = mockk() + + val channel = WorkflowNotificationChannel( + workflowEngine = workflowEngine, + workflowNotificationItemConverter = workflowNotificationItemConverter, + eventTemplatingService = eventTemplatingService, + ) + + val event = mockk() + val notificationQueueItem = NotificationQueueItem( + channel = "workflow", + channelConfig = NullNode.instance, + eventType = "test", + signature = null, + entities = emptyMap(), + extraEntities = emptyMap(), + ref = null, + values = emptyMap(), + template = null, + ) + + every { + workflowNotificationItemConverter.convertForQueue(event) + } returns notificationQueueItem + + every { + eventTemplatingService.renderEvent(event, emptyMap(), "Initial name", PlainEventRenderer.INSTANCE) + } returns "New name" + + val instance = mockk() + + every { + instance.id + } returns "1" + + every { + workflowEngine.startWorkflow(any(), any()) + } returns instance + + channel.publish( + config = WorkflowNotificationChannelConfig( + workflow = Workflow( + name = "Initial name", + nodes = listOf( + WorkflowNode( + id = "start", + executorId = "mock", + data = mapOf("text" to "Test").asJson(), + parents = emptyList() + ) + ) + ) + ), + event = event, + context = emptyMap(), + template = null, + outputProgressCallback = { it }, + ) + + verify { + workflowEngine.startWorkflow( + workflow = Workflow( + name = "New name", + nodes = listOf( + WorkflowNode( + id = "start", + executorId = "mock", + data = mapOf("text" to "Test").asJson(), + parents = emptyList() + ) + ) + ), + context = any() + ) + } + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParserTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParserTest.kt new file mode 100644 index 00000000000..6eda0af2830 --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowParserTest.kt @@ -0,0 +1,73 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import net.nemerosa.ontrack.extension.workflows.definition.Workflow +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowNode +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowParentNode +import net.nemerosa.ontrack.json.asJson +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class WorkflowParserTest { + + @Test + fun `Parsing of YAML`() { + val yaml = """ + name: Notifications in a workflow can reuse the output of the parent nodes in their templates + nodes: + - id: ticket-creation + executorId: notification + data: + channel: mock + channelConfig: + target: PPP + data: XXX + template: Creating the ticket + - id: mail + executorId: notification + parents: + - id: ticket-creation + data: + channel: mock + channelConfig: + target: QQQ + template: | + Ticket created: ${'$'}{workflow.ticket-creation?path=data} + """.trimIndent() + val workflow = WorkflowParser.parseYamlWorkflow(yaml) + assertEquals( + Workflow( + name = "Notifications in a workflow can reuse the output of the parent nodes in their templates", + nodes = listOf( + WorkflowNode( + id = "ticket-creation", + executorId = "notification", + data = mapOf( + "channel" to "mock", + "channelConfig" to mapOf( + "target" to "PPP", + "data" to "XXX", + ), + "template" to "Creating the ticket" + ).asJson(), + ), + WorkflowNode( + id = "mail", + parents = listOf( + WorkflowParentNode(id = "ticket-creation"), + ), + executorId = "notification", + data = mapOf( + "channel" to "mock", + "channelConfig" to mapOf( + "target" to "QQQ", + ), + "template" to "Ticket created: \${workflow.ticket-creation?path=data}" + ).asJson(), + ), + ) + ), + workflow + ) + } + +} \ No newline at end of file diff --git a/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistryImplTest.kt b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistryImplTest.kt new file mode 100644 index 00000000000..173f566b90a --- /dev/null +++ b/ontrack-extension-workflows/src/test/java/net/nemerosa/ontrack/extension/workflows/registry/WorkflowRegistryImplTest.kt @@ -0,0 +1,187 @@ +package net.nemerosa.ontrack.extension.workflows.registry + +import com.fasterxml.jackson.databind.JsonNode +import io.mockk.mockk +import net.nemerosa.ontrack.extension.workflows.definition.WorkflowValidationException +import net.nemerosa.ontrack.it.MockSecurityService +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.model.support.StorageService +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class WorkflowRegistryImplTest { + + private lateinit var storageService: StorageService + private lateinit var workflowRegistry: WorkflowRegistry + + @BeforeEach + fun setUp() { + storageService = mockk() + val securityService = MockSecurityService() + workflowRegistry = WorkflowRegistryImpl(storageService, securityService) + } + + @Test + fun `Validation on saving a Yaml workflow`() { + val yaml = """ + name: Sample + nodes: + - id: start + executorId: mock + data: + text: Start + parents: + - id: end + - id: end + executorId: mock + data: + text: End + parents: + - id: start + """.trimIndent() + assertFailsWith( + message = "Validation of the workflow returned the following errors:\n" + + "* The workflow contains at least one cycle." + ) { + workflowRegistry.saveYamlWorkflow(yaml) + } + } + + @Test + fun `Parsing error on validation`() { + val json = mapOf( + // Missing name + "nodes" to listOf( + mapOf( + "id" to "start", + "executorId" to "mock", + "data" to mapOf( + "text" to "Test" + ), + "parents" to emptyList() + ) + ) + ).asJson() + val validation = workflowRegistry.validateJsonWorkflow(json) + assertTrue(validation.error) + assertEquals(validation.errors.firstOrNull(), "Cannot parse workflow") + } + + @Test + fun `Name is required`() { + val json = mapOf( + "name" to " ", + "nodes" to listOf( + mapOf( + "id" to "start", + "executorId" to "mock", + "data" to mapOf( + "text" to "Test" + ), + "parents" to emptyList() + ) + ) + ).asJson() + val validation = workflowRegistry.validateJsonWorkflow(json) + assertTrue(validation.error) + assertEquals(validation.errors.firstOrNull(), "Workflow name is required.") + } + + @Test + fun `At least one node is required`() { + val json = mapOf( + "name" to "Some name", + "nodes" to emptyList() + ).asJson() + val validation = workflowRegistry.validateJsonWorkflow(json) + assertTrue(validation.error) + assertEquals(validation.errors.firstOrNull(), "At least one node is required.") + } + + @Test + fun `No cycles`() { + val json = mapOf( + "name" to "Cycles", + "nodes" to listOf( + mapOf( + "id" to "start", + "executorId" to "mock", + "data" to mapOf( + "text" to "Start" + ), + "parents" to listOf( + mapOf("id" to "end") + ) + ), + mapOf( + "id" to "middle", + "executorId" to "mock", + "data" to mapOf( + "text" to "Middle" + ), + "parents" to listOf( + mapOf("id" to "start") + ) + ), + mapOf( + "id" to "end", + "executorId" to "mock", + "data" to mapOf( + "text" to "End" + ), + "parents" to listOf( + mapOf("id" to "middle") + ) + ), + ) + ).asJson() + val validation = workflowRegistry.validateJsonWorkflow(json) + assertTrue(validation.error) + assertEquals(validation.errors.firstOrNull(), "The workflow contains at least one cycle.") + } + + @Test + fun `No error`() { + val json = mapOf( + "name" to "No error", + "nodes" to listOf( + mapOf( + "id" to "start", + "executorId" to "mock", + "data" to mapOf( + "text" to "Start" + ), + "parents" to emptyList() + ), + mapOf( + "id" to "middle", + "executorId" to "mock", + "data" to mapOf( + "text" to "Middle" + ), + "parents" to listOf( + mapOf("id" to "start") + ) + ), + mapOf( + "id" to "end", + "executorId" to "mock", + "data" to mapOf( + "text" to "End" + ), + "parents" to listOf( + mapOf("id" to "middle") + ) + ), + ) + ).asJson() + val validation = workflowRegistry.validateJsonWorkflow(json) + assertFalse(validation.error) + assertTrue(validation.errors.isEmpty()) + } + +} \ No newline at end of file diff --git a/ontrack-it-utils/src/main/java/net/nemerosa/ontrack/it/TimeTestUtils.kt b/ontrack-it-utils/src/main/java/net/nemerosa/ontrack/it/TimeTestUtils.kt index 63d4966e25a..a0c6b68d555 100644 --- a/ontrack-it-utils/src/main/java/net/nemerosa/ontrack/it/TimeTestUtils.kt +++ b/ontrack-it-utils/src/main/java/net/nemerosa/ontrack/it/TimeTestUtils.kt @@ -4,6 +4,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import net.nemerosa.ontrack.common.seconds import org.slf4j.LoggerFactory +import java.util.concurrent.TimeoutException import kotlin.time.Duration import kotlin.time.ExperimentalTime @@ -76,7 +77,7 @@ class TimeTestUtils { } } // Timeout - throw IllegalStateException("$message: Timeout exceeded after $timeout") + throw TimeoutException("$message: Timeout exceeded after $timeout") } } diff --git a/ontrack-json/build.gradle.kts b/ontrack-json/build.gradle.kts index e65f9f630fd..67f5c9fa21b 100644 --- a/ontrack-json/build.gradle.kts +++ b/ontrack-json/build.gradle.kts @@ -9,5 +9,6 @@ dependencies { implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") + implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") implementation("org.apache.commons:commons-lang3") } diff --git a/ontrack-json/src/main/java/net/nemerosa/ontrack/json/JsonPathUtils.kt b/ontrack-json/src/main/java/net/nemerosa/ontrack/json/JsonPathUtils.kt new file mode 100644 index 00000000000..386fc095bf1 --- /dev/null +++ b/ontrack-json/src/main/java/net/nemerosa/ontrack/json/JsonPathUtils.kt @@ -0,0 +1,18 @@ +package net.nemerosa.ontrack.json + +import com.fasterxml.jackson.databind.JsonNode + +object JsonPathUtils { + + fun get(root: JsonNode, path: String): JsonNode? = + if (path.isBlank()) { + null + } else if (path == ".") { + root + } else { + path.split('.').fold(root) { current, key -> + current.get(key) ?: return null + } + } + +} \ No newline at end of file diff --git a/ontrack-json/src/main/java/net/nemerosa/ontrack/yaml/Yaml.kt b/ontrack-json/src/main/java/net/nemerosa/ontrack/yaml/Yaml.kt new file mode 100644 index 00000000000..bb8d191b95e --- /dev/null +++ b/ontrack-json/src/main/java/net/nemerosa/ontrack/yaml/Yaml.kt @@ -0,0 +1,41 @@ +package net.nemerosa.ontrack.yaml + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ObjectNode +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory +import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator +import com.fasterxml.jackson.module.kotlin.KotlinModule +import com.fasterxml.jackson.module.kotlin.readValues +import java.io.StringWriter + +class Yaml { + + private val yamlFactory = YAMLFactory().apply { + enable(YAMLGenerator.Feature.LITERAL_BLOCK_STYLE) + } + + private val mapper = ObjectMapper(yamlFactory).apply { + registerModule(KotlinModule.Builder().build()) + } + + /** + * Reads some Yaml as a list of documents + */ + fun read(content: String): List { + val parser = yamlFactory.createParser(content) + return mapper + .readValues(parser) + .readAll() + } + + fun write(json: List): String { + val writer = StringWriter() + json.forEach { + val generator = yamlFactory.createGenerator(writer) + generator.writeObject(it) + writer.append('\n') + } + return writer.toString() + } + +} \ No newline at end of file diff --git a/ontrack-json/src/test/java/net/nemerosa/ontrack/json/JsonPathUtilsTest.kt b/ontrack-json/src/test/java/net/nemerosa/ontrack/json/JsonPathUtilsTest.kt new file mode 100644 index 00000000000..88fd8b2b334 --- /dev/null +++ b/ontrack-json/src/test/java/net/nemerosa/ontrack/json/JsonPathUtilsTest.kt @@ -0,0 +1,55 @@ +package net.nemerosa.ontrack.json + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertNull +import kotlin.test.assertTrue + +class JsonPathUtilsTest { + + @Test + fun `Getting null on blank`() { + val json = mapOf( + "name" to "Test" + ).asJson() + val node = JsonPathUtils.get(json, "") + assertNull(node) + } + + @Test + fun `Getting the root`() { + val json = mapOf( + "name" to "Test" + ).asJson() + val node = JsonPathUtils.get(json, ".") + assertEquals(json, node) + } + + @Test + fun `Getting a field`() { + val json = mapOf( + "name" to "Test" + ).asJson() + val node = JsonPathUtils.get(json, "name") + assertNotNull(node) { + assertTrue(it.isTextual) + assertEquals("Test", it.asText()) + } + } + + @Test + fun `Getting a path`() { + val json = mapOf( + "person" to mapOf( + "age" to 24 + ) + ).asJson() + val node = JsonPathUtils.get(json, "person.age") + assertNotNull(node) { + assertTrue(it.isInt) + assertEquals(24, it.asInt()) + } + } + +} \ No newline at end of file diff --git a/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/ACCDSLWorkflowNotificationChannel.kt b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/ACCDSLWorkflowNotificationChannel.kt new file mode 100644 index 00000000000..8a2526fb7e2 --- /dev/null +++ b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/ACCDSLWorkflowNotificationChannel.kt @@ -0,0 +1,96 @@ +package net.nemerosa.ontrack.kdsl.acceptance.tests.workflows + +import net.nemerosa.ontrack.kdsl.acceptance.tests.support.uid +import net.nemerosa.ontrack.kdsl.acceptance.tests.support.waitUntil +import net.nemerosa.ontrack.kdsl.spec.extension.notifications.notifications +import org.junit.jupiter.api.Test +import kotlin.test.fail + +class ACCDSLWorkflowNotificationChannel : AbstractACCDSLWorkflowsTestSupport() { + + @Test + fun `Notifications reusing their parent output`() { + // Defining a workflow + val prefixGroupName = uid("w-") + val yaml = """ + name: $prefixGroupName + nodes: + - id: start + executorId: notification + data: + channel: in-memory + channelConfig: + group: "start-$prefixGroupName" + data: PRJ-123 + template: | + Message for project ${'$'}{project} + - id: end + executorId: notification + data: + channel: in-memory + channelConfig: + group: "end-$prefixGroupName" + template: | + Message for ${'$'}{workflow.start?path=data} in project ${'$'}{project} + parents: + - id: start + """.trimIndent() + + project { + // Subscribe to new branches + subscribe( + channel = "workflow", + channelConfig = mapOf( + "workflow" to WorkflowTestSupport.yamlWorkflowToJson(yaml) + ), + keywords = null, + events = listOf( + "new_branch", + ), + ) + // Creating a branch to trigger the workflow + branch {} + + // Gets the workflow instance ID from the output of the notification + + fun getWorkflowInstanceId() = ontrack.notifications.notificationRecordsOutputs("workflow") + .firstOrNull() + ?.output + ?.path("workflowInstanceId") + ?.asText() + + waitUntil( + timeout = 30_000, + interval = 500L, + ) { + val instanceId = getWorkflowInstanceId() + instanceId.isNullOrBlank().not() + } + + // Getting the instance ID + val instanceId = getWorkflowInstanceId() ?: fail("Cannot get the workflow instance ID") + + // Waits until the workflow is finished + waitUntilWorkflowFinished(instanceId = instanceId) + + // We expect the messages + + waitUntil( + timeout = 30_000, + interval = 500L, + ) { + val message = ontrack.notifications.inMemory.group("start-$prefixGroupName").firstOrNull() + message?.trim() == "Message for project $name" + } + + waitUntil( + timeout = 30_000, + interval = 500L, + ) { + val message = ontrack.notifications.inMemory.group("end-$prefixGroupName").firstOrNull() + message?.trim() == "Message for PRJ-123 in project $name" + } + } + } + +} \ No newline at end of file diff --git a/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/ACCDSLWorkflows.kt b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/ACCDSLWorkflows.kt new file mode 100644 index 00000000000..cced4393ae7 --- /dev/null +++ b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/ACCDSLWorkflows.kt @@ -0,0 +1,315 @@ +package net.nemerosa.ontrack.kdsl.acceptance.tests.workflows + +import net.nemerosa.ontrack.json.asJson +import net.nemerosa.ontrack.kdsl.acceptance.tests.AbstractACCDSLTestSupport +import net.nemerosa.ontrack.kdsl.acceptance.tests.support.uid +import net.nemerosa.ontrack.kdsl.acceptance.tests.support.waitUntil +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.WorkflowInstanceNodeStatus +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.WorkflowInstanceStatus +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.mock.mock +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.workflows +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals +import kotlin.test.fail + +class ACCDSLWorkflows : AbstractACCDSLWorkflowsTestSupport() { + + @Test + fun `Simple linear workflow`() { + // Defining a workflow + val name = uid("w-") + val workflow = """ + name: $name + nodes: + - id: start + executorId: mock + data: "Start node" + - id: end + executorId: mock + data: "End node" + parents: + - id: start + """.trimIndent() + // Saving the workflow + val workflowId = ontrack.workflows.saveYamlWorkflow( + workflow = workflow, + ) ?: fail("Error while saving workflow") + // Running the workflow + val instanceId = ontrack.workflows.launchWorkflow( + workflowId = workflowId, + context = "mock" to mapOf("text" to "Linear").asJson(), + ) ?: fail("Error while launching workflow") + // Waiting for the workflow result + waitUntilWorkflowFinished(instanceId) + // Checks the outcome of the workflow run + val texts = ontrack.workflows.mock.getTexts(instanceId) + assertEquals( + listOf( + "Processed: Start node for Linear", + "Processed: End node for Linear", + ), + texts + ) + } + + @Test + fun `Parallel with join workflow`() { + // Defining a workflow + val name = uid("w-") + val workflow = """ + name: $name + nodes: + - id: start-a + executorId: mock + data: "Start node A" + - id: start-b + executorId: mock + data: "Start node B" + - id: end + executorId: mock + data: "End node" + parents: + - id: start-a + - id: start-b + """.trimIndent() + // Saving the workflow + val workflowId = ontrack.workflows.saveYamlWorkflow( + workflow = workflow, + ) ?: fail("Error while saving workflow") + // Running the workflow + val instanceId = ontrack.workflows.launchWorkflow( + workflowId = workflowId, + context = "mock" to mapOf("text" to "Parallel / Join").asJson(), + ) ?: fail("Error while launching workflow") + // Waiting for the workflow result + waitUntilWorkflowFinished(instanceId) + // Checks the outcome of the workflow run + val texts = ontrack.workflows.mock.getTexts(instanceId) + assertEquals( + setOf( + "Processed: Start node A for Parallel / Join", + "Processed: Start node B for Parallel / Join", + "Processed: End node for Parallel / Join", + ), + texts.toSet() + ) + } + + @Test + fun `Complex workflow with waiting times`() { + // Defining a workflow + val name = uid("w-") + val workflow = """ + name: $name + nodes: + - id: start + executorId: mock + data: + text: Starting + waitMs: 500 + - id: parallel-a + executorId: mock + data: + text: Parallel A + waitMs: 500 + parents: + - id: start + - id: parallel-b + executorId: mock + data: + text: Parallel B + waitMs: 2000 + parents: + - id: start + - id: end + executorId: mock + data: + text: End + parents: + - id: parallel-a + - id: parallel-b + """.trimIndent() + // Saving the workflow + val workflowId = ontrack.workflows.saveYamlWorkflow( + workflow = workflow, + ) ?: fail("Error while saving workflow") + // Running the workflow + val instanceId = ontrack.workflows.launchWorkflow( + workflowId = workflowId, + context = "mock" to mapOf("text" to "Complex").asJson(), + ) ?: fail("Error while launching workflow") + // Waiting for the workflow result + waitUntilWorkflowFinished(instanceId) + // Checks the outcome of the workflow run + val texts = ontrack.workflows.mock.getTexts(instanceId) + assertEquals( + setOf( + "Processed: Starting for Complex", + "Processed: Parallel A for Complex", + "Processed: Parallel B for Complex", + "Processed: End for Complex", + ), + texts.toSet() + ) + } + + @Test + fun `Asymetric workflow`() { + // Defining a workflow + val name = uid("w-") + val workflow = """ + name: $name + nodes: + - id: start + executorId: mock + data: + text: Starting + waitMs: 500 + - id: parallel-a-1 + executorId: mock + data: + text: Parallel A1 + waitMs: 1000 + parents: + - id: start + - id: parallel-b + executorId: mock + data: + text: Parallel B + waitMs: 500 + parents: + - id: start + - id: parallel-a-2 + executorId: mock + data: + text: Parallel A2 + waitMs: 1000 + parents: + - id: parallel-a-1 + - id: end + executorId: mock + data: + text: End + parents: + - id: parallel-a-2 + - id: parallel-b + """.trimIndent() + // Saving the workflow + val workflowId = ontrack.workflows.saveYamlWorkflow( + workflow = workflow, + ) ?: fail("Error while saving workflow") + // Running the workflow + val instanceId = ontrack.workflows.launchWorkflow( + workflowId = workflowId, + context = "mock" to mapOf("text" to "Complex").asJson(), + ) ?: fail("Error while launching workflow") + // Waiting for the workflow result + waitUntilWorkflowFinished(instanceId) + // Checks the outcome of the workflow run + val texts = ontrack.workflows.mock.getTexts(instanceId) + assertEquals( + setOf( + "Processed: Starting for Complex", + "Processed: Parallel A1 for Complex", + "Processed: Parallel A2 for Complex", + "Processed: Parallel B for Complex", + "Processed: End for Complex", + ), + texts.toSet() + ) + } + + @Test + fun `SPE workflow`() { + // Defining a workflow + val name = uid("w-") + val workflow = """ + name: SPE $name workflow + nodes: + - id: start + executorId: mock + data: + text: Start + - id: end + executorId: mock + data: + text: End + parents: + - id: start + - id: parallel + - id: parallel + executorId: mock + data: + text: Parallel + parents: + - id: start + """.trimIndent() + // Saving the workflow + val workflowId = ontrack.workflows.saveYamlWorkflow( + workflow = workflow, + ) ?: fail("Error while saving workflow") + // Running the workflow + val instanceId = ontrack.workflows.launchWorkflow( + workflowId = workflowId, + context = "mock" to mapOf("text" to "SPE").asJson(), + ) ?: fail("Error while launching workflow") + // Waiting for the workflow result + waitUntilWorkflowFinished(instanceId) + // Checks the outcome of the workflow run + val texts = ontrack.workflows.mock.getTexts(instanceId) + assertEquals( + setOf( + "Processed: Start for SPE", + "Processed: Parallel for SPE", + "Processed: End for SPE", + ), + texts.toSet() + ) + } + + @Test + fun `Error in workflow`() { + + // Defining a workflow + val name = uid("w-") + val workflow = """ + name: $name + nodes: + - id: start + executorId: mock + data: + text: Start + - id: end + executorId: mock + data: + text: End + error: true + parents: + - id: start + """.trimIndent() + // Saving the workflow + val workflowId = ontrack.workflows.saveYamlWorkflow( + workflow = workflow, + ) ?: fail("Error while saving workflow") + // Running the workflow + val instanceId = ontrack.workflows.launchWorkflow( + workflowId = workflowId, + context = "mock" to mapOf("text" to "Error test").asJson(), + ) ?: fail("Error while launching workflow") + // Waiting for the workflow result + val instance = waitUntilWorkflowFinished(instanceId, returnInstanceOnError = true) + // Checks the errors + val nodeInError = instance.nodesExecutions.find { it.id == "end" } + ?: fail("Cannot find the end node") + // Checking the error + assertEquals( + WorkflowInstanceNodeStatus.ERROR, + nodeInError.status + ) + assertEquals( + "Error in end node", + nodeInError.error + ) + } + +} \ No newline at end of file diff --git a/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/AbstractACCDSLWorkflowsTestSupport.kt b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/AbstractACCDSLWorkflowsTestSupport.kt new file mode 100644 index 00000000000..27c1160bae8 --- /dev/null +++ b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/AbstractACCDSLWorkflowsTestSupport.kt @@ -0,0 +1,41 @@ +package net.nemerosa.ontrack.kdsl.acceptance.tests.workflows + +import net.nemerosa.ontrack.kdsl.acceptance.tests.notifications.AbstractACCDSLNotificationsTestSupport +import net.nemerosa.ontrack.kdsl.acceptance.tests.support.waitUntil +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.WorkflowInstance +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.WorkflowInstanceStatus +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.workflows +import kotlin.test.fail + +abstract class AbstractACCDSLWorkflowsTestSupport : AbstractACCDSLNotificationsTestSupport() { + + protected fun waitUntilWorkflowFinished( + instanceId: String, + returnInstanceOnError: Boolean = false, + ): WorkflowInstance { + waitUntil( + timeout = 30_000L, + interval = 500L, + ) { + val instance = ontrack.workflows.workflowInstance(instanceId) + instance != null && instance.finished + } + // Getting the final errors + val instance = ontrack.workflows.workflowInstance(instanceId) + ?: fail("Could not get the workflow instance") + if (!returnInstanceOnError && instance.status == WorkflowInstanceStatus.ERROR) { + // Displaying the errors + instance.nodesExecutions.forEach { node -> + println("Node: ${node.id}") + println(" Status: ${node.status}") + println(" Output: ${node.output}") + println(" Error: ${node.error}") + } + // Failing + fail("Workflow failed in error. See errors above.") + } + // OK, returning the final state of the instance + return instance + } + +} \ No newline at end of file diff --git a/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/WorkflowTestSupport.kt b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/WorkflowTestSupport.kt new file mode 100644 index 00000000000..0a16c14efa3 --- /dev/null +++ b/ontrack-kdsl-acceptance/src/test/java/net/nemerosa/ontrack/kdsl/acceptance/tests/workflows/WorkflowTestSupport.kt @@ -0,0 +1,17 @@ +package net.nemerosa.ontrack.kdsl.acceptance.tests.workflows + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.yaml.Yaml +import kotlin.test.fail + +object WorkflowTestSupport { + + /** + * Utility method to convert a workflow defined as YAML + * into a JSON object usable in notification workflows + */ + fun yamlWorkflowToJson(yaml: String): JsonNode = + Yaml().read(yaml).firstOrNull() + ?: fail("Cannot parse YAML") + +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/LaunchWorkflow.graphql b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/LaunchWorkflow.graphql new file mode 100644 index 00000000000..da0724c3d47 --- /dev/null +++ b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/LaunchWorkflow.graphql @@ -0,0 +1,12 @@ +mutation LaunchWorkflow( + $workflowId: String!, + $context: [LaunchWorkflowInputContext!]!, +) { + launchWorkflow(input: { + workflowId: $workflowId, + context: $context, + }) { + ...PayloadUserErrors + workflowInstanceId + } +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/MockWorkflowTexts.graphql b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/MockWorkflowTexts.graphql new file mode 100644 index 00000000000..ce2f83fd700 --- /dev/null +++ b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/MockWorkflowTexts.graphql @@ -0,0 +1,3 @@ +query MockWorkflowTexts($instanceId: String!) { + mockWorkflowTexts(instanceId: $instanceId) +} diff --git a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/NotificationRecordsOutputs.graphql b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/NotificationRecordsOutputs.graphql new file mode 100644 index 00000000000..a446b2099ff --- /dev/null +++ b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/NotificationRecordsOutputs.graphql @@ -0,0 +1,13 @@ +query NotificationRecordsOutputs( + $channel: String, +) { + notificationRecords(channel: $channel) { + pageItems { + result { + type + message + output + } + } + } +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/SaveYamlWorkflow.graphql b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/SaveYamlWorkflow.graphql new file mode 100644 index 00000000000..eacd2a8abbe --- /dev/null +++ b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/SaveYamlWorkflow.graphql @@ -0,0 +1,10 @@ +mutation SaveYamlWorkflow( + $workflow: String!, +) { + saveYamlWorkflow(input: { + workflow: $workflow, + }) { + ...PayloadUserErrors + workflowId + } +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/WorkflowInstance.graphql b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/WorkflowInstance.graphql new file mode 100644 index 00000000000..452213937c0 --- /dev/null +++ b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/WorkflowInstance.graphql @@ -0,0 +1,14 @@ +query WorkflowInstance( + $workflowInstanceId: String!, +) { + workflowInstance(id: $workflowInstanceId) { + status + finished + nodesExecutions { + id + status + output + error + } + } +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/schema.json b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/schema.json index 54f7b422d42..e91c6db7844 100644 --- a/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/schema.json +++ b/ontrack-kdsl/src/main/graphql/net/nemerosa/ontrack/kdsl/connector/graphql/schema/schema.json @@ -800,6 +800,11 @@ "name": "Build", "ofType": null }, + { + "kind": "OBJECT", + "name": "Project", + "ofType": null + }, { "kind": "OBJECT", "name": "PromotionLevel", @@ -15460,6 +15465,49 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "EventType", + "description": "EventType", + "fields": [ + { + "name": "id", + "description": "id field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": "description field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "ExportFormat", @@ -22459,6 +22507,239 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "JiraConfiguration", + "description": "Jira configuration", + "fields": [ + { + "name": "name", + "description": "Name of the configuration", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "url", + "description": "URL of Jira", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "user", + "description": "Username used to connect", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "include", + "description": "List of projects to include", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "exclude", + "description": "List of projects to exclude", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobActionResult", + "description": null, + "fields": [ + { + "name": "ok", + "description": "Result", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "error", + "description": "Error message", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobCategory", + "description": "JobCategory", + "fields": [ + { + "name": "key", + "description": "key field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "name field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "types", + "description": "All job types for this category", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobType" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobExecutionStatus", + "description": null, + "fields": [ + { + "name": "paused", + "description": "All jobs are paused", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "JobIngestionConfigValidation", @@ -22510,6 +22791,676 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "JobKey", + "description": "JobKey", + "fields": [ + { + "name": "id", + "description": "id field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "type field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobType", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobRunProgress", + "description": "JobRunProgress", + "fields": [ + { + "name": "percentage", + "description": "percentage field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "message", + "description": "message field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "text", + "description": "text field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "JobState", + "description": "Global state of a job", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "IDLE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "RUNNING", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "PAUSED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DISABLED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "INVALID", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobStateInfo", + "description": "Job state information", + "fields": [ + { + "name": "name", + "description": "Name of the state", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "displayName", + "description": "displayName field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": "description field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobStatus", + "description": "JobStatus", + "fields": [ + { + "name": "id", + "description": "id field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "key", + "description": "key field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobKey", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "schedule", + "description": "schedule field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Schedule", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "actualSchedule", + "description": "actualSchedule field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Schedule", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": "description field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isRunning", + "description": "isRunning field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isValid", + "description": "isValid field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isPaused", + "description": "isPaused field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isDisabled", + "description": "isDisabled field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progress", + "description": "progress field", + "args": [], + "type": { + "kind": "OBJECT", + "name": "JobRunProgress", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "progressText", + "description": "progressText field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "runCount", + "description": "runCount field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lastRunDate", + "description": "lastRunDate field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "LocalDateTime", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lastRunDurationMs", + "description": "lastRunDurationMs field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nextRunDate", + "description": "nextRunDate field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "LocalDateTime", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lastErrorCount", + "description": "lastErrorCount field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lastTimeoutCount", + "description": "lastTimeoutCount field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lastError", + "description": "lastError field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "state", + "description": "state field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "JobState", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isError", + "description": "isError field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "isTimeout", + "description": "isTimeout field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "canRun", + "description": "Checks if the job can be run", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "canPause", + "description": "Checks if the job can be paused", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "canResume", + "description": "Checks if the job can be resumed", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "canBeDeleted", + "description": "Checks if the job can be deleted", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "canBeStopped", + "description": "Checks if the job can be stopped", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobStatusPaginated", + "description": null, + "fields": [ + { + "name": "pageInfo", + "description": "Information about the current page", + "args": [], + "type": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageItems", + "description": "Items in the current page", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobStatus" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "JobType", + "description": "JobType", + "fields": [ + { + "name": "key", + "description": "key field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "name field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "category", + "description": "category field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobCategory", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "Label", @@ -22722,6 +23673,136 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "LaunchWorkflowInput", + "description": "Input type for the launchWorkflow mutation.", + "fields": null, + "inputFields": [ + { + "name": "context", + "description": "context field", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "LaunchWorkflowInputContext" + } + } + } + }, + "defaultValue": null + }, + { + "name": "workflowId", + "description": "workflowId field", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "LaunchWorkflowInputContext", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "key", + "description": "key field", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "value", + "description": "value field", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "LaunchWorkflowPayload", + "description": "Output type for the launchWorkflow mutation.", + "fields": [ + { + "name": "workflowInstanceId", + "description": "Workflow instance ID", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "List of errors", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "UserError", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Payload", + "ofType": null + } + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "LinkBuildByIdInput", @@ -23600,6 +24681,193 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "launchJob", + "description": "Launches a job", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pauseJob", + "description": "Pauses a job", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "resumeJob", + "description": "Resumes a job", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "stopJob", + "description": "Stops a job", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "deleteJob", + "description": "Deletes a job", + "args": [ + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pauseAllJobs", + "description": "Pausing the execution of all jobs", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "resumeAllJobs", + "description": "Resuming the execution of all jobs", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobActionResult", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createBranch", "description": "Creates a new branch", @@ -24221,6 +25489,29 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "reorderPromotionLevelById", + "description": "Reordering the promotion levels in a branch", + "args": [ + { + "name": "input", + "description": "Input for the mutation", + "type": { + "kind": "INPUT_OBJECT", + "name": "ReorderPromotionLevelByIdInput", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ReorderPromotionLevelByIdPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "createPromotionRun", "description": "Creating a promotion run for a build identified by its name", @@ -28419,6 +29710,111 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "saveYamlWorkflow", + "description": "Saves a workflow which is defined as YAML", + "args": [ + { + "name": "input", + "description": "Input for the mutation", + "type": { + "kind": "INPUT_OBJECT", + "name": "SaveYamlWorkflowInput", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "SaveYamlWorkflowPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "launchWorkflow", + "description": "Launches an existing workflow", + "args": [ + { + "name": "input", + "description": "Input for the mutation", + "type": { + "kind": "INPUT_OBJECT", + "name": "LaunchWorkflowInput", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "LaunchWorkflowPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "postQueue", + "description": "Post a message on a queue", + "args": [ + { + "name": "input", + "description": "Input for the mutation", + "type": { + "kind": "INPUT_OBJECT", + "name": "PostQueueInput", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PostQueuePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "purgeHookRecordings", + "description": "Purging all records for Hook messages", + "args": [], + "type": { + "kind": "OBJECT", + "name": "PurgeHookRecordingsPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "purgeQueueRecordings", + "description": "Purging all records for Queue messages", + "args": [], + "type": { + "kind": "OBJECT", + "name": "PurgeQueueRecordingsPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "reloadCasc", + "description": "Reload the configuration from the CasC files", + "args": [], + "type": { + "kind": "OBJECT", + "name": "ReloadCascPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deleteNotificationRecords", "description": "Deleting notification records", @@ -28741,65 +30137,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "postQueue", - "description": "Post a message on a queue", - "args": [ - { - "name": "input", - "description": "Input for the mutation", - "type": { - "kind": "INPUT_OBJECT", - "name": "PostQueueInput", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "PostQueuePayload", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "purgeHookRecordings", - "description": "Purging all records for Hook messages", - "args": [], - "type": { - "kind": "OBJECT", - "name": "PurgeHookRecordingsPayload", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "purgeQueueRecordings", - "description": "Purging all records for Queue messages", - "args": [], - "type": { - "kind": "OBJECT", - "name": "PurgeQueueRecordingsPayload", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "reloadCasc", - "description": "Reload the configuration from the CasC files", - "args": [], - "type": { - "kind": "OBJECT", - "name": "ReloadCascPayload", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "shareSCMFileChangeFilter", "description": "Shares or updates a filter at project level", @@ -28895,11 +30232,66 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "NotificationChannel", + "description": "Notification channel", + "fields": [ + { + "name": "type", + "description": "type field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "enabled", + "description": "enabled field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "NotificationRecord", "description": "Notification record", "fields": [ + { + "name": "id", + "description": "Record unique ID", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "timestamp", "description": "Record timestamp", @@ -28969,7 +30361,7 @@ "name": null, "ofType": { "kind": "OBJECT", - "name": "NotificationResult", + "name": "NotificationRecordResult", "ofType": null } }, @@ -29030,7 +30422,7 @@ }, { "kind": "OBJECT", - "name": "NotificationResult", + "name": "NotificationRecordResult", "description": "Result for a notification", "fields": [ { @@ -29050,8 +30442,8 @@ "deprecationReason": null }, { - "name": "id", - "description": "Optional ID for the message into the channel", + "name": "message", + "description": "Result message", "args": [], "type": { "kind": "SCALAR", @@ -29062,12 +30454,12 @@ "deprecationReason": null }, { - "name": "message", - "description": "Result message", + "name": "output", + "description": "Output of the channel", "args": [], "type": { "kind": "SCALAR", - "name": "String", + "name": "JSON", "ofType": null }, "isDeprecated": false, @@ -29931,6 +31323,11 @@ "name": "GitHubIngestionValidateDataByRunIdPayload", "ofType": null }, + { + "kind": "OBJECT", + "name": "LaunchWorkflowPayload", + "ofType": null + }, { "kind": "OBJECT", "name": "LinkBuildByIdPayload", @@ -29971,6 +31368,11 @@ "name": "ReloadCascPayload", "ofType": null }, + { + "kind": "OBJECT", + "name": "ReorderPromotionLevelByIdPayload", + "ofType": null + }, { "kind": "OBJECT", "name": "RevokeAccountTokensPayload", @@ -29991,6 +31393,11 @@ "name": "SaveBuildFilterPayload", "ofType": null }, + { + "kind": "OBJECT", + "name": "SaveYamlWorkflowPayload", + "ofType": null + }, { "kind": "OBJECT", "name": "SetAutoVersioningConfigByNamePayload", @@ -31603,6 +33010,29 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "authorizations", + "description": "Authorizations for this context", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Authorization" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "favourite", "description": "Is this project a favourite of the current user?", @@ -31782,6 +33212,11 @@ "kind": "INTERFACE", "name": "ProjectEntity", "ofType": null + }, + { + "kind": "INTERFACE", + "name": "Authorizable", + "ofType": null } ], "enumValues": null, @@ -35049,6 +36484,18 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "jobExecutionStatus", + "description": "Overall status of the execution of the jobs", + "args": [], + "type": { + "kind": "OBJECT", + "name": "JobExecutionStatus", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "templatingRenderers", "description": "Getting the list of template renderers", @@ -35095,6 +36542,83 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "jenkinsConfiguration", + "description": "Getting a Jenkins configuration by name", + "args": [ + { + "name": "name", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "JenkinsConfiguration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "jiraConfigurations", + "description": "List of Jira configurations", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JiraConfiguration" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "jiraConfiguration", + "description": "Getting a Jira configuration by name", + "args": [ + { + "name": "name", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "JiraConfiguration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "notificationSettings", "description": "Notification settings", @@ -35561,6 +37085,29 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "eventTypes", + "description": "List of all event types", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EventType" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "info", "description": "Gets information about the application", @@ -35721,6 +37268,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "project", + "description": null, + "args": [ + { + "name": "id", + "description": "ID of the project to look for (required)", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "Project", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "projects", "description": null, @@ -36299,6 +37873,145 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "jobCategories", + "description": "List of all job categories and their types (at any given time)", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobCategory" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "jobStateInfos", + "description": "List of job states", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "JobStateInfo" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "jobs", + "description": "List of background jobs", + "args": [ + { + "name": "offset", + "description": "Offset for the page", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": "0" + }, + { + "name": "size", + "description": "Size of the page", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": "20" + }, + { + "name": "description", + "description": "Part of the description of the job", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "state", + "description": "State of the job", + "type": { + "kind": "ENUM", + "name": "JobState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "error", + "description": "Jobs on error", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "timeout", + "description": "Jobs with timeout", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "category", + "description": "Category key", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": "Type key", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "JobStatusPaginated", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "globalMessages", "description": "List of global messages", @@ -36781,6 +38494,320 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "hookRecordFilterInfo", + "description": "Information for the hook record query filter", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "HookRecordFilterInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "workflowInstance", + "description": "Gets an existing workflow instance using its ID", + "args": [ + { + "name": "id", + "description": "ID of the workflow instance", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "WorkflowInstance", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "workflowInstances", + "description": "List of workflow instances", + "args": [ + { + "name": "offset", + "description": "Offset for the page", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": "0" + }, + { + "name": "size", + "description": "Size of the page", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": "20" + } + ], + "type": { + "kind": "OBJECT", + "name": "WorkflowInstancePaginated", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "mockWorkflowTexts", + "description": "Getting a list of texts generated for a mock workflow", + "args": [ + { + "name": "instanceId", + "description": "ID of the workflow instance", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "queueRecordFilterInfo", + "description": "Information for the queue record query filter", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "QueueRecordFilterInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "casc", + "description": "Configuration as Code", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CasC", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "configurableIndicators", + "description": "List of configurable indicators", + "args": [ + { + "name": "category", + "description": "Filter the indicators on their category ID", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": "Filter the indicators on their type ID", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "ConfigurableIndicatorTypeState" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "indicatorCategories", + "description": "List of indicator categories", + "args": [], + "type": { + "kind": "OBJECT", + "name": "IndicatorCategories", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "indicatorPortfolioOfPortfolios", + "description": "List of all portfolios", + "args": [], + "type": { + "kind": "OBJECT", + "name": "IndicatorPortfolioOfPortfolios", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "indicatorPortfolios", + "description": "List of indicator portfolios", + "args": [ + { + "name": "id", + "description": "ID of the indicator portfolio", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "IndicatorPortfolio" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "indicatorTypes", + "description": "List of indicator types", + "args": [], + "type": { + "kind": "OBJECT", + "name": "IndicatorTypes", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "indicatorViewList", + "description": "List of indicator views.", + "args": [], + "type": { + "kind": "OBJECT", + "name": "IndicatorViewList", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "getChart", + "description": "Getting data for a chart", + "args": [ + { + "name": "input", + "description": "Parameters for getting the chart", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "GetChartInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "notificationChannels", + "description": "List of all notification channels", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "NotificationChannel" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "notificationRecords", "description": "Access to the notification recordings", @@ -36805,6 +38832,16 @@ }, "defaultValue": "20" }, + { + "name": "channel", + "description": "Filtering on the channel", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, { "name": "resultType", "description": "Filtering on the result type", @@ -36901,207 +38938,6 @@ "isDeprecated": false, "deprecationReason": null }, - { - "name": "hookRecordFilterInfo", - "description": "Information for the hook record query filter", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "HookRecordFilterInfo", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "queueRecordFilterInfo", - "description": "Information for the queue record query filter", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "QueueRecordFilterInfo", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "casc", - "description": "Configuration as Code", - "args": [], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "CasC", - "ofType": null - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "configurableIndicators", - "description": "List of configurable indicators", - "args": [ - { - "name": "category", - "description": "Filter the indicators on their category ID", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "type", - "description": "Filter the indicators on their type ID", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "ConfigurableIndicatorTypeState" - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indicatorCategories", - "description": "List of indicator categories", - "args": [], - "type": { - "kind": "OBJECT", - "name": "IndicatorCategories", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indicatorPortfolioOfPortfolios", - "description": "List of all portfolios", - "args": [], - "type": { - "kind": "OBJECT", - "name": "IndicatorPortfolioOfPortfolios", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indicatorPortfolios", - "description": "List of indicator portfolios", - "args": [ - { - "name": "id", - "description": "ID of the indicator portfolio", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - } - ], - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "IndicatorPortfolio" - } - } - } - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indicatorTypes", - "description": "List of indicator types", - "args": [], - "type": { - "kind": "OBJECT", - "name": "IndicatorTypes", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "indicatorViewList", - "description": "List of indicator views.", - "args": [], - "type": { - "kind": "OBJECT", - "name": "IndicatorViewList", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "getChart", - "description": "Getting data for a chart", - "args": [ - { - "name": "input", - "description": "Parameters for getting the chart", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "GetChartInput", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "SCALAR", - "name": "JSON", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, { "name": "scmCatalog", "description": "List of SCM catalog entries and/or orphan projects", @@ -38182,6 +40018,92 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "ReorderPromotionLevelByIdInput", + "description": "Input type for the reorderPromotionLevelById mutation.", + "fields": null, + "inputFields": [ + { + "name": "branchId", + "description": "Branch ID", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "newName", + "description": "New name to swap", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "oldName", + "description": "Old name to swap", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ReorderPromotionLevelByIdPayload", + "description": "Output type for the reorderPromotionLevelById mutation.", + "fields": [ + { + "name": "errors", + "description": "List of errors", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "UserError", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Payload", + "ofType": null + } + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "INPUT_OBJECT", "name": "RevokeAccountTokensInput", @@ -39899,6 +41821,151 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "SaveYamlWorkflowInput", + "description": "Input type for the saveYamlWorkflow mutation.", + "fields": null, + "inputFields": [ + { + "name": "workflow", + "description": "workflow field", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "SaveYamlWorkflowPayload", + "description": "Output type for the saveYamlWorkflow mutation.", + "fields": [ + { + "name": "workflowId", + "description": "Saved workflow ID", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "List of errors", + "args": [], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "UserError", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Payload", + "ofType": null + } + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "Schedule", + "description": "Schedule", + "fields": [ + { + "name": "initialPeriod", + "description": "initialPeriod field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "period", + "description": "period field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "unit", + "description": "unit field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "cron", + "description": "cron field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "periodText", + "description": "periodText field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, { "kind": "OBJECT", "name": "SearchResult", @@ -56777,6 +58844,271 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "OBJECT", + "name": "WorkflowInstance", + "description": "Running workflow instance", + "fields": [ + { + "name": "id", + "description": "id field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": "status field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "WorkflowInstanceStatus", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "finished", + "description": "Is the workflow finished?", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodesExecutions", + "description": "List of node statuses in the workflow", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowInstanceNode" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowInstanceNode", + "description": "Status of a node execution in a workflow", + "fields": [ + { + "name": "id", + "description": "id field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "status", + "description": "status field", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "WorkflowInstanceNodeStatus", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "output", + "description": "output field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "error", + "description": "error field", + "args": [], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "WorkflowInstanceNodeStatus", + "description": "Status of a node in a workflow", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "IDLE", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "STARTED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ERROR", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SUCCESS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "WorkflowInstancePaginated", + "description": null, + "fields": [ + { + "name": "pageInfo", + "description": "Information about the current page", + "args": [], + "type": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageItems", + "description": "Items in the current page", + "args": [], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "WorkflowInstance" + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "WorkflowInstanceStatus", + "description": "Status of a running workflow", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "STARTED", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "RUNNING", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ERROR", + "description": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SUCCESS", + "description": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, { "kind": "OBJECT", "name": "__Directive", diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationRecordOutput.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationRecordOutput.kt new file mode 100644 index 00000000000..366a85d8ddd --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationRecordOutput.kt @@ -0,0 +1,9 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.notifications + +import com.fasterxml.jackson.databind.JsonNode + +data class NotificationRecordOutput( + val type: String, + val message: String?, + val output: JsonNode?, +) diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationsMgt.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationsMgt.kt index 9ae6546eecf..ed0ed64c4d3 100644 --- a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationsMgt.kt +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/notifications/NotificationsMgt.kt @@ -5,6 +5,7 @@ import net.nemerosa.ontrack.json.asJson import net.nemerosa.ontrack.kdsl.connector.Connected import net.nemerosa.ontrack.kdsl.connector.Connector import net.nemerosa.ontrack.kdsl.connector.graphql.convert +import net.nemerosa.ontrack.kdsl.connector.graphql.schema.NotificationRecordsOutputsQuery import net.nemerosa.ontrack.kdsl.connector.graphql.schema.SubscribeToEntityEventsMutation import net.nemerosa.ontrack.kdsl.connector.graphqlConnector import net.nemerosa.ontrack.kdsl.spec.ProjectEntity @@ -58,5 +59,22 @@ class NotificationsMgt(connector: Connector) : Connected(connector) { InMemoryMgt(connector) } + /** + * Gets the last notification record outputs for a given channel + */ + fun notificationRecordsOutputs(channel: String?): List { + return graphqlConnector.query( + NotificationRecordsOutputsQuery(Input.fromNullable(channel)) + )?.notificationRecords()?.pageItems() + ?.map { it.result() } + ?.map { + NotificationRecordOutput( + type = it.type().name, + message = it.message(), + output = it.output(), + ) + } ?: emptyList() + } + } \ No newline at end of file diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstance.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstance.kt new file mode 100644 index 00000000000..e6ff4390c5a --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstance.kt @@ -0,0 +1,7 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows + +data class WorkflowInstance( + val status: WorkflowInstanceStatus, + val finished: Boolean, + val nodesExecutions: List, +) diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceNode.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceNode.kt new file mode 100644 index 00000000000..ac016b09a92 --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceNode.kt @@ -0,0 +1,10 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows + +import com.fasterxml.jackson.databind.JsonNode + +data class WorkflowInstanceNode( + val id: String, + val status: WorkflowInstanceNodeStatus, + val output: JsonNode?, + val error: String?, +) diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceNodeStatus.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceNodeStatus.kt new file mode 100644 index 00000000000..1793bcf3be5 --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceNodeStatus.kt @@ -0,0 +1,10 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows + +enum class WorkflowInstanceNodeStatus { + + IDLE, + STARTED, + ERROR, + SUCCESS, + +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceStatus.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceStatus.kt new file mode 100644 index 00000000000..e36a44d7db9 --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowInstanceStatus.kt @@ -0,0 +1,10 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows + +enum class WorkflowInstanceStatus { + + STARTED, + RUNNING, + ERROR, + SUCCESS, + +} \ No newline at end of file diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowsMgt.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowsMgt.kt new file mode 100644 index 00000000000..6d47b466d23 --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowsMgt.kt @@ -0,0 +1,61 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows + +import com.fasterxml.jackson.databind.JsonNode +import net.nemerosa.ontrack.kdsl.connector.Connected +import net.nemerosa.ontrack.kdsl.connector.Connector +import net.nemerosa.ontrack.kdsl.connector.graphql.convert +import net.nemerosa.ontrack.kdsl.connector.graphql.schema.LaunchWorkflowMutation +import net.nemerosa.ontrack.kdsl.connector.graphql.schema.SaveYamlWorkflowMutation +import net.nemerosa.ontrack.kdsl.connector.graphql.schema.WorkflowInstanceQuery +import net.nemerosa.ontrack.kdsl.connector.graphql.schema.type.LaunchWorkflowInputContext +import net.nemerosa.ontrack.kdsl.connector.graphqlConnector + +class WorkflowsMgt(connector: Connector) : Connected(connector) { + + fun saveYamlWorkflow(workflow: String): String? = + graphqlConnector.mutate( + SaveYamlWorkflowMutation(workflow) + ) { + it?.saveYamlWorkflow()?.fragments()?.payloadUserErrors()?.convert() + }?.saveYamlWorkflow()?.workflowId() + + fun launchWorkflow(workflowId: String, context: Pair): String? { + val (key, value) = context + return graphqlConnector.mutate( + LaunchWorkflowMutation( + workflowId, listOf( + LaunchWorkflowInputContext.builder() + .key(key) + .value(value) + .build() + ) + ) + ) { + it?.launchWorkflow()?.fragments()?.payloadUserErrors()?.convert() + }?.launchWorkflow()?.workflowInstanceId() + } + + fun workflowInstance(instanceId: String): WorkflowInstance? { + return graphqlConnector.query( + WorkflowInstanceQuery(instanceId) + )?.workflowInstance()?.run { + WorkflowInstance( + status = status().run { + WorkflowInstanceStatus.valueOf(toString()) + }, + finished = finished(), + nodesExecutions = nodesExecutions().map { + WorkflowInstanceNode( + id = it.id(), + status = it.status().run { + WorkflowInstanceNodeStatus.valueOf(toString()) + }, + output = it.output(), + error = it.error(), + ) + } + ) + } + } + +} diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowsOntrackExtensions.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowsOntrackExtensions.kt new file mode 100644 index 00000000000..cd9ba75159f --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/WorkflowsOntrackExtensions.kt @@ -0,0 +1,8 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows + +import net.nemerosa.ontrack.kdsl.spec.Ontrack + +/** + * Management of workflows in Ontrack. + */ +val Ontrack.workflows: WorkflowsMgt get() = WorkflowsMgt(connector) \ No newline at end of file diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/mock/MockWorkflowsExtensions.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/mock/MockWorkflowsExtensions.kt new file mode 100644 index 00000000000..3848d5a5759 --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/mock/MockWorkflowsExtensions.kt @@ -0,0 +1,5 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows.mock + +import net.nemerosa.ontrack.kdsl.spec.extension.workflows.WorkflowsMgt + +val WorkflowsMgt.mock: MockWorkflowsMgt get() = MockWorkflowsMgt(connector) diff --git a/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/mock/MockWorkflowsMgt.kt b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/mock/MockWorkflowsMgt.kt new file mode 100644 index 00000000000..5a6981ab271 --- /dev/null +++ b/ontrack-kdsl/src/main/java/net/nemerosa/ontrack/kdsl/spec/extension/workflows/mock/MockWorkflowsMgt.kt @@ -0,0 +1,14 @@ +package net.nemerosa.ontrack.kdsl.spec.extension.workflows.mock + +import net.nemerosa.ontrack.kdsl.connector.Connected +import net.nemerosa.ontrack.kdsl.connector.Connector +import net.nemerosa.ontrack.kdsl.connector.graphql.schema.MockWorkflowTextsQuery +import net.nemerosa.ontrack.kdsl.connector.graphqlConnector + +class MockWorkflowsMgt(connector: Connector) : Connected(connector) { + fun getTexts(instanceId: String): List { + return graphqlConnector.query( + MockWorkflowTextsQuery(instanceId) + )?.mockWorkflowTexts() ?: emptyList() + } +} \ No newline at end of file diff --git a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventTemplatingService.kt b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventTemplatingService.kt index 739bb699f44..077b5e028a8 100644 --- a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventTemplatingService.kt +++ b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventTemplatingService.kt @@ -10,12 +10,14 @@ interface EventTemplatingService { * * @param template Content of the template * @param event Event context + * @param context Initial context * @param renderer Target renderer * @return Rendered template */ fun render( template: String, event: Event, + context: Map, renderer: EventRenderer, ): String @@ -23,12 +25,14 @@ interface EventTemplatingService { * Renders an event with its default message or alternatively another template * * @param event Event to render + * @param context Initial context * @param template Content of the alternative template * @param renderer Target renderer * @return Rendered template */ fun renderEvent( event: Event, + context: Map, template: String? = null, renderer: EventRenderer = PlainEventRenderer.INSTANCE, ): String diff --git a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventVariableService.kt b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventVariableService.kt index 44c25bdd22f..cd0308a0248 100644 --- a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventVariableService.kt +++ b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/events/EventVariableService.kt @@ -23,7 +23,8 @@ interface EventVariableService { * Gets a map containing all the entities and values for this event. * * @param event Event for which to get the parameters + * @param context Initial context */ - fun getTemplateContext(event: Event): Map + fun getTemplateContext(event: Event, context: Map): Map } \ No newline at end of file diff --git a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/settings/AbstractSettingsManager.java b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/settings/AbstractSettingsManager.java index 3d6304e4602..8ec6a507681 100644 --- a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/settings/AbstractSettingsManager.java +++ b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/settings/AbstractSettingsManager.java @@ -36,6 +36,10 @@ public final void saveSettings(T settings) { protected abstract void doSaveSettings(T settings); + /** + * @deprecated Will be removed in V5. Settings form are managed in Next UI. + */ + @Deprecated protected abstract Form getSettingsForm(T settings); @Override diff --git a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/DefaultTransactionHelper.kt b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/DefaultTransactionHelper.kt new file mode 100644 index 00000000000..cdca439486d --- /dev/null +++ b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/DefaultTransactionHelper.kt @@ -0,0 +1,24 @@ +package net.nemerosa.ontrack.model.tx + +import net.nemerosa.ontrack.common.RunProfile +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Component +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.TransactionDefinition +import org.springframework.transaction.support.TransactionTemplate + +@Component +@Profile("!${RunProfile.UNIT_TEST}") +class DefaultTransactionHelper( + private val platformTransactionManager: PlatformTransactionManager, +) : TransactionHelper { + + override fun inNewTransaction(code: () -> T): T { + val transactionTemplate = TransactionTemplate(platformTransactionManager) + transactionTemplate.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW + return transactionTemplate.execute { + code() + } ?: error("Unexpected transaction result: null") + } + +} diff --git a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/PassThroughTransactionHelper.kt b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/PassThroughTransactionHelper.kt new file mode 100644 index 00000000000..fa943e715a4 --- /dev/null +++ b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/PassThroughTransactionHelper.kt @@ -0,0 +1,19 @@ +package net.nemerosa.ontrack.model.tx + +import net.nemerosa.ontrack.common.RunProfile +import org.springframework.context.annotation.Profile +import org.springframework.stereotype.Component + +/** + * This implementation, used for testing only, reuses the + * current transaction and does not create a new one. + */ +@Component +@Profile(RunProfile.UNIT_TEST) +class PassThroughTransactionHelper : TransactionHelper { + + override fun inNewTransaction(code: () -> T): T { + return code() + } + +} diff --git a/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/TransactionHelper.kt b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/TransactionHelper.kt new file mode 100644 index 00000000000..90a0451107b --- /dev/null +++ b/ontrack-model/src/main/java/net/nemerosa/ontrack/model/tx/TransactionHelper.kt @@ -0,0 +1,15 @@ +package net.nemerosa.ontrack.model.tx + +/** + * This component can be used by services to create ad-hoc transactions. + */ +interface TransactionHelper { + + /** + * Runs some code into a new transaction. + * + * When running in test mode, no new transaction is created. + */ + fun inNewTransaction(code: () -> T): T + +} \ No newline at end of file diff --git a/ontrack-model/src/test/java/net/nemerosa/ontrack/model/events/MockEventTemplatingService.kt b/ontrack-model/src/test/java/net/nemerosa/ontrack/model/events/MockEventTemplatingService.kt index 00ddcb5751f..c6816afea80 100644 --- a/ontrack-model/src/test/java/net/nemerosa/ontrack/model/events/MockEventTemplatingService.kt +++ b/ontrack-model/src/test/java/net/nemerosa/ontrack/model/events/MockEventTemplatingService.kt @@ -5,11 +5,11 @@ package net.nemerosa.ontrack.model.events */ class MockEventTemplatingService : EventTemplatingService { - override fun render(template: String, event: Event, renderer: EventRenderer): String { + override fun render(template: String, event: Event, context: Map, renderer: EventRenderer): String { TODO("Not yet implemented") } - override fun renderEvent(event: Event, template: String?, renderer: EventRenderer): String = + override fun renderEvent(event: Event, context: Map, template: String?, renderer: EventRenderer): String = if (template.isNullOrBlank()) { event.eventType.template // Not rendering the template } else { diff --git a/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImpl.kt b/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImpl.kt index 708f5b07777..91384cbfd9a 100644 --- a/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImpl.kt +++ b/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImpl.kt @@ -14,19 +14,20 @@ class EventTemplatingServiceImpl( private val templatingService: TemplatingService, ) : EventTemplatingService { - override fun renderEvent(event: Event, template: String?, renderer: EventRenderer): String = + override fun renderEvent(event: Event, context: Map, template: String?, renderer: EventRenderer): String = render( template = template?.takeIf { it.isNotBlank() } ?: event.eventType.template, event = event, + context = context, renderer = renderer, ) - override fun render(template: String, event: Event, renderer: EventRenderer): String = + override fun render(template: String, event: Event, context: Map, renderer: EventRenderer): String = if (templatingService.isLegacyTemplate(template)) { val parameters = eventVariableService.getTemplateParameters(event, caseVariants = true) SimpleExpand.expand(template, parameters) } else { - val context = eventVariableService.getTemplateContext(event) + val context = eventVariableService.getTemplateContext(event, context) templatingService.render( template = template, context = context, diff --git a/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventVariableServiceImpl.kt b/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventVariableServiceImpl.kt index 9c338f3f7a4..73a17c1aa50 100644 --- a/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventVariableServiceImpl.kt +++ b/ontrack-service/src/main/java/net/nemerosa/ontrack/service/events/EventVariableServiceImpl.kt @@ -18,8 +18,8 @@ class EventVariableServiceImpl( extensionManager.getExtensions(EventParameterExtension::class.java) } - override fun getTemplateContext(event: Event): Map { - val result = mutableMapOf() + override fun getTemplateContext(event: Event, context: Map): Map { + val result = context.toMutableMap() // Entities event.entities.forEach { (type, entity) -> result[type.varName] = entity diff --git a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventFactoryIT.kt b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventFactoryIT.kt index e406facf13d..eaf696bd8ce 100644 --- a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventFactoryIT.kt +++ b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventFactoryIT.kt @@ -38,7 +38,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newProject(project) assertEquals( "New project $name.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } @@ -47,7 +47,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.updateProject(project) assertEquals( "Project $name has been updated.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } @@ -56,7 +56,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.enableProject(project) assertEquals( "Project $name has been enabled.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } @@ -65,7 +65,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.disableProject(project) assertEquals( "Project $name has been disabled.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } @@ -74,7 +74,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.deleteProject(project) assertEquals( "Project $name has been deleted.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } @@ -84,7 +84,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newBranch(this) assertEquals( "New branch $name for project ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -95,7 +95,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.updateBranch(this) assertEquals( "Branch $name in ${project.name} has been updated.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -106,7 +106,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.enableBranch(this) assertEquals( "Branch $name in ${project.name} has been enabled.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -117,7 +117,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.disableBranch(this) assertEquals( "Branch $name in ${project.name} has been disabled.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -128,7 +128,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.deleteBranch(this) assertEquals( "Branch $name has been deleted from ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -140,7 +140,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newBuild(this) assertEquals( "New build $name for branch ${branch.name} in ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -153,7 +153,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.updateBuild(this) assertEquals( "Build $name for branch ${branch.name} in ${project.name} has been updated.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -166,7 +166,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.deleteBuild(this) assertEquals( "Build $name for branch ${branch.name} in ${project.name} has been deleted.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -179,7 +179,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newPromotionLevel(this) assertEquals( "New promotion level $name for branch ${branch.name} in ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -192,7 +192,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.imagePromotionLevel(this) assertEquals( "Image for promotion level $name for branch ${branch.name} in ${project.name} has changed.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -205,7 +205,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.updatePromotionLevel(this) assertEquals( "Promotion level $name for branch ${branch.name} in ${project.name} has changed.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -218,7 +218,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.deletePromotionLevel(this) assertEquals( "Promotion level $name for branch ${branch.name} in ${project.name} has been deleted.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -230,7 +230,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.reorderPromotionLevels(this) assertEquals( "Promotion levels for branch $name in ${project.name} have been reordered.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -242,7 +242,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newValidationStamp(vs) assertEquals( "New validation stamp ${vs.name} for branch ${vs.branch.name} in ${vs.project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -254,7 +254,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.imageValidationStamp(vs) assertEquals( "Image for validation stamp ${vs.name} for branch ${vs.branch.name} in ${vs.project.name} has changed.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -266,7 +266,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.updateValidationStamp(vs) assertEquals( "Validation stamp ${vs.name} for branch ${vs.branch.name} in ${vs.project.name} has been updated.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -278,7 +278,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.deleteValidationStamp(vs) assertEquals( "Validation stamp ${vs.name} for branch ${vs.branch.name} in ${vs.project.name} has been deleted.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -289,7 +289,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.reorderValidationStamps(this) assertEquals( "Validation stamps for branch $name in ${project.name} have been reordered.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -303,7 +303,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newPromotionRun(run) assertEquals( "Build $name has been promoted to ${pl.name} for branch ${branch.name} in ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -318,7 +318,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.deletePromotionRun(run) assertEquals( "Promotion ${pl.name} of build $name has been deleted for branch ${branch.name} in ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -333,7 +333,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newValidationRun(run) assertEquals( "Build $name has run for the ${vs.name} with status ${run.lastStatus.statusID.name} in branch ${branch.name} in ${project.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -348,7 +348,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.newValidationRunStatus(run) assertEquals( "Status for the ${vs.name} validation #${run.runOrder} for build $name in branch ${branch.name} of ${project.name} has changed to ${run.lastStatus.statusID.name}.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -363,7 +363,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.updateValidationRunStatusComment(run) assertEquals( "A status message for the ${vs.name} validation #${run.runOrder} for build $name in branch ${branch.name} of ${project.name} has changed.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -375,7 +375,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.propertyChange(this, testPropertyType) assertEquals( "Configuration value property has changed for branch ${project.name}/$name.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -386,7 +386,7 @@ class EventFactoryIT : AbstractDSLTestSupport() { val event = eventFactory.propertyDelete(this, testPropertyType) assertEquals( "Configuration value property has been removed from branch ${project.name}/$name.", - eventTemplatingService.renderEvent(event) + eventTemplatingService.renderEvent(event, emptyMap()) ) } } @@ -401,21 +401,21 @@ class EventFactoryIT : AbstractDSLTestSupport() { val eventNewConfiguration = eventFactory.newConfiguration(configuration) assertEquals( "${configuration.name} configuration has been created.", - eventTemplatingService.renderEvent(eventNewConfiguration) + eventTemplatingService.renderEvent(eventNewConfiguration, emptyMap()) ) // UPDATE_CONFIGURATION val eventUpdateConfiguration = eventFactory.updateConfiguration(configuration) assertEquals( "${configuration.name} configuration has been updated.", - eventTemplatingService.renderEvent(eventUpdateConfiguration) + eventTemplatingService.renderEvent(eventUpdateConfiguration, emptyMap()) ) // DELETE_CONFIGURATION val eventDeleteConfiguration = eventFactory.deleteConfiguration(configuration) assertEquals( "${configuration.name} configuration has been deleted.", - eventTemplatingService.renderEvent(eventDeleteConfiguration) + eventTemplatingService.renderEvent(eventDeleteConfiguration, emptyMap()) ) } diff --git a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceIT.kt b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceIT.kt index 8781e68b738..d7d69ae651d 100644 --- a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceIT.kt +++ b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceIT.kt @@ -38,6 +38,7 @@ class EventTemplatingServiceIT : AbstractDSLTestSupport() { ${'$'}{promotionLevel|uppercase}. """.trimIndent(), event = event, + context = emptyMap(), renderer = PlainEventRenderer() ) @@ -78,6 +79,7 @@ class EventTemplatingServiceIT : AbstractDSLTestSupport() { {Promotion|uppercase}. """.trimIndent(), event = event, + context = emptyMap(), renderer = PlainEventRenderer() ) diff --git a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImplTest.kt b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImplTest.kt index 25279b0f1f6..52fd8f2107c 100644 --- a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImplTest.kt +++ b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventTemplatingServiceImplTest.kt @@ -26,7 +26,7 @@ class EventTemplatingServiceImplTest { @BeforeEach fun init() { eventVariableService = mockk() - every { eventVariableService.getTemplateContext(any()) } returns mapOf( + every { eventVariableService.getTemplateContext(any(), any()) } returns mapOf( "branch" to "release/1.27" ) every { eventVariableService.getTemplateParameters(any(), caseVariants = true) } returns mapOf( @@ -57,6 +57,7 @@ class EventTemplatingServiceImplTest { val event = mockk() val text = eventTemplatingService.renderEvent( event = event, + context = emptyMap(), template = "Legacy {branch} branch", renderer = PlainEventRenderer.INSTANCE, ) @@ -68,6 +69,7 @@ class EventTemplatingServiceImplTest { val event = mockk() val text = eventTemplatingService.renderEvent( event = event, + context = emptyMap(), template = "New templated ${'$'}{branch} branch", renderer = PlainEventRenderer.INSTANCE, ) diff --git a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceIT.kt b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceIT.kt index 0d71cfc99dd..9e771abbcde 100644 --- a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceIT.kt +++ b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceIT.kt @@ -29,7 +29,7 @@ class EventVariableServiceIT : AbstractDSLTestSupport() { val event = eventFactory.newPromotionRun(run) // Gets the templating context - val context = eventVariableService.getTemplateContext(event) + val context = eventVariableService.getTemplateContext(event, emptyMap()) // Checks all parameters assertEquals( @@ -62,7 +62,7 @@ class EventVariableServiceIT : AbstractDSLTestSupport() { val event = eventFactory.newValidationRun(run) // Gets the templating context - val context = eventVariableService.getTemplateContext(event) + val context = eventVariableService.getTemplateContext(event, emptyMap()) // Checks all parameters assertEquals( diff --git a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceImplTest.kt b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceImplTest.kt index e858f5f75c7..aa0b118873b 100644 --- a/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceImplTest.kt +++ b/ontrack-service/src/test/java/net/nemerosa/ontrack/service/events/EventVariableServiceImplTest.kt @@ -18,7 +18,7 @@ class EventVariableServiceImplTest { val run = ValidationRunFixtures.testValidationRun() val event = EventFactoryImpl().newValidationRun(run) // Gets the templating context - val context = eventVariableService.getTemplateContext(event) + val context = eventVariableService.getTemplateContext(event, emptyMap()) // Checks all parameters assertEquals( @@ -42,7 +42,7 @@ class EventVariableServiceImplTest { val event = Event.of(eventType) .withRef(branch) .build() - val context = eventVariableService.getTemplateContext(event) + val context = eventVariableService.getTemplateContext(event, emptyMap()) // Checks all parameters assertEquals( @@ -62,7 +62,7 @@ class EventVariableServiceImplTest { val event = Event.of(eventType) .withExtra(branch) .build() - val context = eventVariableService.getTemplateContext(event) + val context = eventVariableService.getTemplateContext(event, emptyMap()) // Checks all parameters assertEquals( diff --git a/ontrack-ui-graphql/src/main/java/net/nemerosa/ontrack/graphql/support/_GQLTypeUtils.kt b/ontrack-ui-graphql/src/main/java/net/nemerosa/ontrack/graphql/support/_GQLTypeUtils.kt index 538deeec6a7..5f96213e1db 100644 --- a/ontrack-ui-graphql/src/main/java/net/nemerosa/ontrack/graphql/support/_GQLTypeUtils.kt +++ b/ontrack-ui-graphql/src/main/java/net/nemerosa/ontrack/graphql/support/_GQLTypeUtils.kt @@ -12,6 +12,7 @@ import net.nemerosa.ontrack.model.structure.ID import net.nemerosa.ontrack.model.support.NameValue import net.nemerosa.ontrack.model.support.toNameValues import java.time.LocalDateTime +import kotlin.reflect.KClass import kotlin.reflect.KProperty import kotlin.reflect.jvm.javaType @@ -166,6 +167,23 @@ fun TypeBuilder.field( .type(outputType) } +fun TypeBuilder.listField( + property: KProperty>, + description: String? = null, +): GraphQLObjectType.Builder = + field { + val itemTypeName = (property.returnType.arguments.firstOrNull()?.type?.classifier as? KClass<*>)?.java?.simpleName + if (itemTypeName.isNullOrBlank()) error("Cannot get list item type for $property") + it.name(property.name) + .description(getPropertyDescription(property, description)) + .type( + listType( + itemTypeName = itemTypeName, + nullable = property.returnType.isMarkedNullable, + ) + ) + } + fun > TypeBuilder.enumAsStringField( property: KProperty, description: String? = null, diff --git a/ontrack-ui/build.gradle.kts b/ontrack-ui/build.gradle.kts index 73dbcf82366..a6d73f80f77 100644 --- a/ontrack-ui/build.gradle.kts +++ b/ontrack-ui/build.gradle.kts @@ -54,6 +54,7 @@ dependencies { // List of extensions needed for the documentation generation testImplementation(project(":ontrack-extension-notifications")) + testImplementation(project(":ontrack-extension-workflows")) // List of extensions to include in core runtimeOnly(project(":ontrack-extension-general")) @@ -82,8 +83,10 @@ dependencies { runtimeOnly(project(":ontrack-extension-license")) runtimeOnly(project(":ontrack-extension-tfc")) runtimeOnly(project(":ontrack-extension-recordings")) + runtimeOnly(project(":ontrack-extension-notifications")) runtimeOnly(project(":ontrack-extension-hook")) runtimeOnly(project(":ontrack-extension-queue")) + runtimeOnly(project(":ontrack-extension-workflows")) } /** diff --git a/ontrack-ui/src/main/java/net/nemerosa/ontrack/boot/ui/EventController.java b/ontrack-ui/src/main/java/net/nemerosa/ontrack/boot/ui/EventController.java index b8ff5858e3d..9d28f2e4d60 100644 --- a/ontrack-ui/src/main/java/net/nemerosa/ontrack/boot/ui/EventController.java +++ b/ontrack-ui/src/main/java/net/nemerosa/ontrack/boot/ui/EventController.java @@ -15,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -128,6 +129,7 @@ protected UIEvent toUIEvent(Event event) { event.getValues(), eventTemplatingService.renderEvent( event, + Collections.emptyMap(), null, htmlNotificationEventRenderer ), diff --git a/ontrack-ui/src/test/java/net/nemerosa/ontrack/boot/docs/DocumentationGenerationIT.kt b/ontrack-ui/src/test/java/net/nemerosa/ontrack/boot/docs/DocumentationGenerationIT.kt index e029852aa01..4110ee687ca 100644 --- a/ontrack-ui/src/test/java/net/nemerosa/ontrack/boot/docs/DocumentationGenerationIT.kt +++ b/ontrack-ui/src/test/java/net/nemerosa/ontrack/boot/docs/DocumentationGenerationIT.kt @@ -1,6 +1,8 @@ package net.nemerosa.ontrack.boot.docs +import net.nemerosa.ontrack.extension.notifications.channels.NoTemplate import net.nemerosa.ontrack.extension.notifications.channels.NotificationChannel +import net.nemerosa.ontrack.extension.workflows.execution.WorkflowNodeExecutor import net.nemerosa.ontrack.it.AbstractDSLTestSupport import net.nemerosa.ontrack.model.annotations.getAPITypeDescription import net.nemerosa.ontrack.model.docs.* @@ -13,6 +15,7 @@ import org.junit.jupiter.api.Test import org.springframework.beans.factory.annotation.Autowired import java.io.File import kotlin.reflect.full.findAnnotations +import kotlin.reflect.full.hasAnnotation /** * Generation of the documentation @@ -35,6 +38,61 @@ class DocumentationGenerationIT : AbstractDSLTestSupport() { @Autowired private lateinit var notificationChannels: List> + @Autowired + private lateinit var workflowNodeExecutors: List + + @Test + fun `Workflow node executors`() { + + fun getWNXFileId(wnx: WorkflowNodeExecutor): String = + "workflow-node-executor-${wnx.id}" + + fun getWNXTitle(wnx: WorkflowNodeExecutor): String = + "${wnx.displayName} (${wnx.id})" + + fun generateWNX(directoryContext: DirectoryContext, wnx: WorkflowNodeExecutor) { + val description = getAPITypeDescription(wnx::class) + val parameters = getFieldsDocumentation(wnx::class) + val example = getDocumentationExampleCode(wnx::class) + + val fileId = getWNXFileId(wnx) + + directoryContext.writeFile( + fileId = fileId, + level = 4, + title = getWNXTitle(wnx), + header = description, + fields = parameters, + example = example, + links = wnx::class.findAnnotations(), + extendedConfig = { s -> + val output = getFieldsDocumentation(wnx::class, section = "output") + if (output.isNotEmpty()) { + s.append("Output:\n\n") + directoryContext.writeFields(s, output) + } + }, + ) + } + + withDirectory("workflow-node-executors") { + + writeIndex( + fileId = "appendix-workflow-node-executors-index", + level = 4, + title = "List of workflow node executors", + items = workflowNodeExecutors.associate { workflowNodeExecutor -> + getWNXFileId(workflowNodeExecutor) to getWNXTitle(workflowNodeExecutor) + } + ) + + workflowNodeExecutors.forEach { wnx -> + generateWNX(this, wnx) + } + + } + } + @Test fun `Notifications list`() { @@ -70,6 +128,11 @@ class DocumentationGenerationIT : AbstractDSLTestSupport() { s.append("Output:\n\n") directoryContext.writeFields(s, output) } + }, + extendedHeader = { s -> + if (channel::class.hasAnnotation()) { + s.append("\n\n_This channel does not use the custom template._\n\n") + } } ) } diff --git a/ontrack-web-core/.gitignore b/ontrack-web-core/.gitignore index ec5b3dd5dd4..30116e5374d 100644 --- a/ontrack-web-core/.gitignore +++ b/ontrack-web-core/.gitignore @@ -33,3 +33,6 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# Jest +/reports/ diff --git a/ontrack-web-core/__tests__/components/extension/workflows/WorkflowGraphFlow.test.js b/ontrack-web-core/__tests__/components/extension/workflows/WorkflowGraphFlow.test.js new file mode 100644 index 00000000000..8e4731b5dc1 --- /dev/null +++ b/ontrack-web-core/__tests__/components/extension/workflows/WorkflowGraphFlow.test.js @@ -0,0 +1,187 @@ +import { + changeEdges, + changeNodes, + deleteEdgeInEdges, + deleteEdgeInNodes, + deleteNodeInEdges, + deleteNodeInNodes +} from "@components/extension/workflows/WorkflowGraphFlow"; + +describe('WorkflowGraphFlow', () => { + + const graphFixture = () => { + return { + nodes: [ + { + id: 'n1', + data: { + id: 'n1', + executorId: 'mock', + data: { + text: "N1", + } + } + }, + { + id: 'n2', + data: { + id: 'n2', + executorId: '', + data: null, + parents: [ + {id: 'n1'} + ] + } + }, + ], + edges: [ + { + id: 'n1-n2', + source: 'n1', + target: 'n2', + } + ] + } + } + + it('changes a node configuration', () => { + const {nodes, edges} = graphFixture() + const node = { + oldId: 'n2', + id: 'n2', + executorId: 'mock', + data: { + text: "N2", + } + } + + const newNodes = changeNodes(node, nodes) + const newEdges = changeEdges(node, edges) + + expect(newNodes[1]).toStrictEqual({ + id: 'n2', + data: { + id: 'n2', + executorId: 'mock', + data: { + text: "N2", + }, + parents: [ + {id: 'n1'} + ] + } + }) + + expect(newEdges).toBe(edges) // No change in the edges + }); + + it('renames a node', () => { + const {nodes, edges} = graphFixture() + const node = { + oldId: 'n1', + id: 'start', + executorId: 'mock', + data: { + text: "N1", + } + } + + const newNodes = changeNodes(node, nodes) + const newEdges = changeEdges(node, edges) + + expect(newNodes[0]).toStrictEqual({ + id: 'start', + data: { + id: 'start', + executorId: 'mock', + data: { + text: "N1", + } + } + }) + + expect(newNodes[1]).toStrictEqual({ + id: 'n2', + data: { + id: 'n2', + executorId: '', + data: null, + parents: [ + {id: 'start'} + ] + } + }) + + expect(newEdges).toStrictEqual( + [ + { + id: 'start-n2', // was n1-n2 + source: 'start', // was n1 + target: 'n2', + } + ] + ) + }); + + it('deletes a node', () => { + + const {nodes, edges} = graphFixture() + const node = { + oldId: 'n1', + id: null, + } + + const newNodes = deleteNodeInNodes(node, nodes) + const newEdges = deleteNodeInEdges(node, edges) + + expect(newNodes).toStrictEqual([ + { + id: 'n2', + data: { + id: 'n2', + executorId: '', + data: null, + parents: [] + } + }, + ]) + + expect(newEdges).toStrictEqual([]) + + }); + + it('deletes an edge and adjust the parents of the child', () => { + + const {nodes, edges} = graphFixture() + + const newNodes = deleteEdgeInNodes('n1-n2', nodes, edges) + const newEdges = deleteEdgeInEdges('n1-n2', edges) + + expect(newNodes).toStrictEqual([ + { + id: 'n1', + data: { + id: 'n1', + executorId: 'mock', + data: { + text: "N1", + }, + parents: [] + } + }, + { + id: 'n2', + data: { + id: 'n2', + executorId: '', + data: null, + parents: [] + } + }, + ]) + + expect(newEdges).toStrictEqual([]) + + }); + +}); \ No newline at end of file diff --git a/ontrack-web-core/build.gradle.kts b/ontrack-web-core/build.gradle.kts index 080ee214d0c..7c273723a5a 100644 --- a/ontrack-web-core/build.gradle.kts +++ b/ontrack-web-core/build.gradle.kts @@ -21,8 +21,14 @@ val webBuild by tasks.registering(NpmTask::class) { args.set(listOf("run", "build")) } +val test by tasks.registering(NpmTask::class) { + dependsOn("npmInstall") + args.set(listOf("run", "test")) +} + tasks.named("build") { dependsOn(webBuild) + dependsOn(test) } // Docker image diff --git a/ontrack-web-core/components/common/table/StandardTable.js b/ontrack-web-core/components/common/table/StandardTable.js index 6b586b2faa6..699c1e57e23 100644 --- a/ontrack-web-core/components/common/table/StandardTable.js +++ b/ontrack-web-core/components/common/table/StandardTable.js @@ -9,11 +9,11 @@ export default function StandardTable({ variables = {}, reloadCount = 0, columns = [], - expandable, + expandable = false, size = 10, filter = {}, - onFilterChange, - footerExtra, + onFilterChange = (_) => {}, + footerExtra = '', }) { const client = useGraphQLClient() diff --git a/ontrack-web-core/components/extension/notifications/NotificationChannelConfig.js b/ontrack-web-core/components/extension/notifications/NotificationChannelConfig.js index f0f4c5c456a..3bf402a3a82 100644 --- a/ontrack-web-core/components/extension/notifications/NotificationChannelConfig.js +++ b/ontrack-web-core/components/extension/notifications/NotificationChannelConfig.js @@ -2,7 +2,7 @@ import {Dynamic} from "@components/common/Dynamic"; export default function NotificationChannelConfig({channel, config}) { return } \ No newline at end of file diff --git a/ontrack-web-core/components/extension/notifications/NotificationChannelConfigForm.js b/ontrack-web-core/components/extension/notifications/NotificationChannelConfigForm.js index a7d9113b94b..ca622ebd09c 100644 --- a/ontrack-web-core/components/extension/notifications/NotificationChannelConfigForm.js +++ b/ontrack-web-core/components/extension/notifications/NotificationChannelConfigForm.js @@ -2,7 +2,7 @@ import {Dynamic} from "@components/common/Dynamic"; export default function NotificationChannelConfigForm({prefix, channelType}) { return } \ No newline at end of file diff --git a/ontrack-web-core/components/extension/notifications/NotificationRecordOutput.js b/ontrack-web-core/components/extension/notifications/NotificationRecordOutput.js index 96ca5724d3f..37181564c42 100644 --- a/ontrack-web-core/components/extension/notifications/NotificationRecordOutput.js +++ b/ontrack-web-core/components/extension/notifications/NotificationRecordOutput.js @@ -2,7 +2,7 @@ import {Dynamic} from "@components/common/Dynamic"; export default function NotificationRecordOutput({channel, output}) { return } \ No newline at end of file diff --git a/ontrack-web-core/components/extension/notifications/SubscriptionDialog.js b/ontrack-web-core/components/extension/notifications/SubscriptionDialog.js index 914f5a59e2b..0592c9a4748 100644 --- a/ontrack-web-core/components/extension/notifications/SubscriptionDialog.js +++ b/ontrack-web-core/components/extension/notifications/SubscriptionDialog.js @@ -14,7 +14,7 @@ export const useSubscriptionDialog = ({onSuccess, projectEntity}) => { const customPreparation = async (channelType, channelConfig) => { const newConfig = await callDynamicFunction( - `framework/notification-channel-form-prepare/${channelType}`, + `framework/notification-channel/${channelType}/FormPrepare`, channelConfig, ) return newConfig ?? channelConfig diff --git a/ontrack-web-core/components/extension/workflows/ConfigureWorkflowNodeDialog.js b/ontrack-web-core/components/extension/workflows/ConfigureWorkflowNodeDialog.js new file mode 100644 index 00000000000..f22cb3c6d7f --- /dev/null +++ b/ontrack-web-core/components/extension/workflows/ConfigureWorkflowNodeDialog.js @@ -0,0 +1,72 @@ +import FormDialog, {useFormDialog} from "@components/form/FormDialog"; +import {Form, Input} from "antd"; +import SelectWorkflowNodeExecutor from "@components/extension/workflows/SelectWorkflowNodeExecutor"; +import {useState} from "react"; +import Well from "@components/common/Well"; +import WorkflowNodeExecutorForm from "@components/extension/workflows/WorkflowNodeExecutorForm"; + +export const useConfigureWorkflowNodeDialog = ({onSuccess}) => { + + const [currentValues, setCurrentValues] = useState({}) + + return useFormDialog({ + init: (form, context) => { + setCurrentValues({...context}) + form.setFieldValue('id', context.id) + form.setFieldValue('executorId', context.executorId) + form.setFieldValue('data', context.data) + }, + currentValues, + setCurrentValues, + onSuccess, + }) +} + +export default function ConfigureWorkflowNodeDialog({dialog}) { + + const onValuesChange = (changedValues /*, allValues*/) => { + if (changedValues.hasOwnProperty('executorId')) { + const executorId = changedValues.executorId + if (executorId !== dialog.currentValues.executorId) { + dialog.form.setFieldValue('data', null) + dialog.setCurrentValues({...dialog.currentValues, executorId, data: null}) + } + } + } + + return ( + <> + + + + + + + + { + dialog.currentValues.executorId && + + + + + + } + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/extension/workflows/EditWorkflowButton.js b/ontrack-web-core/components/extension/workflows/EditWorkflowButton.js new file mode 100644 index 00000000000..96879c4163d --- /dev/null +++ b/ontrack-web-core/components/extension/workflows/EditWorkflowButton.js @@ -0,0 +1,27 @@ +import {Button, Space} from "antd"; +import {FaProjectDiagram} from "react-icons/fa"; +import EditWorkflowDialog, {useEditWorkflowDialog} from "@components/extension/workflows/EditWorkflowDialog"; +import {ReactFlowProvider} from "reactflow"; + +export default function EditWorkflowButton({value, onChange}) { + + const dialog = useEditWorkflowDialog({ + onSuccess: onChange + }) + + const startEdition = () => { + dialog.start(value) + } + + return ( + <> + + + {value?.name} + + + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/extension/workflows/EditWorkflowDialog.js b/ontrack-web-core/components/extension/workflows/EditWorkflowDialog.js new file mode 100644 index 00000000000..e478e504c0f --- /dev/null +++ b/ontrack-web-core/components/extension/workflows/EditWorkflowDialog.js @@ -0,0 +1,163 @@ +import {Input, Modal, Space} from "antd"; +import {useState} from "react"; +import WorkflowGraph from "@components/extension/workflows/WorkflowGraph"; +import {useReactFlow} from "reactflow"; +import FormErrors from "@components/form/FormErrors"; +import {useGraphQLClient} from "@components/providers/ConnectionContextProvider"; +import {gql} from "graphql-request"; +import {getUserErrors} from "@components/services/graphql-utils"; + +export const useEditWorkflowDialog = ({onSuccess}) => { + + const [open, setOpen] = useState(false) + const [workflow, setWorkflow] = useState({name: '', nodes: []}) + + return { + open, + setOpen, + workflow, + setWorkflow, + onSuccess, + start: (workflow) => { + // Deep copy of the workflow or create an empty one + let localWorkflow + if (workflow) { + localWorkflow = JSON.parse(JSON.stringify(workflow)) + } else { + localWorkflow = { + name: '', + nodes: [], + } + } + setWorkflow(localWorkflow) + setOpen(true) + } + } + +} + +export default function EditWorkflowDialog({dialog}) { + + const client = useGraphQLClient() + + const [loading, setLoading] = useState(false) + const [formErrors, setFormErrors] = useState([]) + + const onCancel = () => { + dialog.setOpen(false) + } + + // Workflow name + const onNameChange = (e) => { + const name = e.target.value + dialog.setWorkflow(old => ({ + ...old, + name, + })) + } + + // Gets the nodes & edges of the graph + const reactFlow = useReactFlow() + + const convertGraphToWorkflow = (nodes, edges) => { + // Getting the nodes + const wNodes = [] + const wIndex = {} + nodes.forEach(({data}) => { + const {id, executorId, data: nodeData} = data + const wNode = { + id, + executorId, + data: nodeData, + parents: [], + }; + wNodes.push(wNode) + wIndex[id] = wNode + }) + // Getting the relationships + edges.forEach(({source, target}) => { + const parent = wIndex[source] + const child = wIndex[target] + if (parent && child) { + child.parents.push({id: parent.id}) + } + }) + // Workflow + return { + name: dialog.workflow.name, + nodes: wNodes, + } + } + + const onSave = async () => { + // Loading mode + setLoading(true) + setFormErrors([]) + try { + // Gets the workflow graph from the context + const nodes = reactFlow.getNodes() + const edges = reactFlow.getEdges() + // Converts the graph into a workflow definition + const workflow = convertGraphToWorkflow(nodes, edges) + // Checks the workflow (name, cycle, etc.) + const data = await client.request( + gql` + mutation ValidateWorkflow($workflow: JSON!) { + validateJsonWorkflow(input: {workflow: $workflow}) { + errors { + message + } + validation { + errors + } + } + } + `, + {workflow} + ) + // Error management + const userNode = data.validateJsonWorkflow + let errors = getUserErrors(userNode) + if (!errors) { + errors = userNode.validation.errors + } + if (errors && errors.length > 0) { + setFormErrors(errors) + } else { + dialog.setOpen(false) + dialog.onSuccess(workflow) + } + } finally { + setLoading(false) + } + } + + return ( + <> + + + + {/* Workflow name */} + + {/* Workflow nodes in edition mode */} + + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/extension/workflows/SelectWorkflowNodeExecutor.js b/ontrack-web-core/components/extension/workflows/SelectWorkflowNodeExecutor.js new file mode 100644 index 00000000000..cf015632021 --- /dev/null +++ b/ontrack-web-core/components/extension/workflows/SelectWorkflowNodeExecutor.js @@ -0,0 +1,29 @@ +import {useContext, useEffect, useState} from "react"; +import {WorkflowNodeExecutorContext} from "@components/extension/workflows/WorkflowNodeExecutorContext"; +import {Select} from "antd"; + +export default function SelectWorkflowNodeExecutor({value, onChange, width}) { + + const executors = useContext(WorkflowNodeExecutorContext) + + const [options, setOptions] = useState([]) + + useEffect(() => { + setOptions(executors.map(executor => ({ + value: executor.id, + label: executor.displayName, + }))) + }, [executors]); + + return ( + <> + diff --git a/ontrack-web-core/components/framework/notification-channel-form-prepare/jira-creation.js b/ontrack-web-core/components/framework/notification-channel/jira-creation/FormPrepare.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-form-prepare/jira-creation.js rename to ontrack-web-core/components/framework/notification-channel/jira-creation/FormPrepare.js diff --git a/ontrack-web-core/components/framework/notification-channel-output/jira-creation.js b/ontrack-web-core/components/framework/notification-channel/jira-creation/Output.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-output/jira-creation.js rename to ontrack-web-core/components/framework/notification-channel/jira-creation/Output.js diff --git a/ontrack-web-core/components/framework/notification-channel-config/jira-service-desk.js b/ontrack-web-core/components/framework/notification-channel/jira-service-desk/Config.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-config/jira-service-desk.js rename to ontrack-web-core/components/framework/notification-channel/jira-service-desk/Config.js diff --git a/ontrack-web-core/components/framework/notification-channel-form/jira-service-desk.js b/ontrack-web-core/components/framework/notification-channel/jira-service-desk/Form.js similarity index 92% rename from ontrack-web-core/components/framework/notification-channel-form/jira-service-desk.js rename to ontrack-web-core/components/framework/notification-channel/jira-service-desk/Form.js index 5015beda05c..e68a887a6b1 100644 --- a/ontrack-web-core/components/framework/notification-channel-form/jira-service-desk.js +++ b/ontrack-web-core/components/framework/notification-channel/jira-service-desk/Form.js @@ -1,11 +1,12 @@ import {Button, Form, Input, InputNumber, Select, Space, Switch, Typography} from "antd"; import {FaExclamationTriangle, FaPlus, FaTrash} from "react-icons/fa"; +import {prefixedFormName} from "@components/form/formUtils"; export default function JiraServiceDeskNotificationChannelForm({prefix}) { return ( <> @@ -41,14 +42,14 @@ export default function JiraServiceDeskNotificationChannelForm({prefix}) { diff --git a/ontrack-web-core/components/framework/notification-channel-form-prepare/jira-service-desk.js b/ontrack-web-core/components/framework/notification-channel/jira-service-desk/FormPrepare.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-form-prepare/jira-service-desk.js rename to ontrack-web-core/components/framework/notification-channel/jira-service-desk/FormPrepare.js diff --git a/ontrack-web-core/components/framework/notification-channel-output/jira-service-desk.js b/ontrack-web-core/components/framework/notification-channel/jira-service-desk/Output.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-output/jira-service-desk.js rename to ontrack-web-core/components/framework/notification-channel/jira-service-desk/Output.js diff --git a/ontrack-web-core/components/framework/notification-channel-config/mail.js b/ontrack-web-core/components/framework/notification-channel/mail/Config.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-config/mail.js rename to ontrack-web-core/components/framework/notification-channel/mail/Config.js diff --git a/ontrack-web-core/components/framework/notification-channel-form/mail.js b/ontrack-web-core/components/framework/notification-channel/mail/Form.js similarity index 78% rename from ontrack-web-core/components/framework/notification-channel-form/mail.js rename to ontrack-web-core/components/framework/notification-channel/mail/Form.js index f73e9b4e992..af6df74291a 100644 --- a/ontrack-web-core/components/framework/notification-channel-form/mail.js +++ b/ontrack-web-core/components/framework/notification-channel/mail/Form.js @@ -1,10 +1,11 @@ import {Form, Input} from "antd"; +import {prefixedFormName} from "@components/form/formUtils"; export default function MailNotificationChannelForm({prefix}) { return ( <> diff --git a/ontrack-web-core/components/framework/notification-channel-output/slack.js b/ontrack-web-core/components/framework/notification-channel/slack/Output.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-output/slack.js rename to ontrack-web-core/components/framework/notification-channel/slack/Output.js diff --git a/ontrack-web-core/components/framework/notification-channel-config/webhook.js b/ontrack-web-core/components/framework/notification-channel/webhook/Config.js similarity index 100% rename from ontrack-web-core/components/framework/notification-channel-config/webhook.js rename to ontrack-web-core/components/framework/notification-channel/webhook/Config.js diff --git a/ontrack-web-core/components/framework/notification-channel-form/webhook.js b/ontrack-web-core/components/framework/notification-channel/webhook/Form.js similarity index 76% rename from ontrack-web-core/components/framework/notification-channel-form/webhook.js rename to ontrack-web-core/components/framework/notification-channel/webhook/Form.js index 6720d6706a5..906bdc3b78d 100644 --- a/ontrack-web-core/components/framework/notification-channel-form/webhook.js +++ b/ontrack-web-core/components/framework/notification-channel/webhook/Form.js @@ -1,10 +1,11 @@ import {Form, Input} from "antd"; +import {prefixedFormName} from "@components/form/formUtils"; export default function WebhookNotificationChannelForm({prefix}) { return ( <> { + dialog.start(workflow) + } + + return ( + <> + + + {workflow?.name} + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/notification-channel/workflow/Form.js b/ontrack-web-core/components/framework/notification-channel/workflow/Form.js new file mode 100644 index 00000000000..4c3c8cab002 --- /dev/null +++ b/ontrack-web-core/components/framework/notification-channel/workflow/Form.js @@ -0,0 +1,17 @@ +import {Form} from "antd"; +import EditWorkflowButton from "@components/extension/workflows/EditWorkflowButton"; +import {prefixedFormName} from "@components/form/formUtils"; + +export default function WorkflowNotificationChannelForm({prefix}) { + + return ( + <> + + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/notification-channel/workflow/Output.js b/ontrack-web-core/components/framework/notification-channel/workflow/Output.js new file mode 100644 index 00000000000..d59144c69b6 --- /dev/null +++ b/ontrack-web-core/components/framework/notification-channel/workflow/Output.js @@ -0,0 +1,11 @@ +import {Space} from "antd"; +import Link from "next/link"; + +export default function WorkflowNotificationChannelOutput({workflowInstanceId}) { + return ( + + Workflow instance: + {workflowInstanceId} + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/settings/workflows-form.js b/ontrack-web-core/components/framework/settings/workflows-form.js new file mode 100644 index 00000000000..c4a43b310a8 --- /dev/null +++ b/ontrack-web-core/components/framework/settings/workflows-form.js @@ -0,0 +1,19 @@ +import SettingsForm from "@components/core/admin/settings/SettingsForm"; +import {Form} from "antd"; +import DurationPicker from "@components/common/DurationPicker"; + +export default function WorkflowsForm({id, ...values}) { + return ( + <> + + + + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/mock/Config.js b/ontrack-web-core/components/framework/workflow-node-executor/mock/Config.js new file mode 100644 index 00000000000..36f06943b32 --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/mock/Config.js @@ -0,0 +1,26 @@ +import {Descriptions, Typography} from "antd"; +import DurationMs from "@components/common/DurationMs"; + +export default function MockWorkflowNodeExecutorConfig({data}) { + + const items = [ + { + key: 'test', + label: "Text", + children: {data.text} + }, + { + key: 'waitMs', + label: "Waiting time", + children: + }, + ] + + return ( + <> + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/mock/Form.js b/ontrack-web-core/components/framework/workflow-node-executor/mock/Form.js new file mode 100644 index 00000000000..1fa2194145f --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/mock/Form.js @@ -0,0 +1,23 @@ +import {Form, Input, InputNumber} from "antd"; + +export default function MockWorkflowNodeExecutorForm() { + return ( + <> + + + + + + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/mock/Output.js b/ontrack-web-core/components/framework/workflow-node-executor/mock/Output.js new file mode 100644 index 00000000000..cf7aeafbe4a --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/mock/Output.js @@ -0,0 +1,20 @@ +import {Descriptions, Typography} from "antd"; + +export default function MockWorkflowNodeExecutorConfig({data}) { + + const items = [ + { + key: 'text', + label: "Text", + children: {data.text} + }, + ] + + return ( + <> + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/mock/ShortConfig.js b/ontrack-web-core/components/framework/workflow-node-executor/mock/ShortConfig.js new file mode 100644 index 00000000000..a5e23228dd8 --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/mock/ShortConfig.js @@ -0,0 +1,7 @@ +import {Typography} from "antd"; + +export default function MockWorkflowNodeExecutorShortConfig({data}) { + return ( + {data.text} + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/notification/Config.js b/ontrack-web-core/components/framework/workflow-node-executor/notification/Config.js new file mode 100644 index 00000000000..e71808a0749 --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/notification/Config.js @@ -0,0 +1,39 @@ +import {Descriptions} from "antd"; +import NotificationChannelConfig from "@components/extension/notifications/NotificationChannelConfig"; + +export default function NotificationWorkflowNodeExecutorConfig({data}) { + + const {channel, channelConfig, template} = data + + return ( + <> + , + span: 12, + }, + { + key: 'template', + label: 'Template', + children: template, + span: 12, + }, + ]} + /> + + ) + +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/notification/Form.js b/ontrack-web-core/components/framework/workflow-node-executor/notification/Form.js new file mode 100644 index 00000000000..da4163697f9 --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/notification/Form.js @@ -0,0 +1,49 @@ +import {Form, Input} from "antd"; +import {useState} from "react"; +import SelectNotificationChannel from "@components/extension/notifications/SelectNotificationChannel"; +import Well from "@components/common/Well"; +import NotificationChannelConfigForm from "@components/extension/notifications/NotificationChannelConfigForm"; + +export default function NotificationWorkflowNodeExecutorForm() { + + const [channelType, setChannelType] = useState('') + + const onSelectedNotificationChannel = (channelType) => { + setChannelType(channelType) + } + + return ( + <> + {/* Channel selection */} + + + + {/* Channel config form */} + { + channelType && + + + + + + } + {/* Content template */} + + + + + ) + +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/notification/Output.js b/ontrack-web-core/components/framework/workflow-node-executor/notification/Output.js new file mode 100644 index 00000000000..43becc5e85e --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/notification/Output.js @@ -0,0 +1,15 @@ +import NotificationRecordOutput from "@components/extension/notifications/NotificationRecordOutput"; + +export default function NotificationWorkflowNodeExecutorOutput({data, nodeData}) { + + const {channel} = nodeData + + return ( + <> + + + ) +} \ No newline at end of file diff --git a/ontrack-web-core/components/framework/workflow-node-executor/notification/ShortConfig.js b/ontrack-web-core/components/framework/workflow-node-executor/notification/ShortConfig.js new file mode 100644 index 00000000000..4786b42821e --- /dev/null +++ b/ontrack-web-core/components/framework/workflow-node-executor/notification/ShortConfig.js @@ -0,0 +1,13 @@ +import {Typography} from "antd"; + +export default function NotificationWorkflowNodeExecutorShortConfig({data}) { + + const {channel} = data + + return ( + <> + {channel} + + ) + +} \ No newline at end of file diff --git a/ontrack-web-core/components/layouts/UserMenu.js b/ontrack-web-core/components/layouts/UserMenu.js index f72b0748ca1..a0dfd14aee0 100644 --- a/ontrack-web-core/components/layouts/UserMenu.js +++ b/ontrack-web-core/components/layouts/UserMenu.js @@ -11,7 +11,7 @@ import { FaInfo, FaJenkins, FaJira, FaList, - FaMagic, FaMailBulk, FaPaperPlane, + FaMagic, FaMailBulk, FaPaperPlane, FaProjectDiagram, FaSignOutAlt, FaTag, FaUser, FaWrench } from "react-icons/fa"; @@ -61,6 +61,7 @@ export default function UserMenu({userMenu}) { 'extension/auto-versioning/audit/global': , 'extension/notifications/subscriptions/global': , 'extension/notifications/recordings': , + 'extension/workflows/audit': , } useEffect(() => { diff --git a/ontrack-web-core/jest.config.js b/ontrack-web-core/jest.config.js new file mode 100644 index 00000000000..c36c2eb144c --- /dev/null +++ b/ontrack-web-core/jest.config.js @@ -0,0 +1,26 @@ +const nextJest = require('next/jest') + +/** @type {import('jest').Config} */ +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: './', +}) + +// Add any custom config to be passed to Jest +const config = { + coverageProvider: 'v8', + testEnvironment: 'jsdom', + // Add more setup options before each test is run + // setupFilesAfterEnv: ['/jest.setup.ts'], + // Reports for JUnit + reporters: [ + "default", + ["jest-junit", { + "outputDirectory": "reports", + "outputName": "junit.xml" + }], + ] +} + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +module.exports = createJestConfig(config) \ No newline at end of file diff --git a/ontrack-web-core/ontrack.graphql b/ontrack-web-core/ontrack.graphql index d3e640020b4..2711dbd9465 100644 --- a/ontrack-web-core/ontrack.graphql +++ b/ontrack-web-core/ontrack.graphql @@ -2947,6 +2947,14 @@ type LabelProviderDescription { name: String! } +"Output type for the launchWorkflow mutation." +type LaunchWorkflowPayload implements Payload { + "List of errors" + errors: [UserError] + "Workflow instance ID" + workflowInstanceId: String +} + "Output type for the linkBuildById mutation." type LinkBuildByIdPayload implements Payload { "Build linked from" @@ -3543,6 +3551,11 @@ type Mutation { ): GitHubIngestionValidateDataByRunIdPayload "Launches a job" launchJob(id: Int!): JobActionResult! + "Launches an existing workflow" + launchWorkflow( + "Input for the mutation" + input: LaunchWorkflowInput + ): LaunchWorkflowPayload "Link two builds using their names" linkBuild( "Input for the mutation" @@ -3610,6 +3623,11 @@ type Mutation { saveDashboard(input: SaveDashboardInput!): SaveDashboardPayload "Saving some generic settings" saveSettings(input: SaveSettingsInput!): SaveSettingsPayload + "Saves a workflow which is defined as YAML" + saveYamlWorkflow( + "Input for the mutation" + input: SaveYamlWorkflowInput + ): SaveYamlWorkflowPayload "Selects a dashboard" selectDashboard(input: SelectDashboardInput!): SelectDashboardPayload "Sets the auto versioning configuration for a branch" @@ -4171,6 +4189,11 @@ type Mutation { "Input for the mutation" input: ValidateBuildWithTestsInput ): ValidateBuildWithTestsPayload + "Validates a workflow which is defined as JSON" + validateJsonWorkflow( + "Input for the mutation" + input: ValidateJsonWorkflowInput + ): ValidateJsonWorkflowPayload } "Association of a name with a value" @@ -5197,6 +5220,11 @@ type Query { "Maximum number of projects to return" count: Int = 10 ): [Project!]! + "Getting a list of texts generated for a mock workflow" + mockWorkflowTexts( + "ID of the workflow instance" + instanceId: String + ): [String!]! "List of all notification channels" notificationChannels: [NotificationChannel!]! "Access to the notification recordings" @@ -5380,6 +5408,20 @@ type Query { "Name of the webhook" name: String ): [Webhook!]! + "Gets an existing workflow instance using its ID" + workflowInstance( + "ID of the workflow instance" + id: String + ): WorkflowInstance + "List of workflow instances" + workflowInstances( + "Offset for the page" + offset: Int = 0, + "Size of the page" + size: Int = 20 + ): WorkflowInstancePaginated + "List of all workflow node executors" + workflowNodeExecutors: [WorkflowNodeExecutor!]! } "QueueDispatchResult" @@ -5709,6 +5751,14 @@ type SaveSettingsPayload implements PayloadInterface { errors: [PayloadUserError] } +"Output type for the saveYamlWorkflow mutation." +type SaveYamlWorkflowPayload implements Payload { + "List of errors" + errors: [UserError] + "Saved workflow ID" + workflowId: String +} + "Schedule" type Schedule { "cron field" @@ -6785,6 +6835,14 @@ type ValidateBuildWithTestsPayload implements Payload { validationRun: ValidationRun } +"Output type for the validateJsonWorkflow mutation." +type ValidateJsonWorkflowPayload implements Payload { + "List of errors" + errors: [UserError] + "Result of the validation" + validation: WorkflowValidation +} + type Validation { "Associated validation runs" validationRuns( @@ -7152,6 +7210,111 @@ type WidgetLayout { y: Int! } +"Workflow" +type Workflow { + "Display name for the workflow" + name: String! + "List of nodes in the workflow" + nodes: [WorkflowNode!]! +} + +"Workflow context, data which is passed to the workflow initially" +type WorkflowContext { + "data field" + data: [WorkflowContextData!]! +} + +"Data in a workflow context" +type WorkflowContextData { + "key field" + key: String! + "value field" + value: JSON +} + +"Running workflow instance" +type WorkflowInstance { + "context field" + context: WorkflowContext! + "durationMs field" + durationMs: Int + "endTime field" + endTime: LocalDateTime + "Is the workflow finished?" + finished: Boolean! + "id field" + id: String! + "List of node statuses in the workflow" + nodesExecutions: [WorkflowInstanceNode!]! + "startTime field" + startTime: LocalDateTime + "status field" + status: WorkflowInstanceStatus! + "timestamp field" + timestamp: LocalDateTime! + "workflow field" + workflow: Workflow! +} + +"Status of a node execution in a workflow" +type WorkflowInstanceNode { + "durationMs field" + durationMs: Int + "endTime field" + endTime: LocalDateTime + "error field" + error: String + "id field" + id: String! + "output field" + output: JSON + "startTime field" + startTime: LocalDateTime + "status field" + status: WorkflowInstanceNodeStatus! +} + +type WorkflowInstancePaginated { + "Information about the current page" + pageInfo: PageInfo + "Items in the current page" + pageItems: [WorkflowInstance!]! +} + +"Workflow node" +type WorkflowNode { + "Raw data associated with the node, to be used by the node executor." + data: JSON + "ID of the executor to use" + executorId: String! + "Unique ID of the node in its workflow." + id: String! + "List of the IDs of the parents for this node" + parents: [WorkflowParentNode!]! +} + +"Workflow node executor" +type WorkflowNodeExecutor { + "displayName field" + displayName: String! + "id field" + id: String! +} + +"Workflow parent node" +type WorkflowParentNode { + "ID of the parent node" + id: String! +} + +"Workflow validation" +type WorkflowValidation { + "error field" + error: Boolean + "errors field" + errors: [String!]! +} + "List of ways the auto approval is managed." enum AutoApprovalMode { CLIENT @@ -7348,6 +7511,22 @@ enum ValidationStampFilterScope { PROJECT } +"Status of a node in a workflow" +enum WorkflowInstanceNodeStatus { + ERROR + IDLE + STARTED + SUCCESS +} + +"Status of a running workflow" +enum WorkflowInstanceStatus { + ERROR + RUNNING + STARTED + SUCCESS +} + "JSON node" scalar JSON @@ -8562,6 +8741,21 @@ input IssueChangeLogExportRequest { grouping: String } +"Input type for the launchWorkflow mutation." +input LaunchWorkflowInput { + "context field" + context: [LaunchWorkflowInputContext!]! + "workflowId field" + workflowId: String! +} + +input LaunchWorkflowInputContext { + "key field" + key: String! + "value field" + value: JSON! +} + "Input type for the linkBuildById mutation." input LinkBuildByIdInput { "ID of the build from which the link must be created" @@ -8786,6 +8980,12 @@ input SaveSettingsInput { values: JSON! } +"Input type for the saveYamlWorkflow mutation." +input SaveYamlWorkflowInput { + "workflow field" + workflow: String! +} + input SelectDashboardInput { "UUID of the dashboard to select" uuid: String! @@ -10287,6 +10487,12 @@ input ValidateBuildWithTestsInput { validation: String! } +"Input type for the validateJsonWorkflow mutation." +input ValidateJsonWorkflowInput { + "workflow field" + workflow: JSON! +} + input WebhookExchangeFilter { "Payload timestamp after this" payloadAfter: LocalDateTime diff --git a/ontrack-web-core/package-lock.json b/ontrack-web-core/package-lock.json index 93a7ee08cb1..67008fe89e5 100644 --- a/ontrack-web-core/package-lock.json +++ b/ontrack-web-core/package-lock.json @@ -33,6 +33,32 @@ "recharts": "^2.10.3", "uuid": "^9.0.0", "web-worker": "^1.2.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.4.5", + "@testing-library/react": "^15.0.7", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jest-junit": "^16.0.0" + } + }, + "node_modules/@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@ant-design/colors": { @@ -100,1602 +126,4584 @@ "react": ">=16.9.0" } }, - "node_modules/@babel/runtime": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", - "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", + "node_modules/@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, "dependencies": { - "regenerator-runtime": "^0.14.0" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@ctrl/tinycolor": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", - "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "node_modules/@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "dev": true, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" - }, - "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==", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "node_modules/@babel/core": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", - "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "node_modules/@babel/core/node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "dev": true, "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.1", - "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" + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" } }, - "node_modules/@graphql-typed-document-node/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", - "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "node_modules/@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@babel/types": "^7.22.5" }, "engines": { - "node": ">=10.10.0" + "node": ">=6.9.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.0" + }, "engines": { - "node": ">=12.22" + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@next/env": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz", - "integrity": "sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==" + "node_modules/@babel/helper-simple-access": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@next/eslint-plugin-next": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.3.0.tgz", - "integrity": "sha512-wuGN5qSEjSgcq9fVkH0Y/qIPFjnZtW3ZPwfjJOn7l/rrf6y8J24h/lo61kwqunTyzZJm/ETGfGVU9PUs8cnzEA==", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "dev": true, "dependencies": { - "glob": "7.1.7" + "@babel/types": "^7.24.5" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@next/swc-darwin-arm64": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz", - "integrity": "sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=6.9.0" } }, - "node_modules/@next/swc-darwin-x64": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz", - "integrity": "sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/helper-validator-identifier": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=6.9.0" } }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz", - "integrity": "sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=6.9.0" } }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz", - "integrity": "sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/helpers": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "dev": true, + "dependencies": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" + }, "engines": { - "node": ">= 10" + "node": ">=6.9.0" } }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz", - "integrity": "sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/highlight": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.24.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, "engines": { - "node": ">= 10" + "node": ">=6.9.0" } }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz", - "integrity": "sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, "engines": { - "node": ">= 10" + "node": ">=4" } }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz", - "integrity": "sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, "engines": { - "node": ">= 10" + "node": ">=4" } }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz", - "integrity": "sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=0.8.0" } }, - "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz", - "integrity": "sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "engines": { - "node": ">= 10" + "node": ">=4" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "has-flag": "^3.0.0" }, "engines": { - "node": ">= 8" + "node": ">=4" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, "engines": { - "node": ">= 8" + "node": ">=6.0.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">= 8" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@pkgr/utils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", - "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "is-glob": "^4.0.3", - "open": "^8.4.0", - "picocolors": "^1.0.0", - "tiny-glob": "^0.2.9", - "tslib": "^2.4.0" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "funding": { - "url": "https://opencollective.com/unts" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/color-picker": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz", - "integrity": "sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==", + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.10.1", - "@ctrl/tinycolor": "^3.6.0", - "classnames": "^2.2.6", - "rc-util": "^5.30.0" + "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/context": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", - "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.10.1", - "rc-util": "^5.27.0" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/mini-decimal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", - "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.0" + "@babel/helper-plugin-utils": "^7.8.0" }, - "engines": { - "node": ">=8.x" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/mutate-observer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", - "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" + "@babel/helper-plugin-utils": "^7.24.0" }, "engines": { - "node": ">=8.x" + "node": ">=6.9.0" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/portal": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", - "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.0", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/tour": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.11.1.tgz", - "integrity": "sha512-c9Lw3/oVinj5D64Rsp8aDLOXcgdViE+hq7bj0Qoo8fTuQEh9sSpUw5OZcum943JkjeIE4hLcc5FD4a5ANtMJ4w==", + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.18.0", - "@rc-component/portal": "^1.0.0-9", - "@rc-component/trigger": "^1.3.6", - "classnames": "^2.3.2", - "rc-util": "^5.24.4" - }, - "engines": { - "node": ">=8.x" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rc-component/trigger": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.18.2.tgz", - "integrity": "sha512-jRLYgFgjLEPq3MvS87fIhcfuywFSRDaDrYw1FLku7Cm4esszvzTbA0JBsyacAyLrK9rF3TiHFcvoEDMzoD3CTA==", + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, "dependencies": { - "@babel/runtime": "^7.23.2", - "@rc-component/portal": "^1.1.0", - "classnames": "^2.3.2", - "rc-motion": "^2.0.0", - "rc-resize-observer": "^1.3.1", - "rc-util": "^5.38.0" - }, - "engines": { - "node": ">=8.x" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reactflow/background": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.4.tgz", - "integrity": "sha512-bgwvqWxF09chwmdkyClpYEMaewBspdwjgLbbFlLf4SpWPFMYyuvCBQrcISsvy/EDEWO9i3Uj9ktgGAhvtSQsmA==", + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, "dependencies": { - "@reactflow/core": "11.9.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reactflow/controls": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.4.tgz", - "integrity": "sha512-x6e5p9iHjC6gd+4SoZ3DOOp0F1MefGKQ8hT6yPVdqxfo1+rV2WhrWvrX/MCoEu12Dp7457LdLfa0giy3aho8tQ==", + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, "dependencies": { - "@reactflow/core": "11.9.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reactflow/core": { - "version": "11.9.4", - "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.9.4.tgz", - "integrity": "sha512-Ko7nKPOYalwDTTbRHi2+QXDiidSAcpUzGN3G+0B+QysLZkcaPCkpkMjjHiDC4c/Z1BJBzs1FRJg/T6BXaBnYkg==", + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, "dependencies": { - "@types/d3": "^7.4.0", - "@types/d3-drag": "^3.0.1", - "@types/d3-selection": "^3.0.3", - "@types/d3-zoom": "^3.0.1", - "classcat": "^5.0.3", - "d3-drag": "^3.0.0", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0", - "zustand": "^4.4.1" + "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reactflow/minimap": { - "version": "11.7.4", - "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.4.tgz", - "integrity": "sha512-Jo1R+uDey9IV7O2s3m0gK2+cZpg9M8hq2EZJb3NGfOSzMAPhj3mby0fNJIgTzycreuht0TpA51c2YfjGI3YIOw==", + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, "dependencies": { - "@reactflow/core": "11.9.4", - "@types/d3-selection": "^3.0.3", - "@types/d3-zoom": "^3.0.1", - "classcat": "^5.0.3", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0", - "zustand": "^4.4.1" + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reactflow/node-resizer": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.4.tgz", - "integrity": "sha512-+p271/hAsM5M1+RQTWW/02pbNkCHeGXwxGimIlL1tMIagyuko0NX2vOz2B8jxJnPKlF09Wj18BcXBNUm3nDcSg==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "dev": true, "dependencies": { - "@reactflow/core": "11.9.4", - "classcat": "^5.0.4", - "d3-drag": "^3.0.0", - "d3-selection": "^3.0.0", - "zustand": "^4.4.1" + "@babel/helper-plugin-utils": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reactflow/node-toolbar": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.4.tgz", - "integrity": "sha512-TfcmpXHRBb2mUfzKGjburiU6FWqRME9pPFs1OwIC1z5e9BjupQhNDEKEk8XHi7PKL/mAiDfwuGXaM1BVVFuPqw==", + "node_modules/@babel/runtime": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", + "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==", "dependencies": { - "@reactflow/core": "11.9.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" + "regenerator-runtime": "^0.14.0" }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@rushstack/eslint-patch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", - "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" + "node_modules/@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@swc/helpers": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", - "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "node_modules/@babel/traverse": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", + "dev": true, "dependencies": { - "tslib": "^2.4.0" + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } }, - "node_modules/@types/d3": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.2.tgz", - "integrity": "sha512-Y4g2Yb30ZJmmtqAJTqMRaqXwRawfvpdpVmyEYEcyGNhrQI/Zvkq3k7yE1tdN07aFSmNBfvmegMQ9Fe2qy9ZMhw==", + "node_modules/@babel/types": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "dev": true, "dependencies": { - "@types/d3-array": "*", - "@types/d3-axis": "*", - "@types/d3-brush": "*", - "@types/d3-chord": "*", - "@types/d3-color": "*", - "@types/d3-contour": "*", - "@types/d3-delaunay": "*", - "@types/d3-dispatch": "*", - "@types/d3-drag": "*", - "@types/d3-dsv": "*", - "@types/d3-ease": "*", - "@types/d3-fetch": "*", - "@types/d3-force": "*", - "@types/d3-format": "*", - "@types/d3-geo": "*", - "@types/d3-hierarchy": "*", - "@types/d3-interpolate": "*", - "@types/d3-path": "*", - "@types/d3-polygon": "*", - "@types/d3-quadtree": "*", - "@types/d3-random": "*", - "@types/d3-scale": "*", - "@types/d3-scale-chromatic": "*", - "@types/d3-selection": "*", - "@types/d3-shape": "*", - "@types/d3-time": "*", - "@types/d3-time-format": "*", - "@types/d3-timer": "*", - "@types/d3-transition": "*", - "@types/d3-zoom": "*" + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@types/d3-array": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.9.tgz", - "integrity": "sha512-mZowFN3p64ajCJJ4riVYlOjNlBJv3hctgAY01pjw3qTnJePD8s9DZmYDzhHKvzfCYvdjwylkU38+Vdt7Cu2FDA==" + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, - "node_modules/@types/d3-axis": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.5.tgz", - "integrity": "sha512-ufDAV3SQzju+uB3Jlty7SUb/jMigjpIlvDDcSGvGmmO6OT/sNO93UE0dRzwWOZeBLzrLSA0CQM4bf3iq1std3A==", - "dependencies": { - "@types/d3-selection": "*" + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "engines": { + "node": ">=10" } }, - "node_modules/@types/d3-brush": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.5.tgz", - "integrity": "sha512-JROQXZNq1X6QdWstESDUv1VilwZ2hBCQnWB91yal+5yZvYwGQvYsGCjrkHGfKK/8/AcX1JnERmpQzdDDuLRUsA==", + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "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==", "dependencies": { - "@types/d3-selection": "*" + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@types/d3-chord": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.5.tgz", - "integrity": "sha512-rs26AIhJjtc+XLR4YQU8IjPTLOlDVO4PR1y+pVFYEHzKh2tE5tYz3MF4QV6iz7HboXQEaYpJQt8dH9uUkne8yA==" - }, - "node_modules/@types/d3-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.2.tgz", - "integrity": "sha512-At+Ski7dL8Bs58E8g8vPcFJc8tGcaC12Z4m07+p41+DRqnZQcAlp3NfYjLrhNYv+zEyQitU1CUxXNjqUyf+c0g==" + "node_modules/@eslint-community/regexpp": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } }, - "node_modules/@types/d3-contour": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.5.tgz", - "integrity": "sha512-wLvjwdOQVd1NL1IcW90CCt1VtpeZ3V20p/OTXlkT8uAiprrJnq2PNNnRNe1QCez4U9aMU29Z14zpJQVLW1+Lcg==", + "node_modules/@eslint/eslintrc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", "dependencies": { - "@types/d3-array": "*", - "@types/geojson": "*" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.1", + "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": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@types/d3-delaunay": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.3.tgz", - "integrity": "sha512-+Lf5NPKZ4JBC9tbudVkKceQXRxU3jJs0el9aKQvinMtdnFSOG84eVXyhCNgIFuXNQO3iIcYs7sgzN359FEOZnQ==" + "node_modules/@eslint/js": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", + "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } }, - "node_modules/@types/d3-dispatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.5.tgz", - "integrity": "sha512-hxvq2kc+9hydVppo21JCGfcM0tLTh1DXnG3MLN0KlxsNZJH4bsdl1iXDuWtXFpWWlBrCMwSqlnoLPDxNAZU3Bg==" + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } }, - "node_modules/@types/d3-drag": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.5.tgz", - "integrity": "sha512-arHyAGvO0NEGGPCU2jTb31TlXeSxwty1bIxr5wOFOCVqVjgriXloLWXoRp39Oa0Y/qXxcAVMIonAWLrtLxUZAQ==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", "dependencies": { - "@types/d3-selection": "*" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" } }, - "node_modules/@types/d3-dsv": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.5.tgz", - "integrity": "sha512-73WZR3QFOaSRVz9iOrebTbTnbo7xjcgS/i0Cq5zy0jMXPO3v/JbkTD3Zqii1eYE6v4EJ78g5VP407rm+p8fdlA==" + "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==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, - "node_modules/@types/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-VZofjpEt8HWv3nxUAosj5o/+4JflnJ7Bbv07k17VO3T2WRuzGdZeookfaF60iVh5RdhVG49LE5w6LIshVUC6rg==" + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" }, - "node_modules/@types/d3-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.5.tgz", - "integrity": "sha512-Rc8pb6H0RRLpAV2hEXduykUgcDUOhjSLTLmCIeo6ejzgs4SaITh/EteMb3p5Env3Hqjsqw0fCksyqopHHzMkMg==", + "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, "dependencies": { - "@types/d3-dsv": "*" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/d3-force": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.7.tgz", - "integrity": "sha512-rsok4CEvPLyVWRPsFiBhanJc3up03H/EARVz4d8soPh8drv82YMuAckYy4yv8g4/81JwCng5U5/o9aj9d0T6bQ==" - }, - "node_modules/@types/d3-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.3.tgz", - "integrity": "sha512-kxuLXSAEJykTeL/EI3tUiEfGqru7PRdqEy099YBnqFl+fF167UVSB4+wntlZv86ZdoYf0DHjsRHnTIm8kcH7qw==" + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } }, - "node_modules/@types/d3-geo": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.6.tgz", - "integrity": "sha512-wblAES3b+C3hvp4VakwECEKtHquT/xc6K4HOna95LM1j1fd7s7WmU4V+JMQZfKhNCMkV2vWD+ZUgY2Uj6gqfuA==", + "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, "dependencies": { - "@types/geojson": "*" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/d3-hierarchy": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.5.tgz", - "integrity": "sha512-DEcBUj1IL3WyPLDlh4m2nsNXnMLITXM5Vwcu4G85yJHtf2cVGPBjgky3L11WBnT+ayHKf06Tchk5mY1eGmd4WQ==" + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.3.tgz", - "integrity": "sha512-6OZ2EIB4lLj+8cUY7I/Cgn9Q+hLdA4DjJHYOQDiHL0SzqS1K9DL5xIOVBSIHgF+tiuO9MU1D36qvdIvRDRPh+Q==", + "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, "dependencies": { - "@types/d3-color": "*" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/d3-path": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.1.tgz", - "integrity": "sha512-blRhp7ki7pVznM8k6lk5iUU9paDbVRVq+/xpf0RRgSJn5gr6SE7RcFtxooYGMBOc1RZiGyqRpVdu5AD0z0ooMA==" + "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, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@types/d3-polygon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.1.tgz", - "integrity": "sha512-nrcWPk7B9qs6xnpq60Cls44zm9eDmFAv65qi/N/emh/oftnG6uYz49aIS0mdFaGeJxVN8H3pHneMuZMV8EwFdw==" + "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, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/@types/d3-quadtree": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.4.tgz", - "integrity": "sha512-B725MopFDIOQ6njFbeOxIEf42HVO2Xv+FmcxQISdOKErvLbFqWz3Riu+OWujUYoogreqqyHBHcGGL/JzzXQYsw==" + "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, + "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, + "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, + "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" + } + }, + "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, + "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" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "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, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "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, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "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" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "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, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "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, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz", + "integrity": "sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.3.0.tgz", + "integrity": "sha512-wuGN5qSEjSgcq9fVkH0Y/qIPFjnZtW3ZPwfjJOn7l/rrf6y8J24h/lo61kwqunTyzZJm/ETGfGVU9PUs8cnzEA==", + "dependencies": { + "glob": "7.1.7" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz", + "integrity": "sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz", + "integrity": "sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz", + "integrity": "sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz", + "integrity": "sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz", + "integrity": "sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz", + "integrity": "sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz", + "integrity": "sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz", + "integrity": "sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz", + "integrity": "sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgr/utils": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", + "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "dependencies": { + "cross-spawn": "^7.0.3", + "is-glob": "^4.0.3", + "open": "^8.4.0", + "picocolors": "^1.0.0", + "tiny-glob": "^0.2.9", + "tslib": "^2.4.0" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz", + "integrity": "sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@ctrl/tinycolor": "^3.6.0", + "classnames": "^2.2.6", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.11.1.tgz", + "integrity": "sha512-c9Lw3/oVinj5D64Rsp8aDLOXcgdViE+hq7bj0Qoo8fTuQEh9sSpUw5OZcum943JkjeIE4hLcc5FD4a5ANtMJ4w==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^1.3.6", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.18.2.tgz", + "integrity": "sha512-jRLYgFgjLEPq3MvS87fIhcfuywFSRDaDrYw1FLku7Cm4esszvzTbA0JBsyacAyLrK9rF3TiHFcvoEDMzoD3CTA==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@reactflow/background": { + "version": "11.3.4", + "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.4.tgz", + "integrity": "sha512-bgwvqWxF09chwmdkyClpYEMaewBspdwjgLbbFlLf4SpWPFMYyuvCBQrcISsvy/EDEWO9i3Uj9ktgGAhvtSQsmA==", + "dependencies": { + "@reactflow/core": "11.9.4", + "classcat": "^5.0.3", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/controls": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.4.tgz", + "integrity": "sha512-x6e5p9iHjC6gd+4SoZ3DOOp0F1MefGKQ8hT6yPVdqxfo1+rV2WhrWvrX/MCoEu12Dp7457LdLfa0giy3aho8tQ==", + "dependencies": { + "@reactflow/core": "11.9.4", + "classcat": "^5.0.3", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/core": { + "version": "11.9.4", + "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.9.4.tgz", + "integrity": "sha512-Ko7nKPOYalwDTTbRHi2+QXDiidSAcpUzGN3G+0B+QysLZkcaPCkpkMjjHiDC4c/Z1BJBzs1FRJg/T6BXaBnYkg==", + "dependencies": { + "@types/d3": "^7.4.0", + "@types/d3-drag": "^3.0.1", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "classcat": "^5.0.3", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/minimap": { + "version": "11.7.4", + "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.4.tgz", + "integrity": "sha512-Jo1R+uDey9IV7O2s3m0gK2+cZpg9M8hq2EZJb3NGfOSzMAPhj3mby0fNJIgTzycreuht0TpA51c2YfjGI3YIOw==", + "dependencies": { + "@reactflow/core": "11.9.4", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "classcat": "^5.0.3", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/node-resizer": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.4.tgz", + "integrity": "sha512-+p271/hAsM5M1+RQTWW/02pbNkCHeGXwxGimIlL1tMIagyuko0NX2vOz2B8jxJnPKlF09Wj18BcXBNUm3nDcSg==", + "dependencies": { + "@reactflow/core": "11.9.4", + "classcat": "^5.0.4", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@reactflow/node-toolbar": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.4.tgz", + "integrity": "sha512-TfcmpXHRBb2mUfzKGjburiU6FWqRME9pPFs1OwIC1z5e9BjupQhNDEKEk8XHi7PKL/mAiDfwuGXaM1BVVFuPqw==", + "dependencies": { + "@reactflow/core": "11.9.4", + "classcat": "^5.0.3", + "zustand": "^4.4.1" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", + "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", + "integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==", + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/dom/node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", + "dev": true, + "dependencies": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + }, + "peerDependencies": { + "@jest/globals": ">= 28", + "@types/bun": "latest", + "@types/jest": ">= 28", + "jest": ">= 28", + "vitest": ">= 0.32" + }, + "peerDependenciesMeta": { + "@jest/globals": { + "optional": true + }, + "@types/bun": { + "optional": true + }, + "@types/jest": { + "optional": true + }, + "jest": { + "optional": true + }, + "vitest": { + "optional": true + } + } + }, + "node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@testing-library/react": { + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz", + "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "node_modules/@types/d3": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.2.tgz", + "integrity": "sha512-Y4g2Yb30ZJmmtqAJTqMRaqXwRawfvpdpVmyEYEcyGNhrQI/Zvkq3k7yE1tdN07aFSmNBfvmegMQ9Fe2qy9ZMhw==", + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.9.tgz", + "integrity": "sha512-mZowFN3p64ajCJJ4riVYlOjNlBJv3hctgAY01pjw3qTnJePD8s9DZmYDzhHKvzfCYvdjwylkU38+Vdt7Cu2FDA==" + }, + "node_modules/@types/d3-axis": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.5.tgz", + "integrity": "sha512-ufDAV3SQzju+uB3Jlty7SUb/jMigjpIlvDDcSGvGmmO6OT/sNO93UE0dRzwWOZeBLzrLSA0CQM4bf3iq1std3A==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.5.tgz", + "integrity": "sha512-JROQXZNq1X6QdWstESDUv1VilwZ2hBCQnWB91yal+5yZvYwGQvYsGCjrkHGfKK/8/AcX1JnERmpQzdDDuLRUsA==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.5.tgz", + "integrity": "sha512-rs26AIhJjtc+XLR4YQU8IjPTLOlDVO4PR1y+pVFYEHzKh2tE5tYz3MF4QV6iz7HboXQEaYpJQt8dH9uUkne8yA==" + }, + "node_modules/@types/d3-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.2.tgz", + "integrity": "sha512-At+Ski7dL8Bs58E8g8vPcFJc8tGcaC12Z4m07+p41+DRqnZQcAlp3NfYjLrhNYv+zEyQitU1CUxXNjqUyf+c0g==" + }, + "node_modules/@types/d3-contour": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.5.tgz", + "integrity": "sha512-wLvjwdOQVd1NL1IcW90CCt1VtpeZ3V20p/OTXlkT8uAiprrJnq2PNNnRNe1QCez4U9aMU29Z14zpJQVLW1+Lcg==", + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.3.tgz", + "integrity": "sha512-+Lf5NPKZ4JBC9tbudVkKceQXRxU3jJs0el9aKQvinMtdnFSOG84eVXyhCNgIFuXNQO3iIcYs7sgzN359FEOZnQ==" + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.5.tgz", + "integrity": "sha512-hxvq2kc+9hydVppo21JCGfcM0tLTh1DXnG3MLN0KlxsNZJH4bsdl1iXDuWtXFpWWlBrCMwSqlnoLPDxNAZU3Bg==" + }, + "node_modules/@types/d3-drag": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.5.tgz", + "integrity": "sha512-arHyAGvO0NEGGPCU2jTb31TlXeSxwty1bIxr5wOFOCVqVjgriXloLWXoRp39Oa0Y/qXxcAVMIonAWLrtLxUZAQ==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.5.tgz", + "integrity": "sha512-73WZR3QFOaSRVz9iOrebTbTnbo7xjcgS/i0Cq5zy0jMXPO3v/JbkTD3Zqii1eYE6v4EJ78g5VP407rm+p8fdlA==" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-VZofjpEt8HWv3nxUAosj5o/+4JflnJ7Bbv07k17VO3T2WRuzGdZeookfaF60iVh5RdhVG49LE5w6LIshVUC6rg==" + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.5.tgz", + "integrity": "sha512-Rc8pb6H0RRLpAV2hEXduykUgcDUOhjSLTLmCIeo6ejzgs4SaITh/EteMb3p5Env3Hqjsqw0fCksyqopHHzMkMg==", + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.7.tgz", + "integrity": "sha512-rsok4CEvPLyVWRPsFiBhanJc3up03H/EARVz4d8soPh8drv82YMuAckYy4yv8g4/81JwCng5U5/o9aj9d0T6bQ==" + }, + "node_modules/@types/d3-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.3.tgz", + "integrity": "sha512-kxuLXSAEJykTeL/EI3tUiEfGqru7PRdqEy099YBnqFl+fF167UVSB4+wntlZv86ZdoYf0DHjsRHnTIm8kcH7qw==" + }, + "node_modules/@types/d3-geo": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.6.tgz", + "integrity": "sha512-wblAES3b+C3hvp4VakwECEKtHquT/xc6K4HOna95LM1j1fd7s7WmU4V+JMQZfKhNCMkV2vWD+ZUgY2Uj6gqfuA==", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.5.tgz", + "integrity": "sha512-DEcBUj1IL3WyPLDlh4m2nsNXnMLITXM5Vwcu4G85yJHtf2cVGPBjgky3L11WBnT+ayHKf06Tchk5mY1eGmd4WQ==" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.3.tgz", + "integrity": "sha512-6OZ2EIB4lLj+8cUY7I/Cgn9Q+hLdA4DjJHYOQDiHL0SzqS1K9DL5xIOVBSIHgF+tiuO9MU1D36qvdIvRDRPh+Q==", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.1.tgz", + "integrity": "sha512-blRhp7ki7pVznM8k6lk5iUU9paDbVRVq+/xpf0RRgSJn5gr6SE7RcFtxooYGMBOc1RZiGyqRpVdu5AD0z0ooMA==" + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-nrcWPk7B9qs6xnpq60Cls44zm9eDmFAv65qi/N/emh/oftnG6uYz49aIS0mdFaGeJxVN8H3pHneMuZMV8EwFdw==" + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.4.tgz", + "integrity": "sha512-B725MopFDIOQ6njFbeOxIEf42HVO2Xv+FmcxQISdOKErvLbFqWz3Riu+OWujUYoogreqqyHBHcGGL/JzzXQYsw==" }, "node_modules/@types/d3-random": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.2.tgz", - "integrity": "sha512-8QhsqkKs6mymAZMrg3ZFXPxKA34rdgp3ZrtB8o6mhFsKAd1gOvR1gocWnca+kmXypQdwgnzKm9gZE2Uw8NjjKw==" + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.2.tgz", + "integrity": "sha512-8QhsqkKs6mymAZMrg3ZFXPxKA34rdgp3ZrtB8o6mhFsKAd1gOvR1gocWnca+kmXypQdwgnzKm9gZE2Uw8NjjKw==" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.6.tgz", + "integrity": "sha512-lo3oMLSiqsQUovv8j15X4BNEDOsnHuGjeVg7GRbAuB2PUa1prK5BNSOu6xixgNf3nqxPl4I1BqJWrPvFGlQoGQ==", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.1.tgz", + "integrity": "sha512-Ob7OrwiTeQXY/WBBbRHGZBOn6rH1h7y3jjpTSKYqDEeqFjktql6k2XSgNwLrLDmAsXhEn8P9NHDY4VTuo0ZY1w==" + }, + "node_modules/@types/d3-selection": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.8.tgz", + "integrity": "sha512-pxCZUfQyedq/DIlPXIR5wE1mIH37omOdx1yxRudL3KZ4AC+156jMjOv1z5RVlGq62f8WX2kyO0hTVgEx627QFg==" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.4.tgz", + "integrity": "sha512-M2/xsWPsjaZc5ifMKp1EBp0gqJG0eO/zlldJNOC85Y/5DGsBQ49gDkRJ2h5GY7ZVD6KUumvZWsylSbvTaJTqKg==", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.2.tgz", + "integrity": "sha512-kbdRXTmUgNfw5OTE3KZnFQn6XdIc4QGroN5UixgdrXATmYsdlPQS6pEut9tVlIojtzuFD4txs/L+Rq41AHtLpg==" + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.2.tgz", + "integrity": "sha512-wr08C1Gh77qaN8JIkrn5Rz/bdt5M9bdEqFmEOcYhUSq2t2sHvLTBfb4XAtGB3D4hm0ubj50NXWWXoXyp5tPXDg==" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-GGTvzKccVEhxmRfJEB6zhY9ieT4UhGVUIQaBzFpUO9OXy2ycAlnPCSJLzmGGgqt3KVjqN3QCQB4g1rsZnHsWhg==" + }, + "node_modules/@types/d3-transition": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.6.tgz", + "integrity": "sha512-K0To23B5UxNwFtKORnS5JoNYvw/DnknU5MzhHIS9czJ/lTqFFDeU6w9lArOdoTl0cZFNdNrMJSFCbRCEHccH2w==", + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.6.tgz", + "integrity": "sha512-dGZQaXEu7aNcCL71LPpjB58IjoQNM9oDPfQuMUJ7N/fbkcIWGX2PnmUWO1jPJ+RLbZBpRUggJUX8twKRvo2hKQ==", + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.12", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.12.tgz", + "integrity": "sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@types/node": { + "version": "16.18.65", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.65.tgz", + "integrity": "sha512-5E9WgTy95B7i90oISjui9U5Zu7iExUPfU4ygtv4yXEy6zJFE3oQYHCnh5H1jZRPkjphJt2Ml3oQW6M0qtK534A==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.3.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", + "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", + "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", + "dependencies": { + "@typescript-eslint/scope-manager": "5.59.0", + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/typescript-estree": "5.59.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", + "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", + "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", + "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "@typescript-eslint/visitor-keys": "5.59.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", + "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "dependencies": { + "@typescript-eslint/types": "5.59.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", + "dev": true + }, + "node_modules/ace-builds": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.24.2.tgz", + "integrity": "sha512-zjvJiEw05BADxPMq5gN/Vgc9FgyiiDHpdy676Af1nJk8DF4ipgf0cNmV3wy8JHeQ6vezypEZV6pHQu9avO+WtQ==" + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antd": { + "version": "5.12.1", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.12.1.tgz", + "integrity": "sha512-lDTg4U/4MxDD4OK0sLM3D0ge+5nHKj27dUj4ufF1FhQKPcRkVnkCWJ43gb1Cn+S3ybvz7yfsiEv0v+QqWJgPlA==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/cssinjs": "^1.18.0", + "@ant-design/icons": "^5.2.6", + "@ant-design/react-slick": "~1.0.2", + "@babel/runtime": "^7.23.4", + "@ctrl/tinycolor": "^3.6.1", + "@rc-component/color-picker": "~1.4.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/tour": "~1.11.0", + "@rc-component/trigger": "^1.18.2", + "classnames": "^2.3.2", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.1", + "qrcode.react": "^3.1.0", + "rc-cascader": "~3.20.0", + "rc-checkbox": "~3.1.0", + "rc-collapse": "~3.7.2", + "rc-dialog": "~9.3.4", + "rc-drawer": "~6.5.2", + "rc-dropdown": "~4.1.0", + "rc-field-form": "~1.41.0", + "rc-image": "~7.5.1", + "rc-input": "~1.3.6", + "rc-input-number": "~8.4.0", + "rc-mentions": "~2.9.1", + "rc-menu": "~9.12.2", + "rc-motion": "^2.9.0", + "rc-notification": "~5.3.0", + "rc-pagination": "~4.0.1", + "rc-picker": "~3.14.6", + "rc-progress": "~3.5.1", + "rc-rate": "~2.12.0", + "rc-resize-observer": "^1.4.0", + "rc-segmented": "~2.2.2", + "rc-select": "~14.10.0", + "rc-slider": "~10.5.0", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.36.0", + "rc-tabs": "~12.14.1", + "rc-textarea": "~1.5.3", + "rc-tooltip": "~6.1.2", + "rc-tree": "~5.8.2", + "rc-tree-select": "~5.15.0", + "rc-upload": "~4.3.5", + "rc-util": "^5.38.1", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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==" + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001617", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz", + "integrity": "sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, + "node_modules/classcat": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz", + "integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==" + }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", + "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookies-next": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-4.1.0.tgz", + "integrity": "sha512-BREVc4TJT4NwXfyKjdjnYFXM6iRns+MYpCd34ClXuYqeisXnkPkbq7Ok9xaqi9mHmV6H2rwPE+p3EpMz4pF/kQ==", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/node": "^16.10.2", + "cookie": "^0.4.0" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/create-jest/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, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } }, - "node_modules/@types/d3-scale": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.6.tgz", - "integrity": "sha512-lo3oMLSiqsQUovv8j15X4BNEDOsnHuGjeVg7GRbAuB2PUa1prK5BNSOu6xixgNf3nqxPl4I1BqJWrPvFGlQoGQ==", + "node_modules/data-urls/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, "dependencies": { - "@types/d3-time": "*" + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dependencies": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-match-patch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", + "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/d3-scale-chromatic": { + "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.1.tgz", - "integrity": "sha512-Ob7OrwiTeQXY/WBBbRHGZBOn6rH1h7y3jjpTSKYqDEeqFjktql6k2XSgNwLrLDmAsXhEn8P9NHDY4VTuo0ZY1w==" - }, - "node_modules/@types/d3-selection": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.8.tgz", - "integrity": "sha512-pxCZUfQyedq/DIlPXIR5wE1mIH37omOdx1yxRudL3KZ4AC+156jMjOv1z5RVlGq62f8WX2kyO0hTVgEx627QFg==" - }, - "node_modules/@types/d3-shape": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.4.tgz", - "integrity": "sha512-M2/xsWPsjaZc5ifMKp1EBp0gqJG0eO/zlldJNOC85Y/5DGsBQ49gDkRJ2h5GY7ZVD6KUumvZWsylSbvTaJTqKg==", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dependencies": { - "@types/d3-path": "*" + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/d3-time": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.2.tgz", - "integrity": "sha512-kbdRXTmUgNfw5OTE3KZnFQn6XdIc4QGroN5UixgdrXATmYsdlPQS6pEut9tVlIojtzuFD4txs/L+Rq41AHtLpg==" - }, - "node_modules/@types/d3-time-format": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.2.tgz", - "integrity": "sha512-wr08C1Gh77qaN8JIkrn5Rz/bdt5M9bdEqFmEOcYhUSq2t2sHvLTBfb4XAtGB3D4hm0ubj50NXWWXoXyp5tPXDg==" + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/@types/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-GGTvzKccVEhxmRfJEB6zhY9ieT4UhGVUIQaBzFpUO9OXy2ycAlnPCSJLzmGGgqt3KVjqN3QCQB4g1rsZnHsWhg==" + "node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true }, - "node_modules/@types/d3-transition": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.6.tgz", - "integrity": "sha512-K0To23B5UxNwFtKORnS5JoNYvw/DnknU5MzhHIS9czJ/lTqFFDeU6w9lArOdoTl0cZFNdNrMJSFCbRCEHccH2w==", + "node_modules/dom-helpers": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", + "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", "dependencies": { - "@types/d3-selection": "*" + "@babel/runtime": "^7.1.2" } }, - "node_modules/@types/d3-zoom": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.6.tgz", - "integrity": "sha512-dGZQaXEu7aNcCL71LPpjB58IjoQNM9oDPfQuMUJ7N/fbkcIWGX2PnmUWO1jPJ+RLbZBpRUggJUX8twKRvo2hKQ==", + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", + "dev": true, "dependencies": { - "@types/d3-interpolate": "*", - "@types/d3-selection": "*" + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/@types/geojson": { - "version": "7946.0.12", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.12.tgz", - "integrity": "sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==" + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + "node_modules/dompurify": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", + "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" }, - "node_modules/@types/node": { - "version": "16.18.65", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.65.tgz", - "integrity": "sha512-5E9WgTy95B7i90oISjui9U5Zu7iExUPfU4ygtv4yXEy6zJFE3oQYHCnh5H1jZRPkjphJt2Ml3oQW6M0qtK534A==" + "node_modules/electron-to-chromium": { + "version": "1.4.763", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.763.tgz", + "integrity": "sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==", + "dev": true }, - "node_modules/@typescript-eslint/parser": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", - "integrity": "sha512-qK9TZ70eJtjojSUMrrEwA9ZDQ4N0e/AuoOIgXuNBorXYcBDk397D2r5MIe1B3cok/oCtdNC5j+lUUpVB+Dpb+w==", - "dependencies": { - "@typescript-eslint/scope-manager": "5.59.0", - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/typescript-estree": "5.59.0", - "debug": "^4.3.4" - }, + "node_modules/elkjs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", + "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.0.tgz", - "integrity": "sha512-tsoldKaMh7izN6BvkK6zRMINj4Z2d6gGhO2UsI8zGZY3XhLq1DndP3Ycjhi1JwdwPRwtLMW4EFPgpuKhbCGOvQ==", + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/enhanced-resolve": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10.13.0" } }, - "node_modules/@typescript-eslint/types": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.0.tgz", - "integrity": "sha512-yR2h1NotF23xFFYKHZs17QJnB51J/s+ud4PYU4MqdZbzeNxpgUr05+dNeCN/bb6raslHvGdd6BFCkVhpPk/ZeA==", + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=0.12" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.0.tgz", - "integrity": "sha512-sUNnktjmI8DyGzPdZ8dRwW741zopGxltGs/SAPgGL/AAgDpiLsCFLcMNSpbfXfmnNeHmK9h3wGmCkGRGAoUZAg==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.0", - "@typescript-eslint/visitor-keys": "5.59.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.0.tgz", - "integrity": "sha512-qZ3iXxQhanchCeaExlKPV3gDQFxMUmU35xfd5eCXB6+kUw1TUAbIy2n7QIrwz9s98DQLzNWyHp61fY0da4ZcbA==", + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", "dependencies": { - "@typescript-eslint/types": "5.59.0", - "eslint-visitor-keys": "^3.3.0" + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ace-builds": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.24.2.tgz", - "integrity": "sha512-zjvJiEw05BADxPMq5gN/Vgc9FgyiiDHpdy676Af1nJk8DF4ipgf0cNmV3wy8JHeQ6vezypEZV6pHQu9avO+WtQ==" - }, - "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "bin": { - "acorn": "bin/acorn" - }, + "node_modules/escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">=6" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, "engines": { - "node": ">=8" + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/eslint": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", + "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", "dependencies": { - "color-convert": "^2.0.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.2", + "@eslint/js": "8.38.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.4.0", + "espree": "^9.5.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/antd": { - "version": "5.12.1", - "resolved": "https://registry.npmjs.org/antd/-/antd-5.12.1.tgz", - "integrity": "sha512-lDTg4U/4MxDD4OK0sLM3D0ge+5nHKj27dUj4ufF1FhQKPcRkVnkCWJ43gb1Cn+S3ybvz7yfsiEv0v+QqWJgPlA==", + "node_modules/eslint-config-next": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.3.0.tgz", + "integrity": "sha512-6YEwmFBX0VjBd3ODGW9df0Is0FLaRFdMN8eAahQG9CN6LjQ28J8AFr19ngxqMSg7Qv6Uca/3VeeBosJh1bzu0w==", "dependencies": { - "@ant-design/colors": "^7.0.0", - "@ant-design/cssinjs": "^1.18.0", - "@ant-design/icons": "^5.2.6", - "@ant-design/react-slick": "~1.0.2", - "@babel/runtime": "^7.23.4", - "@ctrl/tinycolor": "^3.6.1", - "@rc-component/color-picker": "~1.4.1", - "@rc-component/mutate-observer": "^1.1.0", - "@rc-component/tour": "~1.11.0", - "@rc-component/trigger": "^1.18.2", - "classnames": "^2.3.2", - "copy-to-clipboard": "^3.3.3", - "dayjs": "^1.11.1", - "qrcode.react": "^3.1.0", - "rc-cascader": "~3.20.0", - "rc-checkbox": "~3.1.0", - "rc-collapse": "~3.7.2", - "rc-dialog": "~9.3.4", - "rc-drawer": "~6.5.2", - "rc-dropdown": "~4.1.0", - "rc-field-form": "~1.41.0", - "rc-image": "~7.5.1", - "rc-input": "~1.3.6", - "rc-input-number": "~8.4.0", - "rc-mentions": "~2.9.1", - "rc-menu": "~9.12.2", - "rc-motion": "^2.9.0", - "rc-notification": "~5.3.0", - "rc-pagination": "~4.0.1", - "rc-picker": "~3.14.6", - "rc-progress": "~3.5.1", - "rc-rate": "~2.12.0", - "rc-resize-observer": "^1.4.0", - "rc-segmented": "~2.2.2", - "rc-select": "~14.10.0", - "rc-slider": "~10.5.0", - "rc-steps": "~6.0.1", - "rc-switch": "~4.1.0", - "rc-table": "~7.36.0", - "rc-tabs": "~12.14.1", - "rc-textarea": "~1.5.3", - "rc-tooltip": "~6.1.2", - "rc-tree": "~5.8.2", - "rc-tree-select": "~5.15.0", - "rc-upload": "~4.3.5", - "rc-util": "^5.38.1", - "scroll-into-view-if-needed": "^3.1.0", - "throttle-debounce": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/ant-design" + "@next/eslint-plugin-next": "13.3.0", + "@rushstack/eslint-patch": "^1.1.3", + "@typescript-eslint/parser": "^5.42.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.31.7", + "eslint-plugin-react-hooks": "^4.5.0" }, "peerDependencies": { - "react": ">=16.9.0", - "react-dom": ">=16.9.0" + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "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==" + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } }, - "node_modules/aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "deep-equal": "^2.0.5" + "ms": "^2.1.1" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/eslint-import-resolver-typescript": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", + "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "get-tsconfig": "^4.5.0", + "globby": "^13.1.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" } }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" + "node_modules/eslint-import-resolver-typescript/node_modules/globby": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", + "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.11", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/array-tree-filter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", - "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "node_modules/eslint-import-resolver-typescript/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "debug": "^3.2.7" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", - "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.1.3" + "ms": "^2.1.1" } }, - "node_modules/ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==" - }, - "node_modules/async-validator": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", - "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "engines": { - "node": ">= 0.4" + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/axe-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", - "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", - "engines": { - "node": ">=4" + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/axobject-query": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", - "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", "dependencies": { - "deep-equal": "^2.0.5" + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "dependencies": { - "fill-range": "^7.0.1" + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" }, "engines": { - "node": ">=8" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dependencies": { - "streamsearch": "^1.1.0" + "esutils": "^2.0.2" }, "engines": { - "node": ">=10.16.0" + "node": ">=0.10.0" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001480", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", - "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/classcat": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz", - "integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==" - }, - "node_modules/classnames": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", - "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" - }, - "node_modules/client-only": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", - "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" - }, - "node_modules/clsx": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", - "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", + "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", "engines": { - "node": ">=6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/espree": { + "version": "9.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", + "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", "dependencies": { - "delayed-stream": "~1.0.0" + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.0" }, "engines": { - "node": ">= 0.8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/compute-scroll-into-view": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", - "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">= 0.6" + "node": ">=4" } }, - "node_modules/cookies-next": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cookies-next/-/cookies-next-4.1.0.tgz", - "integrity": "sha512-BREVc4TJT4NwXfyKjdjnYFXM6iRns+MYpCd34ClXuYqeisXnkPkbq7Ok9xaqi9mHmV6H2rwPE+p3EpMz4pF/kQ==", + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dependencies": { - "@types/cookie": "^0.4.1", - "@types/node": "^16.10.2", - "cookie": "^0.4.0" + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/copy-to-clipboard": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", - "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dependencies": { - "toggle-selection": "^1.0.6" + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" } }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, - "node_modules/d3-array": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, "dependencies": { - "internmap": "1 - 2" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/d3-dispatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", - "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, "engines": { - "node": ">=12" + "node": ">= 0.8.0" } }, - "node_modules/d3-drag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", - "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, "dependencies": { - "d3-dispatch": "1 - 3", - "d3-selection": "3" + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/d3-ease": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "node_modules/extract-files": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", + "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==", "engines": { - "node": ">=12" + "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/jaydenseric" } }, - "node_modules/d3-format": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", - "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-equals": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==" + }, + "node_modules/fast-glob": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, "engines": { - "node": ">=12" + "node": ">=8.6.0" } }, - "node_modules/d3-interpolate": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dependencies": { - "d3-color": "1 - 3" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=12" + "node": ">= 6" } }, - "node_modules/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", - "engines": { - "node": ">=12" + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" } }, - "node_modules/d3-scale": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, "dependencies": { - "d3-array": "2.10.0 - 3", - "d3-format": "1 - 3", - "d3-interpolate": "1.2.0 - 3", - "d3-time": "2.1.1 - 3", - "d3-time-format": "2 - 4" - }, - "engines": { - "node": ">=12" + "bser": "2.1.1" } }, - "node_modules/d3-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, "engines": { - "node": ">=12" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/d3-shape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dependencies": { - "d3-path": "^3.1.0" + "to-regex-range": "^5.0.1" }, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/d3-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dependencies": { - "d3-array": "2 - 3" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-time-format": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", - "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", "dependencies": { - "d3-time": "1 - 3" + "flatted": "^3.1.0", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=12" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/d3-timer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", - "engines": { - "node": ">=12" + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" } }, - "node_modules/d3-transition": { + "node_modules/form-data": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", - "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", "dependencies": { - "d3-color": "1 - 3", - "d3-dispatch": "1 - 3", - "d3-ease": "1 - 3", - "d3-interpolate": "1 - 3", - "d3-timer": "1 - 3" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=12" - }, - "peerDependencies": { - "d3-selection": "2 - 3" + "node": ">= 6" } }, - "node_modules/d3-zoom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", - "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", - "dependencies": { - "d3-dispatch": "1 - 3", - "d3-drag": "2 - 3", - "d3-interpolate": "1 - 3", - "d3-selection": "2 - 3", - "d3-transition": "2 - 3" - }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "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, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/damerau-levenshtein": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", - "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" - }, - "node_modules/dayjs": { - "version": "1.11.7", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", - "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", "dependencies": { - "ms": "2.1.2" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "dependencies": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" }, "engines": { "node": ">= 0.4" @@ -1704,172 +4712,186 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" + "node_modules/get-tsconfig": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", + "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/diff-match-patch": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", - "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "dependencies": { - "path-type": "^4.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=8" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dependencies": { - "esutils": "^2.0.2" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=6.0.0" + "node": ">=10.13.0" } }, - "node_modules/dom-helpers": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", - "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", + "node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dependencies": { - "@babel/runtime": "^7.1.2" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dompurify": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", - "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" - }, - "node_modules/elkjs": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", - "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" + "define-properties": "^1.1.3" }, "engines": { - "node": ">=10.13.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "node_modules/globalyzer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", + "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==" + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "get-intrinsic": "^1.1.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "node_modules/graphql": { + "version": "16.6.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", + "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-request": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.2.0.tgz", + "integrity": "sha512-pLhKIvnMyBERL0dtFI3medKqWOz/RhHdcgbZ+hMMIb32mEPa5MJSzS4AuXxfI4sRAu6JVVk5tvXuGfCWl9JYWQ==", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "@graphql-typed-document-node/core": "^3.1.1", + "cross-fetch": "^3.1.5", + "extract-files": "^9.0.0", + "form-data": "^3.0.0" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" } }, - "node_modules/es-shim-unscopables": { + "node_modules/has-property-descriptors": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", "dependencies": { - "has": "^1.0.3" + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", "engines": { "node": ">= 0.4" }, @@ -1877,1230 +4899,1530 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", - "integrity": "sha512-pIdsD2jwlUGf/U38Jv97t8lq6HpaU/G9NKbYmpWpZGw3LdTNhZLbJePqxOXGB5+JEKfOPU/XLxYxFh03nr1KTg==", + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.38.0", - "@humanwhocodes/config-array": "^0.11.8", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" + "has-symbols": "^1.0.2" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-config-next": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.3.0.tgz", - "integrity": "sha512-6YEwmFBX0VjBd3ODGW9df0Is0FLaRFdMN8eAahQG9CN6LjQ28J8AFr19ngxqMSg7Qv6Uca/3VeeBosJh1bzu0w==", + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, "dependencies": { - "@next/eslint-plugin-next": "13.3.0", - "@rushstack/eslint-patch": "^1.1.3", - "@typescript-eslint/parser": "^5.42.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-import-resolver-typescript": "^3.5.2", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.31.7", - "eslint-plugin-react-hooks": "^4.5.0" - }, - "peerDependencies": { - "eslint": "^7.23.0 || ^8.0.0", - "typescript": ">=3.3.1" + "whatwg-encoding": "^2.0.0" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": ">=12" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, "dependencies": { - "ms": "^2.1.1" + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/eslint-import-resolver-typescript": { - "version": "3.5.5", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", - "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, "dependencies": { - "debug": "^4.3.4", - "enhanced-resolve": "^5.12.0", - "eslint-module-utils": "^2.7.4", - "get-tsconfig": "^4.5.0", - "globby": "^13.1.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "synckit": "^0.8.5" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" - }, - "peerDependencies": { - "eslint": "*", - "eslint-plugin-import": "*" + "node": ">= 6" } }, - "node_modules/eslint-import-resolver-typescript/node_modules/globby": { - "version": "13.1.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", - "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/eslint-import-resolver-typescript/node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "engines": { - "node": ">=12" + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, "dependencies": { - "debug": "^3.2.7" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" }, "engines": { - "node": ">=4" + "node": ">=8" }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dependencies": { - "ms": "^2.1.1" + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" } }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "dependencies": { - "ms": "^2.1.1" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dependencies": { - "esutils": "^2.0.2" + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "engines": { + "node": ">=12" } }, - "node_modules/eslint-plugin-jsx-a11y": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", - "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", "dependencies": { - "@babel/runtime": "^7.20.7", - "aria-query": "^5.1.3", - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "ast-types-flow": "^0.0.7", - "axe-core": "^4.6.2", - "axobject-query": "^3.1.1", - "damerau-levenshtein": "^1.0.8", - "emoji-regex": "^9.2.2", - "has": "^1.0.3", - "jsx-ast-utils": "^3.3.3", - "language-tags": "=1.0.5", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "semver": "^6.3.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=4.0" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react": { - "version": "7.32.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", - "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flatmap": "^1.3.1", - "array.prototype.tosorted": "^1.1.1", - "doctrine": "^2.1.0", - "estraverse": "^5.3.0", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.6", - "object.fromentries": "^2.0.6", - "object.hasown": "^1.1.2", - "object.values": "^1.1.6", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.4", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.8" + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "engines": { - "node": ">=10" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "node_modules/is-core-module": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", + "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", "dependencies": { - "esutils": "^2.0.2" + "has": "^1.0.3" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", - "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" + "has-tostringtag": "^1.0.0" }, - "bin": { - "resolve": "bin/resolve" + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "is-docker": "cli.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=0.10.0" } }, - "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", - "dependencies": { - "acorn": "^8.8.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" - }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=8" } }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dependencies": { - "estraverse": "^5.1.0" - }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, "engines": { - "node": ">=0.10" + "node": ">=6" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dependencies": { - "estraverse": "^5.2.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": ">=4.0" + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "engines": { - "node": ">=4.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "engines": { - "node": ">=0.10.0" + "node": ">=0.12.0" } }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" - }, - "node_modules/extract-files": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", - "integrity": "sha512-CvdFfHkC95B4bBBk36hcEmvdR2awOdhhVUYH6S/zrVj3477zven/fJMYg7121h4T1xHZC+tetUpubpAhxwI7hQ==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, "engines": { - "node": "^10.17.0 || ^12.0.0 || >= 13.7.0" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/jaydenseric" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } }, - "node_modules/fast-equals": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", - "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==" + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true }, - "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=8.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", "dependencies": { - "is-glob": "^4.0.1" + "call-bind": "^1.0.2" }, - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", - "dependencies": { - "reusify": "^1.0.4" + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dependencies": { - "flat-cache": "^3.0.4" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dependencies": { - "to-regex-range": "^5.0.1" + "has-symbols": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "call-bind": "^1.0.2" }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", "dependencies": { - "is-callable": "^1.1.3" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "is-docker": "^2.0.0" }, "engines": { - "node": ">= 6" + "node": ">=8" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/get-tsconfig": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", - "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, "dependencies": { - "is-glob": "^4.0.3" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">=10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, "dependencies": { - "type-fest": "^0.20.2" - }, + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/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, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/jest-circus/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, "dependencies": { - "define-properties": "^1.1.3" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==" + "node_modules/jest-circus/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/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, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/jest-cli/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + "node_modules/jest-cli/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, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + "node_modules/jest-cli/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true }, - "node_modules/graphql": { - "version": "16.6.0", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", - "integrity": "sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==", + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/graphql-request": { + "node_modules/jest-diff/node_modules/ansi-styles": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-5.2.0.tgz", - "integrity": "sha512-pLhKIvnMyBERL0dtFI3medKqWOz/RhHdcgbZ+hMMIb32mEPa5MJSzS4AuXxfI4sRAu6JVVk5tvXuGfCWl9JYWQ==", - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "cross-fetch": "^3.1.5", - "extract-files": "^9.0.0", - "form-data": "^3.0.0" + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" }, - "peerDependencies": { - "graphql": "14 - 16" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/jest-diff/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, "dependencies": { - "function-bind": "^1.1.1" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/jest-diff/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "node_modules/jest-each/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, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "engines": { - "node": ">= 0.4" + "node_modules/jest-each/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, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/jest-each/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, "engines": { - "node": ">= 4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-junit": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", + "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + }, "engines": { - "node": ">=0.8.19" + "node": ">=10.12.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/jest-junit/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "node_modules/jest-leak-detector/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, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/jest-leak-detector/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, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dependencies": { - "has-bigints": "^1.0.1" + "node_modules/jest-matcher-utils/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, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/jest-matcher-utils/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, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/jest-message-util/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, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-core-module": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.0.tgz", - "integrity": "sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==", + "node_modules/jest-message-util/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, "dependencies": { - "has": "^1.0.3" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/jest-message-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "bin": { - "is-docker": "cli.js" - }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=6" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, "dependencies": { - "is-extglob": "^2.1.1" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "engines": { - "node": ">= 0.4" + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-runtime/node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, "engines": { - "node": ">=0.12.0" + "node": ">=8" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dependencies": { - "has-tostringtag": "^1.0.0" + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/jest-snapshot/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, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/jest-snapshot/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, "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, "dependencies": { - "has-tostringtag": "^1.0.0" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/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, + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dependencies": { - "has-symbols": "^1.0.2" - }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/jest-validate/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, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/jest-validate/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { - "is-docker": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, "node_modules/js-sdsl": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.0.tgz", @@ -3126,6 +6448,117 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3167,6 +6600,15 @@ "node": ">=4.0" } }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -3180,6 +6622,15 @@ "language-subtag-registry": "~0.3.2" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3192,6 +6643,12 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3253,6 +6710,57 @@ "node": ">=10" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3292,6 +6800,24 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3311,6 +6837,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -3409,6 +6947,45 @@ } } }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nwsapi": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", + "integrity": "sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==", + "dev": true + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3530,6 +7107,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", @@ -3590,6 +7182,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3601,6 +7202,36 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3643,15 +7274,88 @@ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/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, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/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, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/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, + "dependencies": { + "p-try": "^2.0.0" + }, "engines": { - "node": ">=8.6" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/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, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, "node_modules/postcss": { @@ -3685,6 +7389,51 @@ "node": ">= 0.8.0" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -3695,6 +7444,12 @@ "react-is": "^16.13.1" } }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, "node_modules/punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", @@ -3703,6 +7458,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/qrcode.react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", @@ -3711,6 +7482,12 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4540,6 +8317,19 @@ "decimal.js-light": "^2.4.1" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", @@ -4561,6 +8351,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -4582,6 +8387,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -4590,6 +8416,15 @@ "node": ">=4" } }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -4648,6 +8483,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -4710,6 +8563,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -4718,6 +8583,15 @@ "node": ">=8" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -4726,6 +8600,43 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -4750,6 +8661,39 @@ "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "node_modules/string.prototype.matchall": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", @@ -4829,6 +8773,27 @@ "node": ">=4" } }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -4889,6 +8854,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "node_modules/synckit": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", @@ -4912,6 +8883,20 @@ "node": ">=6" } }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4939,6 +8924,21 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4955,6 +8955,21 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -5006,6 +9021,15 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -5057,6 +9081,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz", + "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.0" + }, + "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", @@ -5065,6 +9128,16 @@ "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==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -5081,6 +9154,20 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/victory-vendor": { "version": "36.7.0", "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.7.0.tgz", @@ -5102,6 +9189,27 @@ "d3-timer": "^3.0.1" } }, + "node_modules/w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, "node_modules/web-worker": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", @@ -5112,6 +9220,27 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -5177,30 +9306,138 @@ "is-typed-array": "^1.1.10" }, "engines": { - "node": ">= 0.4" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "dev": true, + "engines": { + "node": ">=10.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -5241,6 +9478,22 @@ } }, "dependencies": { + "@adobe/css-tools": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.3.3.tgz", + "integrity": "sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "@ant-design/colors": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.0.tgz", @@ -5292,6 +9545,409 @@ "throttle-debounce": "^5.0.0" } }, + "@babel/code-frame": { + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "dev": true, + "requires": { + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", + "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "dev": true + }, + "@babel/core": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", + "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.24.5", + "@babel/helpers": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", + "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "dev": true, + "requires": { + "@babel/types": "^7.24.5", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", + "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.23.5", + "@babel/helper-validator-option": "^7.23.5", + "browserslist": "^4.22.2", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "dev": true, + "requires": { + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.24.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", + "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "dev": true, + "requires": { + "@babel/types": "^7.24.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", + "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-module-imports": "^7.24.3", + "@babel/helper-simple-access": "^7.24.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/helper-validator-identifier": "^7.24.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz", + "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==", + "dev": true + }, + "@babel/helper-simple-access": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", + "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "dev": true, + "requires": { + "@babel/types": "^7.24.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", + "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.24.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", + "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", + "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "dev": true, + "requires": { + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.5", + "@babel/types": "^7.24.5" + } + }, + "@babel/highlight": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.5.tgz", + "integrity": "sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.24.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", + "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "dev": true + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", + "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", + "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.24.0" + } + }, "@babel/runtime": { "version": "7.23.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz", @@ -5300,6 +9956,60 @@ "regenerator-runtime": "^0.14.0" } }, + "@babel/template": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + } + }, + "@babel/traverse": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", + "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.24.2", + "@babel/generator": "^7.24.5", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.24.5", + "@babel/parser": "^7.24.5", + "@babel/types": "^7.24.5", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.24.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", + "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.24.1", + "@babel/helper-validator-identifier": "^7.24.5", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "@ctrl/tinycolor": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", @@ -5320,60 +10030,457 @@ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "requires": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", + "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==" + }, + "@eslint/eslintrc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", + "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.1", + "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" + } + }, + "@eslint/js": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", + "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==" + }, + "@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "requires": {} + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + }, + "@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, + "requires": { + "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" + }, + "dependencies": { + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "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, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "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, + "requires": { + "p-locate": "^4.1.0" + } + }, + "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, + "requires": { + "p-try": "^2.0.0" + } + }, + "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, + "requires": { + "p-limit": "^2.2.0" + } + }, + "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 + } + } + }, + "@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 + }, + "@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "requires": { + "@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" + } + }, + "@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, + "requires": { + "@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" + }, + "dependencies": { + "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 + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "@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, + "requires": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" } }, - "@eslint-community/regexpp": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.0.tgz", - "integrity": "sha512-vITaYzIcNmjn5tF5uxcZ/ft7/RXGrMUIS9HalWckEOF6ESiwXKoMzAQf2UW0aVd6rnOeExTJVd5hmWXucBKGXQ==" + "@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, + "requires": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + } }, - "@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "@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, "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.5.1", - "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" + "jest-get-type": "^29.6.3" } }, - "@eslint/js": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.38.0.tgz", - "integrity": "sha512-IoD2MfUnOV58ghIHCiil01PcohxjbYR/qCxsoC+xNgUwh1EY8jOOrYmu3d3a71+tJJ23uscEV4X2HJWMsPJu4g==" + "@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, + "requires": { + "@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" + } }, - "@graphql-typed-document-node/core": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", - "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", - "requires": {} + "@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + } }, - "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.5" + "@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" + } + }, + "@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, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@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, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@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, + "requires": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@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, + "requires": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" } }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==" + "@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "requires": { + "@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" + } + }, + "@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, + "requires": { + "@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" + } + }, + "@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==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true }, - "@humanwhocodes/object-schema": { + "@jridgewell/set-array": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==" + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@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==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } }, "@next/env": { "version": "13.3.0", @@ -5628,6 +10735,30 @@ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==" }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, "@swc/helpers": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz", @@ -5636,6 +10767,122 @@ "tslib": "^2.4.0" } }, + "@testing-library/dom": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.1.0.tgz", + "integrity": "sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true + } + } + }, + "@testing-library/jest-dom": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.4.5.tgz", + "integrity": "sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==", + "dev": true, + "requires": { + "@adobe/css-tools": "^4.3.2", + "@babel/runtime": "^7.9.2", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "dependencies": { + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + } + } + }, + "@testing-library/react": { + "version": "15.0.7", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz", + "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^10.0.0", + "@types/react-dom": "^18.0.0" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, + "@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", + "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, "@types/cookie": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", @@ -5868,6 +11115,50 @@ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.12.tgz", "integrity": "sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==" }, + "@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jsdom": { + "version": "20.0.1", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz", + "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -5878,6 +11169,58 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.65.tgz", "integrity": "sha512-5E9WgTy95B7i90oISjui9U5Zu7iExUPfU4ygtv4yXEy6zJFE3oQYHCnh5H1jZRPkjphJt2Ml3oQW6M0qtK534A==" }, + "@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "devOptional": true + }, + "@types/react": { + "version": "18.3.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz", + "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==", + "devOptional": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true + }, + "@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true + }, + "@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true + }, "@typescript-eslint/parser": { "version": "5.59.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.0.tgz", @@ -5926,6 +11269,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, "ace-builds": { "version": "1.24.2", "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.24.2.tgz", @@ -5936,12 +11285,37 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" }, + "acorn-globals": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz", + "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==", + "dev": true, + "requires": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "requires": {} }, + "acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -5953,6 +11327,23 @@ "uri-js": "^4.2.2" } }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + } + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -6021,17 +11412,27 @@ "throttle-debounce": "^5.0.0" } }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "aria-query": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", - "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", "requires": { - "deep-equal": "^2.0.5" + "dequal": "^2.0.3" } }, "array-buffer-byte-length": { @@ -6132,6 +11533,97 @@ "deep-equal": "^2.0.5" } }, + "babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "requires": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6154,6 +11646,33 @@ "fill-range": "^7.0.1" } }, + "browserslist": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -6176,10 +11695,16 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, "caniuse-lite": { - "version": "1.0.30001480", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001480.tgz", - "integrity": "sha512-q7cpoPPvZYgtyC4VaBSN0Bt+PJ4c4EYRf0DrduInOz2SkFpHD5p3LnvEpqBp7UnJn+8x1Ogl1s38saUxe+ihQQ==" + "version": "1.0.30001617", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001617.tgz", + "integrity": "sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==" }, "chalk": { "version": "4.1.2", @@ -6190,6 +11715,24 @@ "supports-color": "^7.1.0" } }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz", + "integrity": "sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==", + "dev": true + }, "classcat": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz", @@ -6205,11 +11748,34 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, "clsx": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==" }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -6241,6 +11807,12 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", @@ -6264,6 +11836,76 @@ "toggle-selection": "^1.0.6" } }, + "create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "dependencies": { + "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 + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, "cross-fetch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", @@ -6282,6 +11924,35 @@ "which": "^2.0.1" } }, + "css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true + }, + "cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, "csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", @@ -6412,6 +12083,44 @@ "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==" }, + "data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "dependencies": { + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } + }, "dayjs": { "version": "1.11.7", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", @@ -6425,11 +12134,24 @@ "ms": "2.1.2" } }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, "decimal.js-light": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==" }, + "dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "requires": {} + }, "deep-equal": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", @@ -6459,6 +12181,12 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true + }, "define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -6478,11 +12206,28 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, "diff-match-patch": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz", "integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==" }, + "diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -6499,6 +12244,12 @@ "esutils": "^2.0.2" } }, + "dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true + }, "dom-helpers": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", @@ -6507,16 +12258,45 @@ "@babel/runtime": "^7.1.2" } }, + "domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "requires": { + "webidl-conversions": "^7.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + } + } + }, "dompurify": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" }, + "electron-to-chromium": { + "version": "1.4.763", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.763.tgz", + "integrity": "sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==", + "dev": true + }, "elkjs": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.8.2.tgz", "integrity": "sha512-L6uRgvZTH+4OF5NE/MBbzQx/WYpru1xCBE9respNj6qznEewGUIfhzmm7horWWxbNO2M0WckQypGctR8lH79xQ==" }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, "emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -6531,6 +12311,21 @@ "tapable": "^2.2.0" } }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, "es-abstract": { "version": "1.21.2", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", @@ -6616,11 +12411,29 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + } + }, "eslint": { "version": "8.38.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.38.0.tgz", @@ -6908,6 +12721,12 @@ "eslint-visitor-keys": "^3.4.0" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, "esquery": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", @@ -6939,6 +12758,42 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + } + }, "extract-files": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-9.0.0.tgz", @@ -6994,6 +12849,15 @@ "reusify": "^1.0.4" } }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -7056,6 +12920,13 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -7077,6 +12948,18 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -7087,6 +12970,18 @@ "has-symbols": "^1.0.3" } }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, "get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -7239,6 +13134,57 @@ "has-symbols": "^1.0.2" } }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, "ignore": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", @@ -7253,11 +13199,27 @@ "resolve-from": "^4.0.0" } }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -7306,6 +13268,12 @@ "is-typed-array": "^1.1.10" } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, "is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -7354,6 +13322,18 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7390,6 +13370,12 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==" }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -7412,6 +13398,12 @@ "call-bind": "^1.0.2" } }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -7453,32 +13445,790 @@ "call-bind": "^1.0.2" } }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", + "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "dev": true, + "requires": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + } + }, + "jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "requires": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "dependencies": { + "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 + }, + "jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + } + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-environment-jsdom": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz", + "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + } + }, + "jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + } + }, + "jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true + }, + "jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-junit": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", + "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } + } + }, + "jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "requires": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } + } + }, + "jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true + }, + "jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "requires": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + } + }, + "jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "requires": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + } + }, + "jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + } + } + }, + "jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + } + }, + "jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "dependencies": { + "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 + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "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, + "requires": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + } + }, + "react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true + } } }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, "requires": { - "is-docker": "^2.0.0" + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" } }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } }, "js-sdsl": { "version": "4.4.0", @@ -7498,6 +14248,90 @@ "argparse": "^2.0.1" } }, + "jsdom": { + "version": "20.0.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", + "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "dependencies": { + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -7533,6 +14367,12 @@ "object.assign": "^4.1.3" } }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, "language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -7546,6 +14386,12 @@ "language-subtag-registry": "~0.3.2" } }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -7555,6 +14401,12 @@ "type-check": "~0.4.0" } }, + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7604,6 +14456,44 @@ "yallist": "^4.0.0" } }, + "lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + }, + "dependencies": { + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7631,6 +14521,18 @@ "mime-db": "1.52.0" } }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -7644,6 +14546,12 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -7689,6 +14597,39 @@ "whatwg-url": "^5.0.0" } }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-releases": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "nwsapi": { + "version": "2.2.9", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.9.tgz", + "integrity": "sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7771,6 +14712,15 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, "open": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", @@ -7810,6 +14760,12 @@ "p-limit": "^3.0.2" } }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -7818,6 +14774,27 @@ "callsites": "^3.0.0" } }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "requires": { + "entities": "^4.4.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7853,6 +14830,60 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "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, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "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, + "requires": { + "p-locate": "^4.1.0" + } + }, + "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, + "requires": { + "p-try": "^2.0.0" + } + }, + "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, + "requires": { + "p-limit": "^2.2.0" + } + } + } + }, "postcss": { "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", @@ -7868,6 +14899,41 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "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 + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + } + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, "prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -7878,17 +14944,35 @@ "react-is": "^16.13.1" } }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, "punycode": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, + "pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true + }, "qrcode.react": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", "integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==", "requires": {} }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -8459,6 +15543,16 @@ "decimal.js-light": "^2.4.1" } }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, "regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", @@ -8474,6 +15568,18 @@ "functions-have-names": "^1.2.2" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -8489,11 +15595,34 @@ "supports-preserve-symlinks-flag": "^1.0.0" } }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + }, + "dependencies": { + "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 + } + } + }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -8525,6 +15654,21 @@ "is-regex": "^1.1.4" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, "scheduler": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", @@ -8572,16 +15716,67 @@ "object-inspect": "^1.9.0" } }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, "stop-iteration-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", @@ -8600,6 +15795,35 @@ "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + } + } + }, "string.prototype.matchall": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", @@ -8658,6 +15882,21 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -8689,6 +15928,12 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, "synckit": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", @@ -8703,6 +15948,17 @@ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==" }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -8727,6 +15983,18 @@ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8740,6 +16008,18 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -8784,6 +16064,12 @@ "prelude-ls": "^1.2.1" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -8816,6 +16102,22 @@ "which-boxed-primitive": "^1.0.2" } }, + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.15.tgz", + "integrity": "sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==", + "dev": true, + "requires": { + "escalade": "^3.1.2", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -8824,6 +16126,16 @@ "punycode": "^2.1.0" } }, + "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==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -8835,6 +16147,17 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" }, + "v8-to-istanbul": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + } + }, "victory-vendor": { "version": "36.7.0", "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.7.0.tgz", @@ -8856,6 +16179,24 @@ "d3-timer": "^3.0.1" } }, + "w3c-xmlserializer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz", + "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==", + "dev": true, + "requires": { + "xml-name-validator": "^4.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, "web-worker": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.2.0.tgz", @@ -8866,6 +16207,21 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true + }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -8924,16 +16280,89 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "ws": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.0.tgz", + "integrity": "sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==", + "dev": true, + "requires": {} + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/ontrack-web-core/package.json b/ontrack-web-core/package.json index 8a4c9235ca2..79f5d45a27f 100644 --- a/ontrack-web-core/package.json +++ b/ontrack-web-core/package.json @@ -6,7 +6,8 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "next lint" + "lint": "next lint", + "test": "jest" }, "dependencies": { "ace-builds": "^1.24.2", @@ -34,5 +35,12 @@ "recharts": "^2.10.3", "uuid": "^9.0.0", "web-worker": "^1.2.0" + }, + "devDependencies": { + "@testing-library/jest-dom": "^6.4.5", + "@testing-library/react": "^15.0.7", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jest-junit": "^16.0.0" } } diff --git a/ontrack-web-core/pages/extension/notifications/recordings.js b/ontrack-web-core/pages/extension/notifications/recordings.js index 2a40f22ee38..32124f4e524 100644 --- a/ontrack-web-core/pages/extension/notifications/recordings.js +++ b/ontrack-web-core/pages/extension/notifications/recordings.js @@ -1,5 +1,4 @@ import MainLayout from "@components/layouts/MainLayout"; -import SubscriptionsGlobalView from "@components/extension/notifications/SubscriptionsGlobalView"; import NotificationRecordingsView from "@components/extension/notifications/NotificationRecordingsView"; export default function NotificationRecordingsPage() { diff --git a/ontrack-web-core/pages/extension/workflows/audit.js b/ontrack-web-core/pages/extension/workflows/audit.js new file mode 100644 index 00000000000..99c49d478eb --- /dev/null +++ b/ontrack-web-core/pages/extension/workflows/audit.js @@ -0,0 +1,14 @@ +import MainLayout from "@components/layouts/MainLayout"; +import WorkflowsAuditView from "@components/extension/workflows/WorkflowsAuditView"; + +export default function WorkflowsAudit() { + return ( + <> +
+ + + +
+ + ) +} \ No newline at end of file diff --git a/ontrack-web-core/pages/extension/workflows/instances/[id].js b/ontrack-web-core/pages/extension/workflows/instances/[id].js new file mode 100644 index 00000000000..3581967029a --- /dev/null +++ b/ontrack-web-core/pages/extension/workflows/instances/[id].js @@ -0,0 +1,19 @@ +import MainLayout from "@components/layouts/MainLayout"; +import WorkflowsAuditView from "@components/extension/workflows/WorkflowsAuditView"; +import {useRouter} from "next/router"; +import WorkflowInstanceView from "@components/extension/workflows/WorkflowInstanceView"; + +export default function WorkflowInstancePage() { + const router = useRouter() + const {id} = router.query + + return ( + <> +
+ + + +
+ + ) +} \ No newline at end of file diff --git a/ontrack-web-core/styles/globals.css b/ontrack-web-core/styles/globals.css index 73c3b312683..856cd56b705 100644 --- a/ontrack-web-core/styles/globals.css +++ b/ontrack-web-core/styles/globals.css @@ -166,3 +166,13 @@ button.ot-validation-stamp-filter-edition { border-radius: 4px; padding: 2px; } + +/** + * Workflows + */ + +.ot-workflow-node-info-title { + display: block; + margin-top: 1em; + border-top: solid 1px lightgray; +} diff --git a/settings.gradle.kts b/settings.gradle.kts index 64455305a9e..40e33b5277f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -71,3 +71,4 @@ include(":ontrack-extension-tfc") include(":ontrack-extension-recordings") include(":ontrack-extension-hook") include(":ontrack-extension-queue") +include(":ontrack-extension-workflows")