diff --git a/async/async-commons-api/src/main/java/org/reactivecommons/async/api/HandlerRegistry.java b/async/async-commons-api/src/main/java/org/reactivecommons/async/api/HandlerRegistry.java index 3b5b65f2..83e5882f 100644 --- a/async/async-commons-api/src/main/java/org/reactivecommons/async/api/HandlerRegistry.java +++ b/async/async-commons-api/src/main/java/org/reactivecommons/async/api/HandlerRegistry.java @@ -29,6 +29,7 @@ @SuppressWarnings({"unchecked", "unused"}) public final class HandlerRegistry { public static final String DEFAULT_DOMAIN = "app"; + private static final String UNRESOLVED_DOMAIN = "__default__"; private final RegisteredDomainHandlers> domainEventListeners = new RegisteredDomainHandlers<>(); private final RegisteredDomainHandlers> dynamicEventHandlers = @@ -41,16 +42,19 @@ public final class HandlerRegistry { private final RegisteredDomainHandlers queueHandlers = new RegisteredDomainHandlers<>(); + public static String getUnresolvedDomain() { + return UNRESOLVED_DOMAIN; + } public static HandlerRegistry register() { HandlerRegistry instance = new HandlerRegistry(); - instance.domainEventListeners.put(DEFAULT_DOMAIN, new CopyOnWriteArrayList<>()); + instance.domainEventListeners.put(UNRESOLVED_DOMAIN, new CopyOnWriteArrayList<>()); return instance; } //events: DomainEvent public HandlerRegistry listenEvent(String eventName, DomainEventHandler handler, Class eventClass) { - return listenDomainEvent(DEFAULT_DOMAIN, eventName, handler, eventClass); + return listenDomainEvent(UNRESOLVED_DOMAIN, eventName, handler, eventClass); } public HandlerRegistry listenDomainEvent(String domain, String eventName, DomainEventHandler handler, @@ -61,7 +65,7 @@ public HandlerRegistry listenDomainEvent(String domain, String eventName, Do // events: CloudEvent public HandlerRegistry listenCloudEvent(String eventName, CloudEventHandler handler) { - return listenDomainCloudEvent(DEFAULT_DOMAIN, eventName, handler); + return listenDomainCloudEvent(UNRESOLVED_DOMAIN, eventName, handler); } public HandlerRegistry listenDomainCloudEvent(String domain, String eventName, CloudEventHandler handler) { @@ -71,7 +75,7 @@ public HandlerRegistry listenDomainCloudEvent(String domain, String eventName, C // events: RawMessage public HandlerRegistry listenRawEvent(String eventName, RawEventHandler handler) { - return listenDomainRawEvent(DEFAULT_DOMAIN, eventName, handler); + return listenDomainRawEvent(UNRESOLVED_DOMAIN, eventName, handler); } public HandlerRegistry listenDomainRawEvent(String domain, String eventName, RawEventHandler handler) { @@ -82,7 +86,7 @@ public HandlerRegistry listenDomainRawEvent(String domain, String eventName, Raw // notifications: DomainEvent public HandlerRegistry listenNotificationEvent(String eventName, DomainEventHandler handler, Class eventClass) { - return listenNotificationEvent(DEFAULT_DOMAIN, eventName, handler, eventClass); + return listenNotificationEvent(UNRESOLVED_DOMAIN, eventName, handler, eventClass); } public HandlerRegistry listenNotificationEvent(String domain, String eventName, DomainEventHandler handler, @@ -93,7 +97,7 @@ public HandlerRegistry listenNotificationEvent(String domain, String eventNa // notifications: CloudEvent public HandlerRegistry listenNotificationCloudEvent(String eventName, CloudEventHandler handler) { - return listenNotificationCloudEvent(DEFAULT_DOMAIN, eventName, handler); + return listenNotificationCloudEvent(UNRESOLVED_DOMAIN, eventName, handler); } public HandlerRegistry listenNotificationCloudEvent(String domain, String eventName, CloudEventHandler handler) { @@ -103,7 +107,7 @@ public HandlerRegistry listenNotificationCloudEvent(String domain, String eventN // notifications: RawMessage public HandlerRegistry listenNotificationRawEvent(String eventName, RawEventHandler handler) { - return listenNotificationRawEvent(DEFAULT_DOMAIN, eventName, handler); + return listenNotificationRawEvent(UNRESOLVED_DOMAIN, eventName, handler); } public HandlerRegistry listenNotificationRawEvent(String domain, String eventName, RawEventHandler handler) { @@ -114,20 +118,20 @@ public HandlerRegistry listenNotificationRawEvent(String domain, String eventNam // dynamic: DomainEvent supported only for default domain public HandlerRegistry handleDynamicEvents(String eventNamePattern, DomainEventHandler handler, Class eventClass) { - dynamicEventHandlers.add(DEFAULT_DOMAIN, new RegisteredEventListener<>(eventNamePattern, handler, eventClass)); + dynamicEventHandlers.add(UNRESOLVED_DOMAIN, new RegisteredEventListener<>(eventNamePattern, handler, eventClass)); return this; } // dynamic: CloudEvent supported only for default domain public HandlerRegistry handleDynamicCloudEvents(String eventNamePattern, CloudEventHandler handler) { - dynamicEventHandlers.add(DEFAULT_DOMAIN, new RegisteredEventListener<>(eventNamePattern, handler, + dynamicEventHandlers.add(UNRESOLVED_DOMAIN, new RegisteredEventListener<>(eventNamePattern, handler, CloudEvent.class)); return this; } // commands: Command public HandlerRegistry handleCommand(String commandName, DomainCommandHandler fn, Class commandClass) { - return handleCommand(DEFAULT_DOMAIN, commandName, fn, commandClass); + return handleCommand(UNRESOLVED_DOMAIN, commandName, fn, commandClass); } public HandlerRegistry handleCommand(String domain, String commandName, DomainCommandHandler fn, @@ -138,7 +142,7 @@ public HandlerRegistry handleCommand(String domain, String commandName, Doma // commands: CloudEvent public HandlerRegistry handleCloudEventCommand(String commandName, CloudCommandHandler handler) { - return handleCloudEventCommand(DEFAULT_DOMAIN, commandName, handler); + return handleCloudEventCommand(UNRESOLVED_DOMAIN, commandName, handler); } public HandlerRegistry handleCloudEventCommand(String domain, String commandName, CloudCommandHandler handler) { @@ -148,7 +152,7 @@ public HandlerRegistry handleCloudEventCommand(String domain, String commandName // commands: RawMessage public HandlerRegistry handleRawCommand(RawCommandHandler handler) { - return handleRawCommand(DEFAULT_DOMAIN, handler); + return handleRawCommand(UNRESOLVED_DOMAIN, handler); } public HandlerRegistry handleRawCommand(String domain, RawCommandHandler handler) { @@ -158,26 +162,26 @@ public HandlerRegistry handleRawCommand(String domain, RawCommandHandler hand // queries: Query public HandlerRegistry serveQuery(String resource, QueryHandler handler, Class queryClass) { - handlers.add(DEFAULT_DOMAIN, new RegisteredQueryHandler<>(resource, (ignored, message) -> + handlers.add(UNRESOLVED_DOMAIN, new RegisteredQueryHandler<>(resource, (ignored, message) -> handler.handle(message), queryClass )); return this; } public HandlerRegistry serveQuery(String resource, QueryHandlerDelegate handler, Class queryClass) { - handlers.add(DEFAULT_DOMAIN, new RegisteredQueryHandler<>(resource, handler, queryClass)); + handlers.add(UNRESOLVED_DOMAIN, new RegisteredQueryHandler<>(resource, handler, queryClass)); return this; } public HandlerRegistry serveCloudEventQuery(String resource, QueryHandler handler) { - handlers.add(DEFAULT_DOMAIN, new RegisteredQueryHandler<>(resource, (ignored, message) -> + handlers.add(UNRESOLVED_DOMAIN, new RegisteredQueryHandler<>(resource, (ignored, message) -> handler.handle(message), CloudEvent.class )); return this; } public HandlerRegistry serveCloudEventQuery(String resource, QueryHandlerDelegate handler) { - handlers.add(DEFAULT_DOMAIN, new RegisteredQueryHandler<>(resource, handler, CloudEvent.class)); + handlers.add(UNRESOLVED_DOMAIN, new RegisteredQueryHandler<>(resource, handler, CloudEvent.class)); return this; } @@ -192,7 +196,7 @@ public HandlerRegistry listenQueue(String domain, String queueName, RawEventHand public HandlerRegistry listenQueue(String queueName, RawEventHandler handler, TopologyHandlerSetup topologyCreator) { - queueHandlers.add(DEFAULT_DOMAIN, new RegisteredQueueListener(queueName, handler, topologyCreator)); + queueHandlers.add(UNRESOLVED_DOMAIN, new RegisteredQueueListener(queueName, handler, topologyCreator)); return this; } @@ -214,7 +218,7 @@ public HandlerRegistry handleDynamicEvents(String eventNamePattern, DomainEv @Deprecated(forRemoval = true) public HandlerRegistry handleCommand(String commandName, DomainCommandHandler handler) { - commandHandlers.add(DEFAULT_DOMAIN, new RegisteredCommandHandler<>(commandName, handler, + commandHandlers.add(UNRESOLVED_DOMAIN, new RegisteredCommandHandler<>(commandName, handler, inferGenericParameterType(handler))); return this; } diff --git a/async/async-commons-api/src/main/java/org/reactivecommons/async/api/handlers/registered/RegisteredDomainHandlers.java b/async/async-commons-api/src/main/java/org/reactivecommons/async/api/handlers/registered/RegisteredDomainHandlers.java index 1410e005..e05daa54 100644 --- a/async/async-commons-api/src/main/java/org/reactivecommons/async/api/handlers/registered/RegisteredDomainHandlers.java +++ b/async/async-commons-api/src/main/java/org/reactivecommons/async/api/handlers/registered/RegisteredDomainHandlers.java @@ -5,7 +5,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class RegisteredDomainHandlers extends ConcurrentHashMap> { - private static final String DEFAULT_DOMAIN = "app"; + private static final String DEFAULT_DOMAIN = "__default__"; public RegisteredDomainHandlers() { super(); diff --git a/async/async-commons-api/src/test/java/org/reactivecommons/async/api/HandlerRegistryTest.java b/async/async-commons-api/src/test/java/org/reactivecommons/async/api/HandlerRegistryTest.java index 9bacee8a..8413a3cd 100644 --- a/async/async-commons-api/src/test/java/org/reactivecommons/async/api/HandlerRegistryTest.java +++ b/async/async-commons-api/src/test/java/org/reactivecommons/async/api/HandlerRegistryTest.java @@ -21,9 +21,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; class HandlerRegistryTest { + private static final String UNRESOLVED_DOMAIN = HandlerRegistry.getUnresolvedDomain(); private final HandlerRegistry registry = HandlerRegistry.register(); private final String name = "some.event"; private final String nameRawNotification = "some.raw.notification.event"; @@ -64,7 +64,7 @@ void shouldListenDomainRawEvent() { registry.listenRawEvent(name, eventHandler); - assertThat(registry.getDomainEventListeners().get(DEFAULT_DOMAIN)) + assertThat(registry.getDomainEventListeners().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -78,7 +78,7 @@ void shouldListenEvent() { registry.listenEvent(name, eventHandler, SomeDataClass.class); - assertThat(registry.getDomainEventListeners().get(DEFAULT_DOMAIN)) + assertThat(registry.getDomainEventListeners().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -92,7 +92,7 @@ void shouldListenCloudEvent() { registry.listenCloudEvent(name, eventHandler); - assertThat(registry.getDomainEventListeners().get(DEFAULT_DOMAIN)) + assertThat(registry.getDomainEventListeners().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -110,7 +110,7 @@ void shouldRegisterPatternEventHandler() { RegisteredEventListener> expectedRegisteredEventListener = new RegisteredEventListener<>(eventNamePattern, eventHandler, SomeDataClass.class); - assertThat(registry.getDomainEventListeners().get(DEFAULT_DOMAIN)) + assertThat(registry.getDomainEventListeners().get(UNRESOLVED_DOMAIN)) .anySatisfy(registeredEventListener -> assertThat(registeredEventListener) .usingRecursiveComparison() .isEqualTo(expectedRegisteredEventListener)); @@ -122,14 +122,14 @@ void shouldRegisterPatternEventHandler() { @Test void shouldRegisterNotificationEventListener() { registry.listenNotificationEvent(name, message -> Mono.empty(), SomeDataClass.class); - assertThat(registry.getEventNotificationListener().get(DEFAULT_DOMAIN)) + assertThat(registry.getEventNotificationListener().get(UNRESOLVED_DOMAIN)) .anySatisfy(listener -> assertThat(listener.path()).isEqualTo(name)); } @Test void shouldRegisterNotificationCloudEventListener() { registry.listenNotificationCloudEvent(name, message -> Mono.empty()); - assertThat(registry.getEventNotificationListener().get(DEFAULT_DOMAIN)) + assertThat(registry.getEventNotificationListener().get(UNRESOLVED_DOMAIN)) .anySatisfy(listener -> assertThat(listener.path()).isEqualTo(name)); } @@ -139,7 +139,7 @@ void shouldRegisterNotificationRawEventListener() { registry.listenNotificationRawEvent(nameRawNotification, eventHandler); - assertThat(registry.getEventNotificationListener().get(DEFAULT_DOMAIN)) + assertThat(registry.getEventNotificationListener().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -153,7 +153,7 @@ void listenEvent() { SomeDomainEventHandler handler = mock(SomeDomainEventHandler.class); registry.listenEvent(name, handler, SomeDataClass.class); - assertThat(registry.getDomainEventListeners().get(DEFAULT_DOMAIN)) + assertThat(registry.getDomainEventListeners().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -167,7 +167,7 @@ void shouldListenDynamicEvent() { registry.handleDynamicEvents(name, eventHandler, SomeDataClass.class); - assertThat(registry.getDynamicEventHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getDynamicEventHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -181,7 +181,7 @@ void shouldListenDynamicCloudEvent() { registry.handleDynamicCloudEvents(name, eventHandler); - assertThat(registry.getDynamicEventHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getDynamicEventHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredEventListener::path, RegisteredEventListener::inputClass, RegisteredEventListener::handler @@ -195,7 +195,7 @@ void handleDomainCommand() { registry.handleCommand(name, handler, SomeDataClass.class); - assertThat(registry.getCommandHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getCommandHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredCommandHandler::path, RegisteredCommandHandler::inputClass, RegisteredCommandHandler::handler @@ -209,7 +209,7 @@ void handleCloudEventCommand() { registry.handleCloudEventCommand(name, cloudCommandHandler); - assertThat(registry.getCommandHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getCommandHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredCommandHandler::path, RegisteredCommandHandler::inputClass, RegisteredCommandHandler::handler @@ -223,7 +223,7 @@ void handleRawCommand() { registry.handleRawCommand(eventHandler); - assertThat(registry.getCommandHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getCommandHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredCommandHandler::path, RegisteredCommandHandler::inputClass, RegisteredCommandHandler::handler @@ -237,7 +237,7 @@ void shouldServerCloudEventQuery() { registry.serveCloudEventQuery(name, queryHandler); - assertThat(registry.getHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredQueryHandler::path, RegisteredQueryHandler::queryClass) .containsExactly(name, CloudEvent.class)).hasSize(1); @@ -247,7 +247,7 @@ void shouldServerCloudEventQuery() { void handleCommandWithLambda() { registry.handleCommand(name, (Command message) -> Mono.empty(), SomeDataClass.class); - assertThat(registry.getCommandHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getCommandHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredCommandHandler::path, RegisteredCommandHandler::inputClass) .containsExactly(name, SomeDataClass.class)).hasSize(1); @@ -257,7 +257,7 @@ void handleCommandWithLambda() { @Test void serveQueryWithLambda() { registry.serveQuery(name, message -> Mono.empty(), SomeDataClass.class); - assertThat(registry.getHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredQueryHandler::path, RegisteredQueryHandler::queryClass) .containsExactly(name, SomeDataClass.class)).hasSize(1); @@ -267,7 +267,7 @@ void serveQueryWithLambda() { void serveQueryWithTypeInference() { QueryHandler handler = new SomeQueryHandler(); registry.serveQuery(name, handler, SomeDataClass.class); - assertThat(registry.getHandlers().get(DEFAULT_DOMAIN)).anySatisfy(registered -> { + assertThat(registry.getHandlers().get(UNRESOLVED_DOMAIN)).anySatisfy(registered -> { assertThat(registered).extracting(RegisteredQueryHandler::path, RegisteredQueryHandler::queryClass) .containsExactly(name, SomeDataClass.class); assertThat(registered).extracting(RegisteredQueryHandler::handler) @@ -279,7 +279,7 @@ void serveQueryWithTypeInference() { void serveQueryDelegate() { QueryHandlerDelegate handler = new SomeQueryHandlerDelegate(); registry.serveQuery(name, handler, SomeDataClass.class); - assertThat(registry.getHandlers().get(DEFAULT_DOMAIN)).anySatisfy(registered -> + assertThat(registry.getHandlers().get(UNRESOLVED_DOMAIN)).anySatisfy(registered -> assertThat(registered) .extracting(RegisteredQueryHandler::path, RegisteredQueryHandler::queryClass) .containsExactly(name, SomeDataClass.class)) @@ -289,7 +289,7 @@ void serveQueryDelegate() { @Test void serveQueryDelegateWithLambda() { registry.serveQuery(name, (from, message) -> Mono.empty(), SomeDataClass.class); - assertThat(registry.getHandlers().get(DEFAULT_DOMAIN)).anySatisfy(registered -> + assertThat(registry.getHandlers().get(UNRESOLVED_DOMAIN)).anySatisfy(registered -> assertThat(registered) .extracting(RegisteredQueryHandler::path, RegisteredQueryHandler::queryClass) .containsExactly(name, SomeDataClass.class)) @@ -366,7 +366,7 @@ void listenNotificationRawEventWithDomain() { void serveCloudEventQueryDelegate() { QueryHandlerDelegate delegate = (from, ce) -> Mono.empty(); registry.serveCloudEventQuery(name, delegate); - assertThat(registry.getHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(registered -> assertThat(registered) .extracting(RegisteredQueryHandler::path, RegisteredQueryHandler::queryClass) .containsExactly(name, CloudEvent.class)).hasSize(1); @@ -375,7 +375,7 @@ void serveCloudEventQueryDelegate() { @Test void listenQueueSimple() { registry.listenQueue("myQueue", msg -> Mono.empty()); - assertThat(registry.getQueueHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getQueueHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(q -> assertThat(q.queueName()).isEqualTo("myQueue")).hasSize(1); } @@ -389,7 +389,7 @@ void listenQueueWithDomain() { @Test void listenQueueWithTopology() { registry.listenQueue("myQueue", msg -> Mono.empty(), creator -> Mono.empty()); - assertThat(registry.getQueueHandlers().get(DEFAULT_DOMAIN)) + assertThat(registry.getQueueHandlers().get(UNRESOLVED_DOMAIN)) .anySatisfy(q -> assertThat(q.queueName()).isEqualTo("myQueue")).hasSize(1); } diff --git a/async/async-commons/async-commons.gradle b/async/async-commons/async-commons.gradle index 381b446b..62e9c5e7 100644 --- a/async/async-commons/async-commons.gradle +++ b/async/async-commons/async-commons.gradle @@ -10,8 +10,8 @@ dependencies { compileOnly 'io.projectreactor:reactor-core' api 'tools.jackson.core:jackson-databind' - implementation 'commons-io:commons-io:2.21.0' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'commons-io:commons-io:2.22.0' + implementation 'io.cloudevents:cloudevents-core:4.0.2' testImplementation 'io.projectreactor:reactor-test' } \ No newline at end of file diff --git a/async/async-commons/src/main/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilder.java b/async/async-commons/src/main/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilder.java index 12087157..8f29f5bb 100644 --- a/async/async-commons/src/main/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilder.java +++ b/async/async-commons/src/main/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilder.java @@ -11,68 +11,59 @@ import org.reactivecommons.async.api.handlers.registered.RegisteredQueueListener; import org.reactivecommons.async.commons.HandlerResolver; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; import java.util.stream.Stream; @Log @NoArgsConstructor(access = AccessLevel.PRIVATE) +@SuppressWarnings({"unchecked", "rawtypes"}) public final class HandlerResolverBuilder { public static HandlerResolver buildResolver(String domain, Map registries, final DefaultCommandHandler defaultCommandHandler) { - final ConcurrentMap> queryHandlers = registries - .values() - .stream() - .flatMap(r -> r.getHandlers() - .getOrDefault(domain, List.of()) - .stream()) - .collect(ConcurrentHashMap::new, (map, handler) - -> map.put(handler.path(), handler), ConcurrentHashMap::putAll - ); + return buildResolver(domain, null, registries, defaultCommandHandler); + } - final ConcurrentMap> commandHandlers = registries - .values() - .stream() - .flatMap(r -> r.getCommandHandlers() - .getOrDefault(domain, List.of()) - .stream()) - .collect(ConcurrentHashMap::new, (map, handler) - -> map.put(handler.path(), handler), ConcurrentHashMap::putAll - ); + public static HandlerResolver buildResolver(String domain, String aliasDomain, + Map registries, + final DefaultCommandHandler defaultCommandHandler) { + Collection allRegistries = registries.values(); - final ConcurrentMap queueListeners = registries - .values() - .stream() - .flatMap(r -> r.getQueueHandlers() - .getOrDefault(domain, List.of()) - .stream()) - .collect(ConcurrentHashMap::new, (map, handler) - -> map.put(handler.queueName(), handler), ConcurrentHashMap::putAll - ); + final ConcurrentMap> queryHandlers = collectHandlers( + allRegistries, r -> mergeHandlers(r.getHandlers(), domain, aliasDomain), + RegisteredQueryHandler::path); - final ConcurrentMap> eventNotificationListeners = registries - .values() - .stream() - .flatMap(r -> r.getEventNotificationListener() - .getOrDefault(domain, List.of()) - .stream()) - .collect(ConcurrentHashMap::new, (map, handler) - -> map.put(handler.path(), handler), ConcurrentHashMap::putAll - ); + final ConcurrentMap> commandHandlers = collectHandlers( + allRegistries, r -> mergeHandlers(r.getCommandHandlers(), domain, aliasDomain), + RegisteredCommandHandler::path); - final ConcurrentMap> eventsToBind = getEventsToBind(domain, - registries); + final ConcurrentMap queueListeners = collectHandlers( + allRegistries, r -> mergeHandlers(r.getQueueHandlers(), domain, aliasDomain), + RegisteredQueueListener::queueName); - final ConcurrentMap> eventListeners = - getEventHandlersWithDynamics(domain, registries); + final ConcurrentMap> eventNotificationListeners = collectHandlers( + allRegistries, r -> mergeHandlers(r.getEventNotificationListener(), domain, aliasDomain), + RegisteredEventListener::path); + + final ConcurrentMap> eventsToBind = collectHandlers( + allRegistries, r -> mergeHandlers(r.getDomainEventListeners(), domain, aliasDomain), + RegisteredEventListener::path); + + final ConcurrentMap> eventListeners = collectHandlers( + allRegistries, + r -> Stream.concat( + mergeHandlers(r.getDomainEventListeners(), domain, aliasDomain), + mergeHandlers(r.getDynamicEventHandlers(), domain, aliasDomain)), + RegisteredEventListener::path); return new HandlerResolver(queryHandlers, eventListeners, eventsToBind, eventNotificationListeners, commandHandlers, queueListeners) { @Override - @SuppressWarnings("unchecked") public RegisteredCommandHandler getCommandHandler(String path) { final RegisteredCommandHandler handler = super.getCommandHandler(path); return handler != null ? @@ -81,37 +72,22 @@ public RegisteredCommandHandler getCommandHandler(String path) { }; } - private static ConcurrentMap> getEventHandlersWithDynamics( - String domain, Map registries) { - // event handlers and dynamic handlers - return registries - .values() - .stream() - .flatMap(r -> Stream.concat(r.getDomainEventListeners() - .getOrDefault(domain, List.of()) - .stream(), - getDynamics(domain, r))) + private static ConcurrentMap collectHandlers(Collection registries, + Function> extractor, + Function keyMapper) { + return registries.stream() + .flatMap(extractor) .collect(ConcurrentHashMap::new, (map, handler) - -> map.put(handler.path(), handler), ConcurrentHashMap::putAll - ); + -> map.put(keyMapper.apply(handler), handler), ConcurrentHashMap::putAll); } - private static Stream> getDynamics(String domain, HandlerRegistry r) { - return r.getDynamicEventHandlers().getOrDefault(domain, List.of()).stream(); - } - - private static ConcurrentMap> getEventsToBind( - String domain, Map registries) { - return registries - .values().stream() - .flatMap(r -> { - if (r.getDomainEventListeners().containsKey(domain)) { - return r.getDomainEventListeners().get(domain).stream(); - } - return Stream.empty(); - }) - .collect(ConcurrentHashMap::new, (map, handler) - -> map.put(handler.path(), handler), ConcurrentHashMap::putAll - ); + private static Stream mergeHandlers(Map> handlersMap, + String domain, String aliasDomain) { + Stream primary = Stream.ofNullable(handlersMap.get(domain)).flatMap(List::stream); + if (aliasDomain != null && !aliasDomain.equals(domain)) { + Stream alias = Stream.ofNullable(handlersMap.get(aliasDomain)).flatMap(List::stream); + return Stream.concat(primary, alias); + } + return primary; } } diff --git a/async/async-commons/src/test/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilderTest.java b/async/async-commons/src/test/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilderTest.java index e9062ba6..291356f4 100644 --- a/async/async-commons/src/test/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilderTest.java +++ b/async/async-commons/src/test/java/org/reactivecommons/async/commons/utils/resolver/HandlerResolverBuilderTest.java @@ -16,7 +16,8 @@ class HandlerResolverBuilderTest { @Test void buildResolverWithEmptyRegistries() { var registry = HandlerRegistry.register(); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.hasQueryHandlers()).isFalse(); assertThat(resolver.hasCommandHandlers()).isFalse(); @@ -28,7 +29,8 @@ void buildResolverWithQueryHandlers() { var registry = HandlerRegistry.register() .serveQuery("my.query", msg -> Mono.just("result"), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.hasQueryHandlers()).isTrue(); assertThat(resolver.getQueryHandler("my.query")).isNotNull(); @@ -40,7 +42,8 @@ void buildResolverWithCommandHandlers() { var registry = HandlerRegistry.register() .handleCommand("my.cmd", cmd -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.hasCommandHandlers()).isTrue(); assertThat(resolver.getCommandHandler("my.cmd")).isNotNull(); @@ -52,7 +55,8 @@ void buildResolverWithEventListeners() { var registry = HandlerRegistry.register() .listenEvent("my.event", evt -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.getEventListener("my.event")).isNotNull(); } @@ -62,7 +66,8 @@ void buildResolverWithNotificationListeners() { var registry = HandlerRegistry.register() .listenNotificationEvent("notif.event", evt -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.hasNotificationListeners()).isTrue(); assertThat(resolver.getNotificationListener("notif.event")).isNotNull(); @@ -73,7 +78,8 @@ void buildResolverWithQueueListeners() { var registry = HandlerRegistry.register() .listenQueue("myQueue", msg -> Mono.empty()); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.getQueueListeners()).containsKey("myQueue"); } @@ -83,7 +89,8 @@ void buildResolverWithDynamicEventHandlers() { var registry = HandlerRegistry.register() .handleDynamicEvents("event.*", evt -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.getEventListener("event.foo")).isNotNull(); } @@ -91,7 +98,8 @@ void buildResolverWithDynamicEventHandlers() { @Test void defaultCommandHandlerReturnedForUnknownPath() { var registry = HandlerRegistry.register(); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); var handler = resolver.getCommandHandler("unknown.command"); assertThat(handler).isNotNull(); @@ -105,7 +113,7 @@ void buildResolverWithMultipleRegistries() { var registry2 = HandlerRegistry.register() .handleCommand("c1", cmd -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), Map.of("r1", registry1, "r2", registry2), defaultHandler); assertThat(resolver.hasQueryHandlers()).isTrue(); @@ -128,7 +136,8 @@ void buildResolverForDomainIgnoresOtherDomainEntries() { var registry = HandlerRegistry.register() .handleCommand("other", "other.cmd", cmd -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.hasCommandHandlers()).isFalse(); } @@ -139,7 +148,8 @@ void buildResolverEventListenersIncludesDynamics() { .listenEvent("static.event", evt -> Mono.empty(), String.class) .handleDynamicEvents("dynamic.*", evt -> Mono.empty(), String.class); - var resolver = HandlerResolverBuilder.buildResolver("app", Map.of("r1", registry), defaultHandler); + var resolver = HandlerResolverBuilder.buildResolver("app", HandlerRegistry.getUnresolvedDomain(), + Map.of("r1", registry), defaultHandler); assertThat(resolver.getEventListener("static.event")).isNotNull(); assertThat(resolver.getEventListener("dynamic.foo")).isNotNull(); diff --git a/async/async-kafka/async-kafka.gradle b/async/async-kafka/async-kafka.gradle index 3f7af8b6..056191a8 100644 --- a/async/async-kafka/async-kafka.gradle +++ b/async/async-kafka/async-kafka.gradle @@ -9,5 +9,5 @@ dependencies { api project(':async-commons') api project(':cloudevents-json-jackson') api 'io.projectreactor.kafka:reactor-kafka:1.3.25' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' } \ No newline at end of file diff --git a/async/async-rabbit/async-rabbit.gradle b/async/async-rabbit/async-rabbit.gradle index dde69636..f9f000c8 100644 --- a/async/async-rabbit/async-rabbit.gradle +++ b/async/async-rabbit/async-rabbit.gradle @@ -15,6 +15,6 @@ dependencies { api 'com.rabbitmq:amqp-client' api 'tools.jackson.core:jackson-databind' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' testImplementation 'io.projectreactor:reactor-test' } \ No newline at end of file diff --git a/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationCommandListenerPerfTest.java b/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationCommandListenerPerfTest.java index e78cbbac..f2b39629 100644 --- a/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationCommandListenerPerfTest.java +++ b/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationCommandListenerPerfTest.java @@ -42,7 +42,6 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; import static reactor.core.publisher.Flux.range; @ExtendWith(MockitoExtension.class) @@ -276,7 +275,7 @@ private HandlerResolver createHandlerResolver(final HandlerRegistry initialRegis ) .block(); final ConcurrentMap> commandHandlers = registry.getCommandHandlers() - .get(DEFAULT_DOMAIN) + .get(HandlerRegistry.getUnresolvedDomain()) .stream() .collect(ConcurrentHashMap::new, (map, handler) -> map.put(handler.path(), handler), ConcurrentHashMap::putAll diff --git a/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationQueueListenerTest.java b/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationQueueListenerTest.java index 1e8cdd17..57747e4f 100644 --- a/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationQueueListenerTest.java +++ b/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ApplicationQueueListenerTest.java @@ -100,7 +100,7 @@ void shouldRegisterMultipleQueuesInDifferentDomains() { assertThat(registry.getQueueHandlers().get("domain1")).hasSize(1); assertThat(registry.getQueueHandlers().get("domain2")).hasSize(1); - assertThat(registry.getQueueHandlers().get(HandlerRegistry.DEFAULT_DOMAIN)).hasSize(1); + assertThat(registry.getQueueHandlers().get(HandlerRegistry.getUnresolvedDomain())).hasSize(1); } @Test diff --git a/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ListenerReporterTestSuperClass.java b/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ListenerReporterTestSuperClass.java index 8286a20a..25cb6dc1 100644 --- a/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ListenerReporterTestSuperClass.java +++ b/async/async-rabbit/src/test/java/org/reactivecommons/async/rabbit/listeners/ListenerReporterTestSuperClass.java @@ -50,7 +50,6 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; import static reactor.core.publisher.Mono.empty; import static reactor.core.publisher.Mono.just; @@ -146,9 +145,10 @@ protected Flux createSource(Function rout protected abstract GenericMessageListener createMessageListener(final HandlerResolver handlerResolver); private HandlerResolver createHandlerResolver(final HandlerRegistry registry) { + String unresolvedDomain = HandlerRegistry.getUnresolvedDomain(); Stream> listenerStream = Stream.concat( - registry.getDynamicEventHandlers().get(DEFAULT_DOMAIN).stream(), - registry.getDomainEventListeners().get(DEFAULT_DOMAIN).stream()); + registry.getDynamicEventHandlers().get(unresolvedDomain).stream(), + registry.getDomainEventListeners().get(unresolvedDomain).stream()); if (registry.getDomainEventListeners().containsKey("domain")) { listenerStream = Stream.concat( listenerStream, @@ -157,18 +157,18 @@ private HandlerResolver createHandlerResolver(final HandlerRegistry registry) { final Map> eventHandlers = listenerStream .collect(toMap(RegisteredEventListener::path, identity())); final Map> eventsToBind = registry.getDomainEventListeners() - .get(DEFAULT_DOMAIN).stream().collect(toMap(RegisteredEventListener::path, identity())); + .get(unresolvedDomain).stream().collect(toMap(RegisteredEventListener::path, identity())); final Map> notificationHandlers = registry.getEventNotificationListener() - .get(DEFAULT_DOMAIN) + .get(unresolvedDomain) .stream().collect(toMap(RegisteredEventListener::path, identity())); - final Map> queryHandlers = registry.getHandlers().get(DEFAULT_DOMAIN) + final Map> queryHandlers = registry.getHandlers().get(unresolvedDomain) .stream() .collect(toMap(RegisteredQueryHandler::path, identity())); final Map> commandHandlers = registry.getCommandHandlers() - .get(DEFAULT_DOMAIN) + .get(unresolvedDomain) .stream().collect(toMap(RegisteredCommandHandler::path, identity())); final Map queueHandlers = registry.getQueueHandlers() - .get(DEFAULT_DOMAIN) + .get(unresolvedDomain) .stream().collect(toMap(RegisteredQueueListener::queueName, identity())); return new HandlerResolver( new ConcurrentHashMap<>(queryHandlers), diff --git a/async/cloudevents-json-jackson/cloudevents-json-jackson.gradle b/async/cloudevents-json-jackson/cloudevents-json-jackson.gradle index 161f122a..35378387 100644 --- a/async/cloudevents-json-jackson/cloudevents-json-jackson.gradle +++ b/async/cloudevents-json-jackson/cloudevents-json-jackson.gradle @@ -5,6 +5,6 @@ ext { dependencies { api 'tools.jackson.core:jackson-databind' - implementation 'io.cloudevents:cloudevents-api:4.0.1' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-api:4.0.2' + implementation 'io.cloudevents:cloudevents-core:4.0.2' } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 0e1a8333..fa6c2298 100644 --- a/build.gradle +++ b/build.gradle @@ -12,10 +12,10 @@ buildscript { plugins { id 'jacoco' - id 'org.sonarqube' version '7.2.2.6593' - id 'org.springframework.boot' version '4.0.4' apply false + id 'org.sonarqube' version '7.3.0.8198' + id 'org.springframework.boot' version '4.0.6' apply false id 'io.github.gradle-nexus.publish-plugin' version '2.0.0' - id 'co.com.bancolombia.cleanArchitecture' version '4.3.0' + id 'co.com.bancolombia.cleanArchitecture' version '4.4.1' } repositories { diff --git a/docs/docs/reactive-commons/1-getting-started.md b/docs/docs/reactive-commons/1-getting-started.md index bd6baff5..a446ae46 100644 --- a/docs/docs/reactive-commons/1-getting-started.md +++ b/docs/docs/reactive-commons/1-getting-started.md @@ -54,7 +54,7 @@ dependencies { If you will use Cloud Events, you should include the Cloud Events dependency: ```groovy dependencies { - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' } ``` ::: @@ -228,7 +228,7 @@ dependencies { If you will use Cloud Events, you should include the Cloud Events dependency: ```groovy dependencies { - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' ``` ::: diff --git a/docs/docs/reactive-commons/configuration_properties/1-rabbitmq.md b/docs/docs/reactive-commons/configuration_properties/1-rabbitmq.md index 665f8069..1bae7913 100644 --- a/docs/docs/reactive-commons/configuration_properties/1-rabbitmq.md +++ b/docs/docs/reactive-commons/configuration_properties/1-rabbitmq.md @@ -4,13 +4,18 @@ sidebar_position: 1 # RabbitMQ Configuration -You can customize some predefined variables of Reactive Commons. - -This can be done by Spring Boot `application.yaml` or by overriding -the [AsyncProps](https://github.com/reactive-commons/reactive-commons-java/blob/master/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncProps.java) -bean. - -```yaml +This page describes how to configure RabbitMQ connection and messaging properties for each **domain** in +Reactive Commons. A domain represents an independent connection to a RabbitMQ broker. Your application can work +with a single domain (one broker) or multiple domains (several independent brokers), each with its own properties. +See [Communication Scenarios](/reactive-commons-java/docs/category/communication-scenarios) for guidance on when +to use multiple domains. + +All available properties are defined in the +[AsyncProps](https://github.com/reactive-commons/reactive-commons-java/blob/master/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncProps.java) +class. There are three ways to provide these values — via `application.yaml`, programmatically, or a combination of +both — as described in the [Configuration approaches](#configuration-approaches) section below. + +```yaml title="application.yaml" app: async: app: # this is the name of the default domain @@ -58,13 +63,30 @@ app: virtual-host: /accounts ``` -You can override this settings programmatically through an `AsyncRabbitPropsDomainProperties` bean: - :::caution[Mandatory `app` Domain Configuration] To ensure a correct configuration, you should always override the properties of the `app` domain. If it is not configured, an exception will be thrown. You can also add properties for additional custom domain if needed. ::: +## Configuration approaches + +There are three ways to supply domain properties. Choose the one that best fits your use case. + +### Approach 1 — YAML only + +Define all domains directly in `application.yaml` as shown above. No additional Java configuration is needed. +This is the simplest approach and works well when properties do not depend on runtime values such as secrets. + +### Approach 2 — Fully programmatic (no YAML domains) + +:::danger[Deprecated] +This approach is **deprecated** and will be removed in a future version. Use **Approach 3** instead, which provides +better separation of concerns and runtime flexibility. +::: + +Override the `AsyncRabbitPropsDomainProperties` bean to define all domains in code. +**Do not declare any domain under `app.async` in your YAML when using this approach**, as both sources would conflict. + ```java package sample; @@ -72,6 +94,7 @@ import org.reactivecommons.async.rabbit.config.RabbitProperties; import org.reactivecommons.async.rabbit.config.props.AsyncProps; import org.reactivecommons.async.rabbit.config.props.AsyncRabbitPropsDomainProperties; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @Configuration @@ -106,6 +129,128 @@ public class MyDomainConfig { } ``` +### Approach 3 — Hybrid: YAML + `RabbitPropsCustomizer` + +Use this approach when you want to define the domain structure in YAML (topology, retry settings, etc.) but need to +set some properties at runtime — for example, loading connection credentials from a secrets manager. + +Declare your domains in `application.yaml` as usual, then define a `RabbitPropsCustomizer` bean to override specific +properties after the YAML is loaded. The customizer receives the full map of configured domains and can modify +any property on any domain. + +:::caution[YAML domains are optional] +The `RabbitPropsCustomizer` can work with or without pre-existing YAML domains. If no domains are defined in your +`application.yaml` under `app.async`, you can define all domains directly inside the customizer using +`domainProperties.put("", AsyncProps.builder()...build())`. At least one domain must exist after the customizer +executes, otherwise an `InvalidConfigurationException` is thrown. +::: + +You have two options: + +**Option A: Define domains in YAML, then override with customizer** + +Declare your domains in `application.yaml` as usual, then use the customizer to override or extend them. + +```yaml title="application.yaml" +app: + async: + push: # first domain (will be treated as the default) + withDLQRetry: true + maxRetries: 3 + listenReplies: true + accounts: # second domain with independent broker + listenReplies: false +``` + +```java +package sample; + +import org.reactivecommons.async.rabbit.config.RabbitProperties; +import org.reactivecommons.async.rabbit.config.props.AsyncProps; +import org.reactivecommons.async.rabbit.config.props.AsyncPropsDomain; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitMQConfig { + + // Loads RabbitMQ connection properties from a secrets manager at runtime. + // See the "Loading properties from a secret" section below for a complete implementation example. + private RabbitProperties loadFromSecret(String secretName) { + // ... + return new RabbitProperties(); + } + + @Bean + public AsyncPropsDomain.RabbitPropsCustomizer rabbitPropsCustomizer() { + return domainProperties -> { + // Customize the "push" domain — overrides take precedence over YAML values + AsyncProps push = domainProperties.get("push"); + if (push != null) { + push.setConnectionProperties(loadFromSecret("secret-push-rabbit")); + } + + // Customize the "accounts" domain independently + AsyncProps accounts = domainProperties.get("accounts"); + if (accounts != null) { + accounts.setConnectionProperties(loadFromSecret("secret-accounts-rabbit")); + } + }; + } +} +``` + +**Option B: Define all domains in the customizer (no YAML domains)** + +If you prefer full programmatic control, **omit the `app.async` section entirely from your `application.yaml`** and +define all domains +inside the customizer: + +```java +package sample; + +import org.reactivecommons.async.rabbit.config.RabbitProperties; +import org.reactivecommons.async.rabbit.config.props.AsyncProps; +import org.reactivecommons.async.rabbit.config.props.AsyncPropsDomain; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitMQConfig { + + private RabbitProperties loadFromSecret(String secretName) { + // ... + return new RabbitProperties(); + } + + @Bean + public AsyncPropsDomain.RabbitPropsCustomizer rabbitPropsCustomizer() { + return domainProperties -> { + // Define all domains programmatically + domainProperties.put("push", AsyncProps.builder() + .withDLQRetry(true) + .maxRetries(3) + .listenReplies(true) + .connectionProperties(loadFromSecret("secret-push-rabbit")) + .build()); + + domainProperties.put("app", AsyncProps.builder() + .listenReplies(false) + .connectionProperties(loadFromSecret("secret-app-rabbit")) + .build()); + }; + } +} +``` + +**Key rules for the hybrid approach:** + +- Properties set in the customizer **take precedence** over YAML values. +- YAML values not touched by the customizer are **preserved**. +- The customizer can also **add new domains** by calling `domainProperties.put("newDomain", asyncProps)`. +- The first domain declared in YAML becomes the **default domain** and automatically resolves handlers registered + without an explicit domain (e.g., via `HandlerRegistry.register().listenEvent(...)`). + ## Loading properties from a secret Additionally, if you want to set only connection properties you can use the `AsyncPropsDomain.RabbitSecretFiller` class. diff --git a/docs/docs/reactive-commons/configuration_properties/2-kafka.md b/docs/docs/reactive-commons/configuration_properties/2-kafka.md index 81917b22..db46f1b4 100644 --- a/docs/docs/reactive-commons/configuration_properties/2-kafka.md +++ b/docs/docs/reactive-commons/configuration_properties/2-kafka.md @@ -4,13 +4,18 @@ sidebar_position: 2 # Kafka Configuration -You can customize some predefined variables of Reactive Commons. +This page describes how to configure Kafka connection and messaging properties for each **domain** in +Reactive Commons. A domain represents an independent connection to a Kafka cluster. Your application can work +with a single domain (one cluster) or multiple domains (several independent clusters), each with its own properties. +See [Communication Scenarios](/reactive-commons-java/docs/category/communication-scenarios) for guidance on when +to use multiple domains. -This can be done by Spring Boot `application.yaml` or by overriding -the [AsyncKafkaProps](https://github.com/reactive-commons/reactive-commons-java/blob/master/starters/async-kafka-starter/src/main/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaProps.java) -bean. +All available properties are defined in the +[AsyncKafkaProps](https://github.com/reactive-commons/reactive-commons-java/blob/master/starters/async-kafka-starter/src/main/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaProps.java) +class. There are three ways to provide these values — via `application.yaml`, programmatically, or a combination of +both — as described in the [Configuration approaches](#configuration-approaches) section below. -```yaml +```yaml title="application.yaml" reactive: commons: kafka: @@ -33,7 +38,25 @@ reactive: bootstrap-servers: localhost:9093 ``` -You can override this settings programmatically through a `AsyncKafkaPropsDomainProperties` bean: +## Configuration approaches + +There are three ways to supply domain properties. Choose the one that best fits your use case. + +### Approach 1 — YAML only + +Define all domains directly in `application.yaml` as shown above. No additional Java configuration is needed. +This is the simplest approach and works well when properties do not depend on runtime values such as secrets. + +### Approach 2 — Fully programmatic (no YAML domains) + +:::danger[Deprecated] +This approach is **deprecated** and will be removed in a future version. Use **Approach 3** instead, which provides +better separation of concerns and runtime flexibility. +::: + +Override the `AsyncKafkaPropsDomainProperties` bean to define all domains in code. +**Do not declare any domain under `reactive.commons.kafka` in your YAML when using this approach**, as both sources +would conflict. ```java package sample; @@ -68,6 +91,128 @@ public class MyDomainConfig { } ``` +### Approach 3 — Hybrid: YAML + `KafkaPropsCustomizer` + +Use this approach when you want to define the domain structure in YAML (topology, retry settings, etc.) but need to +set some properties at runtime — for example, loading bootstrap servers or credentials from a secrets manager. + +Declare your domains in `application.yaml` as usual, then define a `KafkaPropsCustomizer` bean to override specific +properties after the YAML is loaded. The customizer receives the full map of configured domains and can modify +any property on any domain. + +:::caution[YAML domains are optional] +The `KafkaPropsCustomizer` can work with or without pre-existing YAML domains. If no domains are defined in your +`application.yaml` under `reactive.commons.kafka`, you can define all domains directly inside the customizer using +`domainProperties.put("", AsyncKafkaProps.builder()...build())`. At least one domain must exist after the +customizer +executes, otherwise an `InvalidConfigurationException` is thrown. +::: + +You have two options: + +**Option A: Define domains in YAML, then override with customizer** + +Declare your domains in `application.yaml` as usual, then use the customizer to override or extend them. + +```yaml title="application.yaml" +reactive: + commons: + kafka: + app: # first domain (will be treated as the default) + retryDelay: 60000 + maxRetries: 3 + accounts: # second domain with independent cluster + retryDelay: 40000 +``` + +```java +package sample; + +import org.reactivecommons.async.kafka.config.KafkaProperties; +import org.reactivecommons.async.kafka.config.props.AsyncKafkaProps; +import org.reactivecommons.async.kafka.config.props.AsyncKafkaPropsDomain; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class KafkaConfig { + + // Loads Kafka connection properties from a secrets manager at runtime. + // See the "Loading properties from a secret" section below for a complete implementation example. + private KafkaProperties loadFromSecret(String secretName) { + // ... + return new KafkaProperties(); + } + + @Bean + public AsyncKafkaPropsDomain.KafkaPropsCustomizer kafkaPropsCustomizer() { + return domainProperties -> { + // Customize the "app" domain — overrides take precedence over YAML values + AsyncKafkaProps app = domainProperties.get("app"); + if (app != null) { + app.setConnectionProperties(loadFromSecret("secret-app-kafka")); + } + + // Customize the "accounts" domain independently + AsyncKafkaProps accounts = domainProperties.get("accounts"); + if (accounts != null) { + accounts.setConnectionProperties(loadFromSecret("secret-accounts-kafka")); + } + }; + } +} +``` + +**Option B: Define all domains in the customizer (no YAML domains)** + +If you prefer full programmatic control, **omit the `reactive.commons.kafka` section entirely from +your `application.yaml`** and define all domains +inside the customizer: + +```java +package sample; + +import org.reactivecommons.async.kafka.config.KafkaProperties; +import org.reactivecommons.async.kafka.config.props.AsyncKafkaProps; +import org.reactivecommons.async.kafka.config.props.AsyncKafkaPropsDomain; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class KafkaConfig { + + private KafkaProperties loadFromSecret(String secretName) { + // ... + return new KafkaProperties(); + } + + @Bean + public AsyncKafkaPropsDomain.KafkaPropsCustomizer kafkaPropsCustomizer() { + return domainProperties -> { + // Define all domains programmatically + domainProperties.put("app", AsyncKafkaProps.builder() + .retryDelay(60000) + .maxRetries(3) + .connectionProperties(loadFromSecret("secret-app-kafka")) + .build()); + + domainProperties.put("accounts", AsyncKafkaProps.builder() + .retryDelay(40000) + .connectionProperties(loadFromSecret("secret-accounts-kafka")) + .build()); + }; + } +} +``` + +**Key rules for the hybrid approach:** + +- Properties set in the customizer **take precedence** over YAML values. +- YAML values not touched by the customizer are **preserved**. +- The customizer can also **add new domains** by calling `domainProperties.put("newDomain", asyncKafkaProps)`. +- The first domain declared in YAML becomes the **default domain** and automatically resolves handlers registered + without an explicit domain (e.g., via `HandlerRegistry.register().listenEvent(...)`). + ## Loading properties from a secret Additionally, if you want to set only connection properties you can use the `AsyncKafkaPropsDomain.KafkaSecretFiller` diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 76ce0a31..b1602ba7 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -24,7 +24,12 @@ const config = { projectName: 'reactive-commons-java', // Usually your repo name. onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', + markdown: { + hooks: { + onBrokenMarkdownLinks: 'warn', + onBrokenMarkdownImages: 'throw', + }, + }, // Even if you don't use internationalization, you can use this field to set // useful metadata like html lang. For example, if your site is Chinese, you @@ -44,7 +49,7 @@ const config = { // Please change this to your repo. // Remove this to remove the "edit this page" links. editUrl: - 'https://github.com/reactive-commons/reactive-commons-java/tree/docs/docs', + 'https://github.com/reactive-commons/reactive-commons-java/tree/docs/docs', }, theme: { customCss: './src/css/custom.css', diff --git a/docs/package-lock.json b/docs/package-lock.json index b4cc6652..b976576b 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,64 +8,64 @@ "name": "docs", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^3.9.2", - "@docusaurus/preset-classic": "^3.9.2", - "@docusaurus/theme-common": "^3.9.2", + "@docusaurus/core": "^3.10.1", + "@docusaurus/preset-classic": "^3.10.1", + "@docusaurus/theme-common": "^3.10.1", "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", - "react": "^19.2.4", - "react-dom": "^19.2.4" + "react": "^19.2.6", + "react-dom": "^19.2.6" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.9.2", - "@docusaurus/types": "^3.9.2" + "@docusaurus/module-type-aliases": "^3.10.1", + "@docusaurus/types": "^3.10.1" }, "engines": { "node": ">=18.0" } }, "node_modules/@algolia/abtesting": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.15.1.tgz", - "integrity": "sha512-2yuIC48rUuHGhU1U5qJ9kJHaxYpJ0jpDHJVI5ekOxSMYXlH4+HP+pA31G820lsAznfmu2nzDV7n5RO44zIY1zw==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.18.1.tgz", + "integrity": "sha512-aehCadlWOGvrT91KUIZpC0MbB8KBW9yUuvTJFd2xesR7le/IsT4nJUnjCCZ4ZqZCeTcPHPV5mo//fZ5oxcSVYw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", - "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.8.tgz", + "integrity": "sha512-3YEorYg44niXcm7gkft3nXYItHd44e8tmh4D33CTszPgP0QWkaLEaFywiNyJBo7UL/mqObA/G9RYuU7R8tN1IA==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", - "@algolia/autocomplete-shared": "1.19.2" + "@algolia/autocomplete-plugin-algolia-insights": "1.19.8", + "@algolia/autocomplete-shared": "1.19.8" } }, "node_modules/@algolia/autocomplete-plugin-algolia-insights": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", - "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.8.tgz", + "integrity": "sha512-ZvJWO8ZZJDpc1LNM2TTBdmQsZBLMR4rU5iNR2OYvEeFBiaf/0ESnRSSLQbryarJY4SVxtoz6A2ZtDMNM+iQEAA==", "license": "MIT", "dependencies": { - "@algolia/autocomplete-shared": "1.19.2" + "@algolia/autocomplete-shared": "1.19.8" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", - "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", + "version": "1.19.8", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.8.tgz", + "integrity": "sha512-h5hf2t8ejF6vlOgvLaZzQbWs5SyH2z4PAWygNAvvD/2RI29hdQ54ldUGwqVuj9Srs+n8XUKTPUqb7fvhBhQrnQ==", "license": "MIT", "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -73,100 +73,99 @@ } }, "node_modules/@algolia/client-abtesting": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.49.1.tgz", - "integrity": "sha512-h6M7HzPin+45/l09q0r2dYmocSSt2MMGOOk5c4O5K/bBBlEwf1BKfN6z+iX4b8WXcQQhf7rgQwC52kBZJt/ZZw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.52.1.tgz", + "integrity": "sha512-HmXOGBOAOJPounpBzBpuY0zDYeiCpxgHnQmuA7JO6ScukcBdGp3/XM9zJk5pJx/xNGD68mbPGXWpDxGtl6BwDQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.49.1.tgz", - "integrity": "sha512-048T9/Z8OeLmTk8h76QUqaNFp7Rq2VgS2Zm6Y2tNMYGQ1uNuzePY/udB5l5krlXll7ZGflyCjFvRiOtlPZpE9g==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.52.1.tgz", + "integrity": "sha512-5oo4+I8iixie9vXhCyNFCzeIr8pqA3FQ//VsLHTDvZAV4ttYOPGvYHGQq5NSalrLx5Jc3dRro/5uDOlnUMcBJg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.49.1.tgz", - "integrity": "sha512-vp5/a9ikqvf3mn9QvHN8PRekn8hW34aV9eX+O0J5mKPZXeA6Pd5OQEh2ZWf7gJY6yyfTlLp5LMFzQUAU+Fpqpg==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.52.1.tgz", + "integrity": "sha512-qCDoZfx5MpX7XQzvQ3bC4tSEMkQWQMaF/ABtLuoze03Y/flR563CCSws02qIJ23oX7lxl92LsilZjINVyTdtLw==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.49.1.tgz", - "integrity": "sha512-B6N7PgkvYrul3bntTz/l6uXnhQ2bvP+M7NqTcayh681tSqPaA5cJCUBp/vrP7vpPRpej4Eeyx2qz5p0tE/2N2g==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.52.1.tgz", + "integrity": "sha512-hnGs0/lsFJ2PWDxNBz7pxreXo/Xz7gxYRcfePBUjsH26ad0kU/sgnVZd9LwWBpsQv65z2jlb5dkyaB9WE9M9FQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.49.1.tgz", - "integrity": "sha512-v+4DN+lkYfBd01Hbnb9ZrCHe7l+mvihyx218INRX/kaCXROIWUDIT1cs3urQxfE7kXBFnLsqYeOflQALv/gA5w==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.52.1.tgz", + "integrity": "sha512-2VxxNc/uBysyKvGeBdSM5n9eIDKH8kWD7wd9/yqbJAiVwU4Yv6tU1LSJusHKrXV/aCu1KW7t9Gug9QyeEmtn/Q==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.49.1.tgz", - "integrity": "sha512-Un11cab6ZCv0W+Jiak8UktGIqoa4+gSNgEZNfG8m8eTsXGqwIEr370H3Rqwj87zeNSlFpH2BslMXJ/cLNS1qtg==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.52.1.tgz", + "integrity": "sha512-O6mPtsw3xEfNOe6gWFpYLeAZAIljNa4Hgna3bq15PwyN7nbjTY0wXJFRbzs/0YVf75Br+SbOQUmjKxXYjDiSiQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.49.1.tgz", - "integrity": "sha512-Nt9hri7nbOo0RipAsGjIssHkpLMHHN/P7QqENywAq5TLsoYDzUyJGny8FEiD/9KJUxtGH8blGpMedilI6kK3rA==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.52.1.tgz", + "integrity": "sha512-gA8oJOV1LnQQkDf91iebNnFInHuW0gRPEgLSOQ7EfipCEjYTHm5swm1DlH9H5RaRw4RrHuzHBegnlzc0MAstcg==", "license": "MIT", - "peer": true, "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" @@ -179,81 +178,81 @@ "license": "MIT" }, "node_modules/@algolia/ingestion": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.49.1.tgz", - "integrity": "sha512-b5hUXwDqje0Y4CpU6VL481DXgPgxpTD5sYMnfQTHKgUispGnaCLCm2/T9WbJo1YNUbX3iHtYDArp804eD6CmRQ==", + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.52.1.tgz", + "integrity": "sha512-U9zZfc5xIu9wRxZkt+HceJUAD4VKHKbAyLSloJdEyMRmphXeibfrY9cxqIXBcmPeZzGhn3Imb35Dq8l19PkJhw==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { - "version": "1.49.1", - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.49.1.tgz", - "integrity": "sha512-bvrXwZ0WsL3rN6Q4m4QqxsXFCo6WAew7sAdrpMQMK4Efn4/W920r9ptOuckejOSSvyLr9pAWgC5rsHhR2FYuYw==", + "version": "1.52.1", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.52.1.tgz", + "integrity": "sha512-a3SGNceHmkQfq77iG8Ka+w1pvwfZa/0lzEIgse30fL0kD+yKnd/dg0dQvSfFPAEt2f21DMcGkDSSeJlO3KdQjQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.49.1.tgz", - "integrity": "sha512-h2yz3AGeGkQwNgbLmoe3bxYs8fac4An1CprKTypYyTU/k3Q+9FbIvJ8aS1DoBKaTjSRZVoyQS7SZQio6GaHbZw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.52.1.tgz", + "integrity": "sha512-z98QEguCFDpxb4S/PyrUK1igqF8tPsdbqOUUO6ON91vJ58w+Gwa6ncrI0oNXSFcrkxA5EqPKPQ2A1PBCn08TYQ==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "@algolia/client-common": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.49.1.tgz", - "integrity": "sha512-2UPyRuUR/qpqSqH8mxFV5uBZWEpxhGPHLlx9Xf6OVxr79XO2ctzZQAhsmTZ6X22x+N8MBWpB9UEky7YU2HGFgA==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.52.1.tgz", + "integrity": "sha512-CI7+/0I11QeZM59Uc8whd2or0kqzFVjpaPn9Qpwll/krHcBAxk24WkAQ6WX+IwDVMfpont4YGbKwAmCre3vE8Q==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1" + "@algolia/client-common": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.49.1.tgz", - "integrity": "sha512-N+xlE4lN+wpuT+4vhNEwPVlrfN+DWAZmSX9SYhbz986Oq8AMsqdntOqUyiOXVxYsQtfLwmiej24vbvJGYv1Qtw==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.52.1.tgz", + "integrity": "sha512-S6bDuw9byfOvm3T71cgdoZgrgnZq6hpdMLkx52Louh57nUAmvGQESz2aojOynQHjbTiV55smvAFbgn0qT4tJrg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1" + "@algolia/client-common": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.49.1.tgz", - "integrity": "sha512-zA5bkUOB5PPtTr182DJmajCiizHp0rCJQ0Chf96zNFvkdESKYlDeYA3tQ7r2oyHbu/8DiohAQ5PZ85edctzbXA==", + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.52.1.tgz", + "integrity": "sha512-tqZXM+54rWo4mk5jL5Z/flE11nPmNEdXwFBM5py9DkOmbjeCNemfVd45FyM97XdzfZ0dl9uOJC6PYn1FpkeyQg==", "license": "MIT", "dependencies": { - "@algolia/client-common": "5.49.1" + "@algolia/client-common": "5.52.1" }, "engines": { "node": ">= 14.0.0" @@ -274,9 +273,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -287,7 +286,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -376,9 +374,9 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz", + "integrity": "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", @@ -386,7 +384,7 @@ "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", + "@babel/traverse": "^7.29.0", "semver": "^6.3.1" }, "engines": { @@ -432,9 +430,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", - "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", @@ -609,22 +607,22 @@ } }, "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", "license": "MIT", "dependencies": { "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" + "@babel/types": "^7.29.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" @@ -682,6 +680,22 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz", + "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", @@ -1212,9 +1226,9 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.28.6", @@ -1749,18 +1763,19 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", - "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", + "version": "7.29.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.5.tgz", + "integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.29.0", + "@babel/compat-data": "^7.29.3", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", @@ -1792,7 +1807,7 @@ "@babel/plugin-transform-member-expression-literals": "^7.27.1", "@babel/plugin-transform-modules-amd": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.29.0", + "@babel/plugin-transform-modules-systemjs": "^7.29.4", "@babel/plugin-transform-modules-umd": "^7.27.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-new-target": "^7.27.1", @@ -1833,12 +1848,12 @@ } }, "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", - "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "core-js-compat": "^3.48.0" }, "peerDependencies": { @@ -1908,26 +1923,14 @@ } }, "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.0.tgz", - "integrity": "sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA==", - "license": "MIT", - "dependencies": { - "core-js-pure": "^3.48.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.28.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", @@ -2090,7 +2093,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" }, @@ -2113,7 +2115,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=18" } @@ -2223,7 +2224,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2645,7 +2645,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3313,9 +3312,9 @@ } }, "node_modules/@docsearch/core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.0.tgz", - "integrity": "sha512-IqG3oSd529jVRQ4dWZQKwZwQLVd//bWJTz2HiL0LkiHrI4U/vLrBasKB7lwQB/69nBAcCgs3TmudxTZSLH/ZQg==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.3.tgz", + "integrity": "sha512-rUOujwIpxJRgD7+kicVsI3D5sqBvdiRTquzWBpTEXZs8ZXfGbfzpus5HqumaNYTppN2HvH8E2yNuRwYdHJeOlA==", "license": "MIT", "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", @@ -3335,20 +3334,20 @@ } }, "node_modules/@docsearch/css": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.0.tgz", - "integrity": "sha512-YlcAimkXclvqta47g47efzCM5CFxDwv2ClkDfEs/fC/Ak0OxPH2b3czwa4o8O1TRBf+ujFF2RiUwszz2fPVNJQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.3.tgz", + "integrity": "sha512-nlOwcXcsNAptQl4vlL4MA78qNJKO0Qlds5GuBjCoePgkebTXLSf8Qt1oyZ3YBshYupKXG9VRGEsk1zr23d+bzQ==", "license": "MIT" }, "node_modules/@docsearch/react": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.0.tgz", - "integrity": "sha512-j8H5B4ArGxBPBWvw3X0J0Rm/Pjv2JDa2rV5OE0DLTp5oiBCptIJ/YlNOhZxuzbO2nwge+o3Z52nJRi3hryK9cA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.3.tgz", + "integrity": "sha512-Bg2wdDsoQVlNCcEKuEJAU04tvHCqgx8rIu+uIoM4pRtcx3TBKJuXutJik3LTA8LRc9YEyHkrYUrmcC0D7BYf+g==", "license": "MIT", "dependencies": { "@algolia/autocomplete-core": "1.19.2", - "@docsearch/core": "4.6.0", - "@docsearch/css": "4.6.0" + "@docsearch/core": "4.6.3", + "@docsearch/css": "4.6.3" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 20.0.0", @@ -3371,10 +3370,42 @@ } } }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-core": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", + "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", + "@algolia/autocomplete-shared": "1.19.2" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", + "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.19.2" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-shared": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", + "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, "node_modules/@docusaurus/babel": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", - "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.1.tgz", + "integrity": "sha512-DZzFO1K3v/GoEt1fx1DiYHF4en+PuhtQf1AkQJa5zu3CoeKSpr5cpQRUlz3jr0m44wyzmSXu9bVpfir+N4+8bg==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", @@ -3385,10 +3416,9 @@ "@babel/preset-react": "^7.25.9", "@babel/preset-typescript": "^7.25.9", "@babel/runtime": "^7.25.9", - "@babel/runtime-corejs3": "^7.25.9", "@babel/traverse": "^7.25.9", - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", "babel-plugin-dynamic-import-node": "^2.3.3", "fs-extra": "^11.1.1", "tslib": "^2.6.0" @@ -3398,17 +3428,17 @@ } }, "node_modules/@docusaurus/bundler": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", - "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.1.tgz", + "integrity": "sha512-HIqQPvbqnnQRe4NsBd1774KRarjXqS6wHsWELtyuSs1gCfvixJO2jUGH/OEBtr1Gvzpw+ze5CjGMvSJ8UE1KUw==", "license": "MIT", "dependencies": { "@babel/core": "^7.25.9", - "@docusaurus/babel": "3.9.2", - "@docusaurus/cssnano-preset": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", + "@docusaurus/babel": "3.10.1", + "@docusaurus/cssnano-preset": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", "babel-loader": "^9.2.1", "clean-css": "^5.3.3", "copy-webpack-plugin": "^11.0.0", @@ -3426,7 +3456,7 @@ "tslib": "^2.6.0", "url-loader": "^4.1.1", "webpack": "^5.95.0", - "webpackbar": "^6.0.1" + "webpackbar": "^7.0.0" }, "engines": { "node": ">=20.0" @@ -3441,18 +3471,18 @@ } }, "node_modules/@docusaurus/core": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", - "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", - "license": "MIT", - "dependencies": { - "@docusaurus/babel": "3.9.2", - "@docusaurus/bundler": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.1.tgz", + "integrity": "sha512-3pf2fXXw0eVk8WnC3T4LIigRDupcpvngpKo9Vy7mYyBhuddc0klDUuZAIfzMoK6z05pdlk6EFC/vBSX43+1O5w==", + "license": "MIT", + "dependencies": { + "@docusaurus/babel": "3.10.1", + "@docusaurus/bundler": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "boxen": "^6.2.1", "chalk": "^4.1.2", "chokidar": "^3.5.3", @@ -3464,7 +3494,7 @@ "escape-html": "^1.0.3", "eta": "^2.2.0", "eval": "^0.1.8", - "execa": "5.1.1", + "execa": "^5.1.1", "fs-extra": "^11.1.1", "html-tags": "^3.3.1", "html-webpack-plugin": "^5.6.0", @@ -3475,12 +3505,12 @@ "prompts": "^2.4.2", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", "react-router": "^5.3.4", "react-router-config": "^5.1.1", "react-router-dom": "^5.3.4", "semver": "^7.5.4", - "serve-handler": "^6.1.6", + "serve-handler": "^6.1.7", "tinypool": "^1.0.2", "tslib": "^2.6.0", "update-notifier": "^6.0.2", @@ -3496,15 +3526,21 @@ "node": ">=20.0" }, "peerDependencies": { + "@docusaurus/faster": "*", "@mdx-js/react": "^3.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@docusaurus/faster": { + "optional": true + } } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", - "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.1.tgz", + "integrity": "sha512-eNfHGcTKCSq6xmcavAkX3RRclHaE2xRCMParlDXLdXVP01/a2e/jKXMj/0ULnLFQSNwwuI62L0Ge8J+nZsR7UQ==", "license": "MIT", "dependencies": { "cssnano-preset-advanced": "^6.1.2", @@ -3517,9 +3553,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", - "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.1.tgz", + "integrity": "sha512-oPjNFnfJsRCkePVjkGrxWGq4MvJKRQT0r9jOP0eRBTZ7Wr9FAbzdP/Gjs0I2Ss6YRkPoEgygKG112OkE6skvJw==", "license": "MIT", "dependencies": { "chalk": "^4.1.2", @@ -3530,14 +3566,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", - "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.1.tgz", + "integrity": "sha512-GRmeb/wQ+iXRrFwcHBfgQhrJxGElgCsoTWZYDhccjsZVne1p8MK/EpQVIloXttz76TCe78kKD5AEG9n1xc1oxQ==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "@mdx-js/mdx": "^3.0.0", "@slorber/remark-comment": "^1.0.0", "escape-html": "^1.0.3", @@ -3569,12 +3605,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz", - "integrity": "sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.1.tgz", + "integrity": "sha512-YoOZKUdGlp8xSYhuAkGdSo5Ydkbq4V4eK3sD8v0a2hloxCWdQbNBhkc+Ko9QyjpESc0BYcIGM5iHVAy5hdFV6w==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.2", + "@docusaurus/types": "3.10.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3588,20 +3624,21 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz", - "integrity": "sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.1.tgz", + "integrity": "sha512-mmkgE6Q2+K74tnkou7tXlpDLvoCU/qkSa2GSQ3XUiHWvcebCoDQzS670RR3tO8PmaWlIyWWISYWzZLuMfxunRA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "cheerio": "1.0.0-rc.12", + "combine-promises": "^1.1.0", "feed": "^4.2.2", "fs-extra": "^11.1.1", "lodash": "^4.17.21", @@ -3622,21 +3659,20 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", - "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.1.tgz", + "integrity": "sha512-2jRVrtzjf8LClGTHQlwlwuD3wQXRx3WEoF7XUarJ8Ou+0onV+SLtejsyfY9JLpfUh9hPhXM4pbBGkyAY4Bi3HQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.1.1", @@ -3656,16 +3692,16 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz", - "integrity": "sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.1.tgz", + "integrity": "sha512-huJpaRPMl42nsFwuCXvV8bVDj2MazuwRJIUylI/RSlmZeJssVoZXeCjVf1y+1Drtpa9SKcdGn8yoJ76IRJijtw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "fs-extra": "^11.1.1", "tslib": "^2.6.0", "webpack": "^5.88.1" @@ -3679,15 +3715,15 @@ } }, "node_modules/@docusaurus/plugin-css-cascade-layers": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz", - "integrity": "sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.1.tgz", + "integrity": "sha512-r//fn+MNHkE1wCof8T29VAQezt1enGCpsFxoziBbvLgBM4JfXN2P3rxrBaavHmvLvm7lYkpJeitcDthwnmWCTw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { @@ -3695,14 +3731,14 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz", - "integrity": "sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.1.tgz", + "integrity": "sha512-9KqOpKNfAyqGZykRb9LhIT/vyRF6sm/ykhjj/39JvaJahDS+jZJE0Z1Wfz9q3DUNDTMNN0Q7u/kk4rKKU+IJuA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", "fs-extra": "^11.1.1", "react-json-view-lite": "^2.3.0", "tslib": "^2.6.0" @@ -3716,14 +3752,14 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz", - "integrity": "sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.1.tgz", + "integrity": "sha512-8o0P1KtmgdYQHH+oInitPpRWI0Of5XednAX4+DMhQNSmGSRNrsEEHg1ebv35m9AgRClfAytCJ5jA9KvcASTyuA==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { @@ -3735,15 +3771,15 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz", - "integrity": "sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.1.tgz", + "integrity": "sha512-pu3xIUo5o/zCMLfUY9BO5KOwSH0zIsAGyFRPvXHayFSA5XIhCU/SFuB0g0ZNjFn9niZLCaNvoeAuOGFJZq0fdw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", - "@types/gtag.js": "^0.0.12", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", + "@types/gtag.js": "^0.0.20", "tslib": "^2.6.0" }, "engines": { @@ -3755,14 +3791,14 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz", - "integrity": "sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.1.tgz", + "integrity": "sha512-f6fyGHiCm7kJHBtAisGQS5oNBnpnMTYQZxDXeVrnw/3zWU+LMA22pr6UHGYkBKDbN+qPC5QHG3NuOfzQLq3+Lw==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "tslib": "^2.6.0" }, "engines": { @@ -3774,17 +3810,17 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz", - "integrity": "sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.1.tgz", + "integrity": "sha512-C26MbmmqgdjkDq1htaZ3aD7LzEDKFWXfpyQpt0EOUThuq5nV77zDaedV20yHcVo9p+3ey9aZ4pbHA0D3QcZTzg==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "fs-extra": "^11.1.1", "sitemap": "^7.1.1", "tslib": "^2.6.0" @@ -3798,15 +3834,15 @@ } }, "node_modules/@docusaurus/plugin-svgr": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz", - "integrity": "sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.1.tgz", + "integrity": "sha512-6SFxsmjWFkVLDmBUvFK6i72QjUwqyQFe4Ovz+SUJophJjOyVG3ZZG5IQpBC/kX/Gfv1yWeU9nWauH6F6Q7QX/Q==", "license": "MIT", "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "@svgr/core": "8.1.0", "@svgr/webpack": "^8.1.0", "tslib": "^2.6.0", @@ -3821,26 +3857,26 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz", - "integrity": "sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/plugin-content-blog": "3.9.2", - "@docusaurus/plugin-content-docs": "3.9.2", - "@docusaurus/plugin-content-pages": "3.9.2", - "@docusaurus/plugin-css-cascade-layers": "3.9.2", - "@docusaurus/plugin-debug": "3.9.2", - "@docusaurus/plugin-google-analytics": "3.9.2", - "@docusaurus/plugin-google-gtag": "3.9.2", - "@docusaurus/plugin-google-tag-manager": "3.9.2", - "@docusaurus/plugin-sitemap": "3.9.2", - "@docusaurus/plugin-svgr": "3.9.2", - "@docusaurus/theme-classic": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/theme-search-algolia": "3.9.2", - "@docusaurus/types": "3.9.2" + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.10.1.tgz", + "integrity": "sha512-YO/FL8v1zmbxoTso6mjMz/RDjhaTJxb1UpFFTDdY5847LLDCeyYiYlrhyTbgN1RIN3xnkLKZ9Lj1x8hUzI4JOg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/plugin-css-cascade-layers": "3.10.1", + "@docusaurus/plugin-debug": "3.10.1", + "@docusaurus/plugin-google-analytics": "3.10.1", + "@docusaurus/plugin-google-gtag": "3.10.1", + "@docusaurus/plugin-google-tag-manager": "3.10.1", + "@docusaurus/plugin-sitemap": "3.10.1", + "@docusaurus/plugin-svgr": "3.10.1", + "@docusaurus/theme-classic": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-search-algolia": "3.10.1", + "@docusaurus/types": "3.10.1" }, "engines": { "node": ">=20.0" @@ -3851,26 +3887,27 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz", - "integrity": "sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA==", - "license": "MIT", - "dependencies": { - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/plugin-content-blog": "3.9.2", - "@docusaurus/plugin-content-docs": "3.9.2", - "@docusaurus/plugin-content-pages": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.1.tgz", + "integrity": "sha512-VU1RK0qb2pab0si4r7HFK37cYco8VzqLj3u1PspVipSr/z/GPVKHO4/HXbnePqHoWDk8urjyGSeatH0NIMBM1A==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/plugin-content-blog": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/plugin-content-pages": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "@mdx-js/react": "^3.0.0", "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", "infima": "0.2.0-alpha.45", "lodash": "^4.17.21", "nprogress": "^0.2.0", @@ -3891,15 +3928,15 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.2.tgz", - "integrity": "sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.1.tgz", + "integrity": "sha512-0YtmIeoNo1fIw65LO8+/1dPgmDV86UmhMkow37gzjytuiCSQm9xob6PJy0L4kuQEMTLfUOGvkXvZr7GPrHquMA==", "license": "MIT", "dependencies": { - "@docusaurus/mdx-loader": "3.9.2", - "@docusaurus/module-type-aliases": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", + "@docusaurus/mdx-loader": "3.10.1", + "@docusaurus/module-type-aliases": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -3919,19 +3956,20 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz", - "integrity": "sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw==", - "license": "MIT", - "dependencies": { - "@docsearch/react": "^3.9.0 || ^4.1.0", - "@docusaurus/core": "3.9.2", - "@docusaurus/logger": "3.9.2", - "@docusaurus/plugin-content-docs": "3.9.2", - "@docusaurus/theme-common": "3.9.2", - "@docusaurus/theme-translations": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-validation": "3.9.2", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.1.tgz", + "integrity": "sha512-OTaARARVZj2GvkJQjB+1jOIxntRaXea+G+fMsNqrZBAU1O1vJKDW22R7kECOHW27oJCLFN9HKaZeRrfAUyviug==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "^1.19.2", + "@docsearch/react": "^3.9.0 || ^4.3.2", + "@docusaurus/core": "3.10.1", + "@docusaurus/logger": "3.10.1", + "@docusaurus/plugin-content-docs": "3.10.1", + "@docusaurus/theme-common": "3.10.1", + "@docusaurus/theme-translations": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-validation": "3.10.1", "algoliasearch": "^5.37.0", "algoliasearch-helper": "^3.26.0", "clsx": "^2.0.0", @@ -3950,9 +3988,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz", - "integrity": "sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.1.tgz", + "integrity": "sha512-cLMyaKivjBVWKMJuWqyFVVgtqe8DPJNPkog0bn8W1MDVAKcPdxRFycBfC1We1RaNp7Rdk513bmtW78RR6OBxBw==", "license": "MIT", "dependencies": { "fs-extra": "^11.1.1", @@ -3963,9 +4001,9 @@ } }, "node_modules/@docusaurus/types": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.1.tgz", + "integrity": "sha512-XYMK8k1szDCFMw2V+Xyen0g7Kee1sP3dtFnl7vkGkZOkeAJ/oPDQPL8iz4HBKOo/cwU8QeV6onVjMqtP+tFzsw==", "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.0.0", @@ -3999,16 +4037,16 @@ } }, "node_modules/@docusaurus/utils": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.2.tgz", - "integrity": "sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.1.tgz", + "integrity": "sha512-3ojeJry9xBYdJO6qoyyzqeJFSJBVx2mXhyDzSdjwL2+URFQMf+h25gG38iswGImicK0ELjTd1EL2xzk8hf3QPw==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/types": "3.9.2", - "@docusaurus/utils-common": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/types": "3.10.1", + "@docusaurus/utils-common": "3.10.1", "escape-string-regexp": "^4.0.0", - "execa": "5.1.1", + "execa": "^5.1.1", "file-loader": "^6.2.0", "fs-extra": "^11.1.1", "github-slugger": "^1.5.0", @@ -4031,12 +4069,12 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.2.tgz", - "integrity": "sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.1.tgz", + "integrity": "sha512-5mFSgEADtnFxFH7RLw02QA5MpU5JVUCj0MPeIvi/aF4Fi45tQRIuTwXoXDqJ+1VfQJuYJGz3SI63wmGz4HvXzA==", "license": "MIT", "dependencies": { - "@docusaurus/types": "3.9.2", + "@docusaurus/types": "3.10.1", "tslib": "^2.6.0" }, "engines": { @@ -4044,14 +4082,14 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "3.9.2", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz", - "integrity": "sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.1.tgz", + "integrity": "sha512-cRv1X69jwaWv47waglllgZVWzeBFLhl53XT/XED/83BerVBTC5FTP8WTcVl8Z6sZOegDSwitu/wpCSPCDOT6lg==", "license": "MIT", "dependencies": { - "@docusaurus/logger": "3.9.2", - "@docusaurus/utils": "3.9.2", - "@docusaurus/utils-common": "3.9.2", + "@docusaurus/logger": "3.10.1", + "@docusaurus/utils": "3.10.1", + "@docusaurus/utils-common": "3.10.1", "fs-extra": "^11.2.0", "joi": "^17.9.2", "js-yaml": "^4.1.0", @@ -4210,13 +4248,13 @@ } }, "node_modules/@jsonjoy.com/fs-core": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.56.11.tgz", - "integrity": "sha512-wThHjzUp01ImIjfCwhs+UnFkeGPFAymwLEkOtenHewaKe2pTP12p6r1UuwikA9NEvNf9Vlck92r8fb8n/MWM5w==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz", + "integrity": "sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", "thingies": "^2.5.0" }, "engines": { @@ -4231,14 +4269,14 @@ } }, "node_modules/@jsonjoy.com/fs-fsa": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.56.11.tgz", - "integrity": "sha512-ZYlF3XbMayyp97xEN8ZvYutU99PCHjM64mMZvnCseXkCJXJDVLAwlF8Q/7q/xiWQRsv3pQBj1WXHd9eEyYcaCQ==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz", + "integrity": "sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", "thingies": "^2.5.0" }, "engines": { @@ -4253,16 +4291,16 @@ } }, "node_modules/@jsonjoy.com/fs-node": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.56.11.tgz", - "integrity": "sha512-D65YrnP6wRuZyEWoSFnBJSr5zARVpVBGctnhie4rCsMuGXNzX7IHKaOt85/Aj7SSoG1N2+/xlNjWmkLvZ2H3Tg==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz", + "integrity": "sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", - "@jsonjoy.com/fs-print": "4.56.11", - "@jsonjoy.com/fs-snapshot": "4.56.11", + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", "glob-to-regex.js": "^1.0.0", "thingies": "^2.5.0" }, @@ -4278,9 +4316,9 @@ } }, "node_modules/@jsonjoy.com/fs-node-builtins": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.56.11.tgz", - "integrity": "sha512-CNmt3a0zMCIhniFLXtzPWuUxXFU+U+2VyQiIrgt/rRVeEJNrMQUABaRbVxR0Ouw1LyR9RjaEkPM6nYpED+y43A==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz", + "integrity": "sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==", "license": "Apache-2.0", "engines": { "node": ">=10.0" @@ -4294,14 +4332,14 @@ } }, "node_modules/@jsonjoy.com/fs-node-to-fsa": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.56.11.tgz", - "integrity": "sha512-5OzGdvJDgZVo+xXWEYo72u81zpOWlxlbG4d4nL+hSiW+LKlua/dldNgPrpWxtvhgyntmdFQad2UTxFyGjJAGhA==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz", + "integrity": "sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-fsa": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11" + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2" }, "engines": { "node": ">=10.0" @@ -4315,12 +4353,12 @@ } }, "node_modules/@jsonjoy.com/fs-node-utils": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.56.11.tgz", - "integrity": "sha512-JADOZFDA3wRfsuxkT0+MYc4F9hJO2PYDaY66kRTG6NqGX3+bqmKu66YFYAbII/tEmQWPZeHoClUB23rtQM9UPg==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz", + "integrity": "sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-builtins": "4.56.11" + "@jsonjoy.com/fs-node-builtins": "4.57.2" }, "engines": { "node": ">=10.0" @@ -4334,12 +4372,12 @@ } }, "node_modules/@jsonjoy.com/fs-print": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.56.11.tgz", - "integrity": "sha512-rnaKRgCRIn8JGTjxhS0JPE38YM3Pj/H7SW4/tglhIPbfKEkky7dpPayNKV2qy25SZSL15oFVgH/62dMZ/z7cyA==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz", + "integrity": "sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.57.2", "tree-dump": "^1.1.0" }, "engines": { @@ -4354,13 +4392,13 @@ } }, "node_modules/@jsonjoy.com/fs-snapshot": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.56.11.tgz", - "integrity": "sha512-IIldPX+cIRQuUol9fQzSS3hqyECxVpYMJQMqdU3dCKZFRzEl1rkIkw4P6y7Oh493sI7YdxZlKr/yWdzEWZ1wGQ==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz", + "integrity": "sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==", "license": "Apache-2.0", "dependencies": { "@jsonjoy.com/buffers": "^17.65.0", - "@jsonjoy.com/fs-node-utils": "4.56.11", + "@jsonjoy.com/fs-node-utils": "4.57.2", "@jsonjoy.com/json-pack": "^17.65.0", "@jsonjoy.com/util": "^17.65.0" }, @@ -4618,7 +4656,6 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", - "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -4679,131 +4716,140 @@ } }, "node_modules/@peculiar/asn1-cms": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.6.1.tgz", - "integrity": "sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.7.0.tgz", + "integrity": "sha512-hew63shtzzvBcSHbhm+cyAmKe6AIfinT9hzEqSPjDC6opTTMKmTkQ0gHuN2KsWlvqiKw1S/fS94fhag/FJkioQ==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", - "@peculiar/asn1-x509-attr": "^2.6.1", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "@peculiar/asn1-x509-attr": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-csr": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.6.1.tgz", - "integrity": "sha512-WRWnKfIocHyzFYQTka8O/tXCiBquAPSrRjXbOkHbO4qdmS6loffCEGs+rby6WxxGdJCuunnhS2duHURhjyio6w==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.7.0.tgz", + "integrity": "sha512-VVsAyGqErT9D1SY4aEqozThXMVI+ssVRiv2DDeYuvpBKLIgZ3hYs3Ay3u/VSoKq6ESFi9cf6rf3IOOzfwh7oMA==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-ecc": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.6.1.tgz", - "integrity": "sha512-+Vqw8WFxrtDIN5ehUdvlN2m73exS2JVG0UAyfVB31gIfor3zWEAQPD+K9ydCxaj3MLen9k0JhKpu9LqviuCE1g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.7.0.tgz", + "integrity": "sha512-n7KEs/Q/wrB415cxy4fHOBhegp4NdJ15fkJPwcB/3/8iNBQC2L/N7SChJPKDJPZGYH0jD4Tg4/0vnHmwghnbKw==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-pfx": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.6.1.tgz", - "integrity": "sha512-nB5jVQy3MAAWvq0KY0R2JUZG8bO/bTLpnwyOzXyEh/e54ynGTatAR+csOnXkkVD9AFZ2uL8Z7EV918+qB1qDvw==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.7.0.tgz", + "integrity": "sha512-V/nrlQVmhg7lYAsM7E13UDL5erAwFv6kCIVFqNaMIHSVi7dngcT839JkRTkQBqznMG98l2XjxYk74ZztAohZzA==", "license": "MIT", "dependencies": { - "@peculiar/asn1-cms": "^2.6.1", - "@peculiar/asn1-pkcs8": "^2.6.1", - "@peculiar/asn1-rsa": "^2.6.1", - "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-cms": "^2.7.0", + "@peculiar/asn1-pkcs8": "^2.7.0", + "@peculiar/asn1-rsa": "^2.7.0", + "@peculiar/asn1-schema": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-pkcs8": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.6.1.tgz", - "integrity": "sha512-JB5iQ9Izn5yGMw3ZG4Nw3Xn/hb/G38GYF3lf7WmJb8JZUydhVGEjK/ZlFSWhnlB7K/4oqEs8HnfFIKklhR58Tw==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.7.0.tgz", + "integrity": "sha512-9GTl1nE8Mx1kTZ+7QyYatDyKsm34QcWRBFkY1iPvWC3X4Dona5s/tlLiQsx5WzVdZqiMBZNYT0buyw4/vbhnjw==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-pkcs9": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.6.1.tgz", - "integrity": "sha512-5EV8nZoMSxeWmcxWmmcolg22ojZRgJg+Y9MX2fnE2bGRo5KQLqV5IL9kdSQDZxlHz95tHvIq9F//bvL1OeNILw==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.7.0.tgz", + "integrity": "sha512-Bh7m+OuIaSEllPQcSd9OSp93F4ROWH7sbITWV8MI+8dwsjE5111/87VxiWVvYFKyww3vp39geLv9ENqhwWHcew==", "license": "MIT", "dependencies": { - "@peculiar/asn1-cms": "^2.6.1", - "@peculiar/asn1-pfx": "^2.6.1", - "@peculiar/asn1-pkcs8": "^2.6.1", - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", - "@peculiar/asn1-x509-attr": "^2.6.1", + "@peculiar/asn1-cms": "^2.7.0", + "@peculiar/asn1-pfx": "^2.7.0", + "@peculiar/asn1-pkcs8": "^2.7.0", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", + "@peculiar/asn1-x509-attr": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-rsa": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.6.1.tgz", - "integrity": "sha512-1nVMEh46SElUt5CB3RUTV4EG/z7iYc7EoaDY5ECwganibQPkZ/Y2eMsTKB/LeyrUJ+W/tKoD9WUqIy8vB+CEdA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.7.0.tgz", + "integrity": "sha512-/qvENQrXyTZURjMqSeofHul0JJt2sNSzSwk36pl2olkHbaioMQgrASDZAlHXl0xUlnVbHj0uGgOrBMTb5x2aJQ==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-schema": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz", - "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.7.0.tgz", + "integrity": "sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg==", "license": "MIT", "dependencies": { + "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.6", - "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-x509": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.6.1.tgz", - "integrity": "sha512-O9jT5F1A2+t3r7C4VT7LYGXqkGLK7Kj1xFpz7U0isPrubwU5PbDoyYtx6MiGst29yq7pXN5vZbQFKRCP+lLZlA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.7.0.tgz", + "integrity": "sha512-mUn9RRrkGDnG4ALfunDmzyRW5dg+sWCj/pfnCCqEHYbkGxEpvUt6iVJv8Yw1cyp6SWZ26ZE5oSmI5SqEaen15g==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.6", - "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-x509-attr": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.6.1.tgz", - "integrity": "sha512-tlW6cxoHwgcQghnJwv3YS+9OO1737zgPogZ+CgWRUK4roEwIPzRH4JEiG770xe5HX2ATfCpmX60gurfWIF9dcQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.7.0.tgz", + "integrity": "sha512-NS8e7SOgXipkzUPLF/sce7ukpMpWjhxYsH0n6Y+bHYo4TTxOb95Zv7hqwSuL212mj5YxovjdOKQOgH1As3E94w==", "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.6.0", - "@peculiar/asn1-x509": "^2.6.1", + "@peculiar/asn1-schema": "^2.7.0", + "@peculiar/asn1-x509": "^2.7.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, + "node_modules/@peculiar/utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@peculiar/utils/-/utils-2.0.3.tgz", + "integrity": "sha512-+oL3HPFRIZ1St2K50lWCXiioIgSoxzz7R1J3uF6neO2yl1sgmpgY6XXJH4BdpoDkMWznQTeYF6oWNDZLCdQ4eQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.8.1" + } + }, "node_modules/@peculiar/x509": { "version": "1.14.3", "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", @@ -5082,7 +5128,6 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5232,9 +5277,9 @@ } }, "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "license": "MIT", "dependencies": { "@types/ms": "*" @@ -5261,9 +5306,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -5300,9 +5345,9 @@ } }, "node_modules/@types/gtag.js": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.20.tgz", + "integrity": "sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg==", "license": "MIT" }, "node_modules/@types/hast": { @@ -5405,12 +5450,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "25.3.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.5.tgz", - "integrity": "sha512-oX8xrhvpiyRCQkG1MFchB09f+cXftgIXb3a7UUa4Y3wpmZPw5tyZGTLWhlESOLq1Rq6oDlc8npVU2/9xiCuXMA==", + "version": "25.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.1.tgz", + "integrity": "sha512-coJCN8O1q4AGyyqCAUSP06P+SrMTu18BkEj3NVAK07q6QUneD2wzj3CLv9+yP+BMeZQlMvneXqqvDe3w+xcq7g==", "license": "MIT", "dependencies": { - "undici-types": "~7.18.0" + "undici-types": "~7.19.0" } }, "node_modules/@types/prismjs": { @@ -5420,9 +5465,9 @@ "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz", - "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==", + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", "license": "MIT" }, "node_modules/@types/range-parser": { @@ -5436,7 +5481,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -5567,9 +5611,9 @@ "license": "MIT" }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", "license": "ISC" }, "node_modules/@webassemblyjs/ast": { @@ -5778,7 +5822,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5842,11 +5885,10 @@ } }, "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5888,35 +5930,34 @@ } }, "node_modules/algoliasearch": { - "version": "5.49.1", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.49.1.tgz", - "integrity": "sha512-X3Pp2aRQhg4xUC6PQtkubn5NpRKuUPQ9FPDQlx36SmpFwwH2N0/tw4c+NXV3nw3PsgeUs+BuWGP0gjz3TvENLQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "@algolia/abtesting": "1.15.1", - "@algolia/client-abtesting": "5.49.1", - "@algolia/client-analytics": "5.49.1", - "@algolia/client-common": "5.49.1", - "@algolia/client-insights": "5.49.1", - "@algolia/client-personalization": "5.49.1", - "@algolia/client-query-suggestions": "5.49.1", - "@algolia/client-search": "5.49.1", - "@algolia/ingestion": "1.49.1", - "@algolia/monitoring": "1.49.1", - "@algolia/recommend": "5.49.1", - "@algolia/requester-browser-xhr": "5.49.1", - "@algolia/requester-fetch": "5.49.1", - "@algolia/requester-node-http": "5.49.1" + "version": "5.52.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.52.1.tgz", + "integrity": "sha512-fHA8+kXTbjagw3jkLiaS7KKrH8qe2DyOsiUhGlN4cdT77PEsfqXZl7ewDk1hsg+pJnPlnE50XtLxjR91iJOpmg==", + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.18.1", + "@algolia/client-abtesting": "5.52.1", + "@algolia/client-analytics": "5.52.1", + "@algolia/client-common": "5.52.1", + "@algolia/client-insights": "5.52.1", + "@algolia/client-personalization": "5.52.1", + "@algolia/client-query-suggestions": "5.52.1", + "@algolia/client-search": "5.52.1", + "@algolia/ingestion": "1.52.1", + "@algolia/monitoring": "1.52.1", + "@algolia/recommend": "5.52.1", + "@algolia/requester-browser-xhr": "5.52.1", + "@algolia/requester-fetch": "5.52.1", + "@algolia/requester-node-http": "5.52.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/algoliasearch-helper": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.28.0.tgz", - "integrity": "sha512-GBN0xsxGggaCPElZq24QzMdfphrjIiV2xA+hRXE4/UMpN3nsF2WrM8q+x80OGvGpJWtB7F+4Hq5eSfWwuejXrg==", + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.29.1.tgz", + "integrity": "sha512-6ck2YFudF2Pje7szQoPBiRFTGfd+1I+0I/WfLPGn0bj1kvrFoOQmNyedNiDxTk3/r4IfSLDYk+RA4G7u8H6+yA==", "license": "MIT", "dependencies": { "@algolia/events": "^4.0.1" @@ -5954,33 +5995,6 @@ "node": ">=8" } }, - "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==", - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-html-community": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", @@ -6017,6 +6031,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansis": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-3.17.0.tgz", + "integrity": "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==", + "license": "ISC", + "engines": { + "node": ">=14" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -6058,13 +6081,13 @@ } }, "node_modules/asn1js": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz", - "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.10.tgz", + "integrity": "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg==", "license": "BSD-3-Clause", "dependencies": { "pvtsutils": "^1.3.6", - "pvutils": "^1.1.3", + "pvutils": "^1.1.5", "tslib": "^2.8.1" }, "engines": { @@ -6081,9 +6104,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.27", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz", - "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", "funding": [ { "type": "opencollective", @@ -6100,8 +6123,8 @@ ], "license": "MIT", "dependencies": { - "browserslist": "^4.28.1", - "caniuse-lite": "^1.0.30001774", + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" @@ -6143,13 +6166,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", - "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", "license": "MIT", "dependencies": { "@babel/compat-data": "^7.28.6", - "@babel/helper-define-polyfill-provider": "^0.6.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { @@ -6179,12 +6202,12 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", - "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.6" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -6207,9 +6230,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", - "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "version": "2.10.27", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.27.tgz", + "integrity": "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -6246,9 +6269,9 @@ } }, "node_modules/body-parser": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", - "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", "license": "MIT", "dependencies": { "bytes": "~3.1.2", @@ -6259,7 +6282,7 @@ "http-errors": "~2.0.1", "iconv-lite": "~0.4.24", "on-finished": "~2.4.1", - "qs": "~6.14.0", + "qs": "~6.15.1", "raw-body": "~2.5.3", "type-is": "~1.6.18", "unpipe": "~1.0.0" @@ -6293,6 +6316,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/bonjour-service": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", @@ -6332,9 +6370,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -6354,9 +6392,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", "funding": [ { "type": "opencollective", @@ -6372,13 +6410,12 @@ } ], "license": "MIT", - "peer": true, "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" @@ -6454,14 +6491,14 @@ } }, "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" }, "engines": { @@ -6544,9 +6581,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001777", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", - "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", "funding": [ { "type": "opencollective", @@ -7059,6 +7096,18 @@ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", "license": "MIT" }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz", + "integrity": "sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/copy-webpack-plugin": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", @@ -7127,9 +7176,9 @@ } }, "node_modules/core-js": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.48.0.tgz", - "integrity": "sha512-zpEHTy1fjTMZCKLHUZoVeylt9XrzaIN2rbPXEt0k+q7JE5CkCZdo6bNq55bn24a69CH7ErAVLKijxJja4fw+UQ==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", "hasInstallScript": true, "license": "MIT", "funding": { @@ -7138,9 +7187,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "license": "MIT", "dependencies": { "browserslist": "^4.28.1" @@ -7150,17 +7199,6 @@ "url": "https://opencollective.com/core-js" } }, - "node_modules/core-js-pure": { - "version": "3.48.0", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.48.0.tgz", - "integrity": "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==", - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -7273,9 +7311,9 @@ } }, "node_modules/css-declaration-sorter": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.3.1.tgz", - "integrity": "sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz", + "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==", "license": "ISC", "engines": { "node": "^14 || ^16 || >=18" @@ -7338,7 +7376,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8033,9 +8070,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.307", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", - "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "version": "1.5.352", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.352.tgz", + "integrity": "sha512-9wHk8x6dyuimoe18EdiDPWKExNdxYqo4fn4FwOVVper6RxT3cmpBwBkWWfSOCYJjQdIco/nPhJhNLmn4Ufg1Yg==", "license": "ISC" }, "node_modules/emoji-regex": { @@ -8079,13 +8116,13 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", - "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "version": "5.21.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.1.tgz", + "integrity": "sha512-8p7DUVq6XJnZEz9W4oSwiwycxBIjHjRzYb3Je3zVN+geKTRQKzAkR/K4PBExlS0090d9nshak6phMUxr3PDjmQ==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "tapable": "^2.3.3" }, "engines": { "node": ">=10.13.0" @@ -8131,9 +8168,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "license": "MIT" }, "node_modules/es-object-atoms": { @@ -8532,9 +8569,9 @@ "license": "MIT" }, "node_modules/express/node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "license": "MIT" }, "node_modules/express/node_modules/range-parser": { @@ -8593,9 +8630,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -8654,30 +8691,6 @@ "node": ">=0.4.0" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/figures/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==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/file-loader": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", @@ -8699,11 +8712,10 @@ } }, "node_modules/file-loader/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -8835,9 +8847,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", @@ -8903,9 +8915,9 @@ } }, "node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", + "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -9237,9 +9249,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9549,9 +9561,9 @@ } }, "node_modules/html-webpack-plugin": { - "version": "5.6.6", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.6.tgz", - "integrity": "sha512-bLjW01UTrvoWTJQL5LsMRo1SypHW80FTm12OJRSnr3v6YHNhfe+1r0MYUZJMACxnCHURVnBWRwAsWs2yPU9Ezw==", + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz", + "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==", "license": "MIT", "dependencies": { "@types/html-minifier-terser": "^6.0.0", @@ -9876,9 +9888,9 @@ } }, "node_modules/ipaddr.js": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.3.0.tgz", - "integrity": "sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", "license": "MIT", "engines": { "node": ">= 10" @@ -9939,12 +9951,12 @@ } }, "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", "license": "MIT", "dependencies": { - "hasown": "^2.0.2" + "hasown": "^2.0.3" }, "engines": { "node": ">= 0.4" @@ -10350,9 +10362,9 @@ } }, "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", "license": "MIT", "dependencies": { "universalify": "^2.0.0" @@ -10404,9 +10416,9 @@ } }, "node_modules/launch-editor": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.1.tgz", - "integrity": "sha512-lPSddlAAluRKJ7/cjRFoXUFzaX7q/YKI7yPHuEvSJVqoXvFnJov1/Ud87Aa4zULIbA9Nja4mSPK8l0z/7eV2wA==", + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz", + "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==", "license": "MIT", "dependencies": { "picocolors": "^1.1.1", @@ -10441,9 +10453,9 @@ "license": "MIT" }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "license": "MIT", "engines": { "node": ">=6.11.5" @@ -10483,9 +10495,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.debounce": { @@ -11007,19 +11019,19 @@ } }, "node_modules/memfs": { - "version": "4.56.11", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.56.11.tgz", - "integrity": "sha512-/GodtwVeKVIHZKLUSr2ZdOxKBC5hHki4JNCU22DoCGPEHr5o2PD5U721zvESKyWwCfTfavFl9WZYgA13OAYK0g==", + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz", + "integrity": "sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==", "license": "Apache-2.0", "dependencies": { - "@jsonjoy.com/fs-core": "4.56.11", - "@jsonjoy.com/fs-fsa": "4.56.11", - "@jsonjoy.com/fs-node": "4.56.11", - "@jsonjoy.com/fs-node-builtins": "4.56.11", - "@jsonjoy.com/fs-node-to-fsa": "4.56.11", - "@jsonjoy.com/fs-node-utils": "4.56.11", - "@jsonjoy.com/fs-print": "4.56.11", - "@jsonjoy.com/fs-snapshot": "4.56.11", + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-to-fsa": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", "@jsonjoy.com/json-pack": "^1.11.0", "@jsonjoy.com/util": "^1.9.0", "glob-to-regex.js": "^1.0.1", @@ -12920,9 +12932,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz", - "integrity": "sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", "license": "MIT", "dependencies": { "schema-utils": "^4.0.0", @@ -12995,9 +13007,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -13053,9 +13065,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", "license": "MIT" }, "node_modules/normalize-path": { @@ -13130,11 +13142,10 @@ } }, "node_modules/null-loader/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13605,9 +13616,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -13632,9 +13643,9 @@ } }, "node_modules/pkijs": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.3.3.tgz", - "integrity": "sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", + "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", "license": "BSD-3-Clause", "dependencies": { "@noble/hashes": "1.4.0", @@ -13649,9 +13660,9 @@ } }, "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", "funding": [ { "type": "opencollective", @@ -13667,7 +13678,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -14571,7 +14581,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15384,26 +15393,24 @@ } }, "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.4" + "react": "^19.2.6" } }, "node_modules/react-fast-compare": { @@ -15454,7 +15461,6 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", - "peer": true, "dependencies": { "@types/react": "*" }, @@ -15463,9 +15469,9 @@ } }, "node_modules/react-loadable-ssr-addon-v5-slorber": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz", + "integrity": "sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.10.3" @@ -15483,7 +15489,6 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -15698,9 +15703,9 @@ "license": "MIT" }, "node_modules/regjsparser": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz", + "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.1.0" @@ -15976,15 +15981,6 @@ "entities": "^2.0.0" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -16009,11 +16005,12 @@ "license": "MIT" }, "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", "license": "MIT", "dependencies": { + "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" @@ -16163,9 +16160,9 @@ "license": "MIT" }, "node_modules/sax": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz", - "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", "license": "BlueOak-1.0.0", "engines": { "node": ">=11.0.0" @@ -16547,13 +16544,13 @@ } }, "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" + "object-inspect": "^1.13.4" }, "engines": { "node": ">= 0.4" @@ -17033,9 +17030,9 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "license": "MIT", "engines": { "node": ">=6" @@ -17046,9 +17043,9 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", + "version": "5.47.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", + "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", @@ -17064,9 +17061,9 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.17", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", - "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz", + "integrity": "sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==", "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", @@ -17132,9 +17129,9 @@ "license": "MIT" }, "node_modules/thingies": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.5.0.tgz", - "integrity": "sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", "license": "MIT", "engines": { "node": ">=10.18" @@ -17244,8 +17241,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsyringe": { "version": "4.10.0", @@ -17321,9 +17317,9 @@ } }, "node_modules/undici-types": { - "version": "7.18.2", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", - "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { @@ -17649,11 +17645,10 @@ } }, "node_modules/url-loader/node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17753,6 +17748,7 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", "license": "MIT", "bin": { "uuid": "dist/bin/uuid" @@ -17848,11 +17844,10 @@ } }, "node_modules/webpack": { - "version": "5.105.4", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.4.tgz", - "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", + "version": "5.106.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", + "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", "license": "MIT", - "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -17870,9 +17865,8 @@ "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", + "mime-db": "^1.54.0", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", @@ -18082,9 +18076,9 @@ } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -18117,105 +18111,48 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", - "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", + "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==", "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/webpack/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, "engines": { "node": ">= 0.6" } }, "node_modules/webpackbar": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-6.0.1.tgz", - "integrity": "sha512-TnErZpmuKdwWBdMoexjio3KKX6ZtoKHRVvLIU0A47R0VVBDtx3ZyOJDktgYixhoJokZTYTt1Z37OkO9pnGJa9Q==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-7.0.0.tgz", + "integrity": "sha512-aS9soqSO2iCHgqHoCrj4LbfGQUboDCYJPSFOAchEK+9psIjNrfSWW4Y0YEz67MKURNvMmfo0ycOg9d/+OOf9/Q==", "license": "MIT", "dependencies": { - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", + "ansis": "^3.2.0", "consola": "^3.2.3", - "figures": "^3.2.0", - "markdown-table": "^2.0.0", "pretty-time": "^1.1.0", - "std-env": "^3.7.0", - "wrap-ansi": "^7.0.0" + "std-env": "^3.7.0" }, "engines": { "node": ">=14.21.3" }, "peerDependencies": { + "@rspack/core": "*", "webpack": "3 || 4 || 5" - } - }, - "node_modules/webpackbar/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/webpackbar/node_modules/markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "license": "MIT", - "dependencies": { - "repeat-string": "^1.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/webpackbar/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==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/webpackbar/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==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/websocket-driver": { diff --git a/docs/package.json b/docs/package.json index e05da191..fc615fd8 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,18 +14,18 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^3.9.2", - "@docusaurus/preset-classic": "^3.9.2", - "@docusaurus/theme-common": "^3.9.2", + "@docusaurus/core": "^3.10.1", + "@docusaurus/preset-classic": "^3.10.1", + "@docusaurus/theme-common": "^3.10.1", "@mdx-js/react": "^3.1.1", "clsx": "^2.1.1", "prism-react-renderer": "^2.4.1", - "react": "^19.2.4", - "react-dom": "^19.2.4" + "react": "^19.2.6", + "react-dom": "^19.2.6" }, "devDependencies": { - "@docusaurus/module-type-aliases": "^3.9.2", - "@docusaurus/types": "^3.9.2" + "@docusaurus/module-type-aliases": "^3.10.1", + "@docusaurus/types": "^3.10.1" }, "browserslist": { "production": [ diff --git a/domain/domain-events/domain-events-api.gradle b/domain/domain-events/domain-events-api.gradle index 7af7f448..b42e4b9e 100644 --- a/domain/domain-events/domain-events-api.gradle +++ b/domain/domain-events/domain-events-api.gradle @@ -5,5 +5,5 @@ ext { dependencies { api 'org.reactivestreams:reactive-streams:1.0.4' - api 'io.cloudevents:cloudevents-api:4.0.1' + api 'io.cloudevents:cloudevents-api:4.0.2' } \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index cd679d1d..8d5d2d88 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version=7.1.0 +version=7.1.1 toPublish=domain-events-api,async-commons-api,async-commons,cloudevents-json-jackson,reactor-rabbitmq,async-rabbit,async-commons-rabbit-starter,async-kafka,async-kafka-starter,async-commons-starter onlyUpdater=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d997cfc6..b1b8ef56 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c61a118f..b52fb7e7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 739907df..b9bb139f 100755 --- a/gradlew +++ b/gradlew @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/2d6327017519d23b96af35865dc997fcb544fb40/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index e509b2dd..aa5f10b0 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -23,8 +23,8 @@ @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/main.gradle b/main.gradle index 75310037..215ad386 100644 --- a/main.gradle +++ b/main.gradle @@ -91,7 +91,7 @@ subprojects { dependencyManagement { imports { - mavenBom 'org.springframework.boot:spring-boot-dependencies:4.0.4' + mavenBom 'org.springframework.boot:spring-boot-dependencies:4.0.6' } } @@ -187,6 +187,6 @@ tasks.register('generateMergedReport', JacocoReport) { } tasks.named('wrapper') { - gradleVersion = '9.4.1' + gradleVersion = '9.5.0' validateDistributionUrl = true } \ No newline at end of file diff --git a/samples/async/async-kafka-sender-client/async-kafka-sender-client.gradle b/samples/async/async-kafka-sender-client/async-kafka-sender-client.gradle index d73c3b23..9d3ba7af 100644 --- a/samples/async/async-kafka-sender-client/async-kafka-sender-client.gradle +++ b/samples/async/async-kafka-sender-client/async-kafka-sender-client.gradle @@ -4,7 +4,7 @@ dependencies { implementation project(':shared') implementation project(':async-kafka-starter') implementation project(':cloudevents-json-jackson') - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'io.micrometer:micrometer-registry-prometheus' diff --git a/samples/async/eda-async-receiver-responder/eda-async-receiver-sample.gradle b/samples/async/eda-async-receiver-responder/eda-async-receiver-sample.gradle index f8e8ef06..c3c59d4c 100644 --- a/samples/async/eda-async-receiver-responder/eda-async-receiver-sample.gradle +++ b/samples/async/eda-async-receiver-responder/eda-async-receiver-sample.gradle @@ -4,5 +4,5 @@ dependencies { implementation project(":shared") implementation project(":async-commons-rabbit-starter") implementation 'org.springframework.boot:spring-boot-starter' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' } \ No newline at end of file diff --git a/samples/async/eda-async-sender-client-domain-a/eda-async-sender-client-domain-a.gradle b/samples/async/eda-async-sender-client-domain-a/eda-async-sender-client-domain-a.gradle index b4fa1123..1c41e0e0 100644 --- a/samples/async/eda-async-sender-client-domain-a/eda-async-sender-client-domain-a.gradle +++ b/samples/async/eda-async-sender-client-domain-a/eda-async-sender-client-domain-a.gradle @@ -6,6 +6,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'io.micrometer:micrometer-registry-prometheus' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' } \ No newline at end of file diff --git a/samples/async/eda-async-sender-client/eda-async-sender-client.gradle b/samples/async/eda-async-sender-client/eda-async-sender-client.gradle index b4fa1123..1c41e0e0 100644 --- a/samples/async/eda-async-sender-client/eda-async-sender-client.gradle +++ b/samples/async/eda-async-sender-client/eda-async-sender-client.gradle @@ -6,6 +6,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-webflux' implementation 'org.springframework.boot:spring-boot-starter-actuator' implementation 'io.micrometer:micrometer-registry-prometheus' - implementation 'io.cloudevents:cloudevents-core:4.0.1' + implementation 'io.cloudevents:cloudevents-core:4.0.2' } \ No newline at end of file diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ConnectionManager.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ConnectionManager.java index 92ba2630..ccf61948 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ConnectionManager.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ConnectionManager.java @@ -1,5 +1,7 @@ package org.reactivecommons.async.starter.config; +import lombok.Getter; +import lombok.Setter; import org.reactivecommons.async.starter.broker.BrokerProvider; import java.util.Map; @@ -9,6 +11,9 @@ @SuppressWarnings("rawtypes") public class ConnectionManager { private final Map connections = new TreeMap<>(); + @Getter + @Setter + private String defaultDomain; public void forDomain(BiConsumer consumer) { connections.forEach(consumer); diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsConfig.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsConfig.java index 5c95e5b1..a04ded8e 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsConfig.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsConfig.java @@ -26,8 +26,6 @@ import java.util.Map; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; - @Log @Configuration @RequiredArgsConstructor @@ -43,7 +41,11 @@ public ConnectionManager buildConnectionManager(ApplicationContext context) { ConnectionManager connectionManager = new ConnectionManager(); props.forEach((beanName, domainProps) -> { - final GenericAsyncProps defaultDomainProps = domainProps.getProps(DEFAULT_DOMAIN); + final String defaultDomainName = domainProps.getDefaultDomainName(); + if (connectionManager.getDefaultDomain() == null) { + connectionManager.setDefaultDomain(defaultDomainName); + } + final GenericAsyncProps defaultDomainProps = domainProps.getProps(defaultDomainName); domainProps.forEach((domain, asyncPropsObject) -> { String domainName = (String) domain; final GenericAsyncProps asyncProps = (GenericAsyncProps) asyncPropsObject; diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsListenersConfig.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsListenersConfig.java index 0f7a7a11..b08b51b5 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsListenersConfig.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/config/ReactiveCommonsListenersConfig.java @@ -23,6 +23,12 @@ @ComponentScan("org.reactivecommons.async.starter.impl.listener") public class ReactiveCommonsListenersConfig { + /** + * Builds the {@link DomainHandlers} by resolving all registered {@link HandlerRegistry} beans against each + * configured domain. The first configured domain always gets {@link HandlerRegistry#DEFAULT_DOMAIN} as + * its alias, ensuring that all handlers registered via the standard API (which internally stores them under + * the default key) are always resolved by the first domain, regardless of its actual name. + */ @Bean @SuppressWarnings({"rawtypes", "unchecked"}) public DomainHandlers buildHandlers(ApplicationContext context, @@ -33,15 +39,20 @@ public DomainHandlers buildHandlers(ApplicationContext context, registries.put("primaryHandlerRegistry", primaryRegistry); } final Map props = context.getBeansOfType(GenericAsyncPropsDomain.class); - props.forEach((beanName, properties) -> properties - .forEach((domain, asyncProps) -> { - String domainName = (String) domain; - HandlerResolver resolver = HandlerResolverBuilder.buildResolver( - domainName, registries, commandHandler - ); - handlers.add(domainName, resolver); - }) - ); + props.forEach((beanName, properties) -> { + String defaultDomain = properties.getDefaultDomainName(); + log.info("DEFAULT_DOMAIN: " + defaultDomain); + properties.forEach((domain, asyncProps) -> { + String domainName = (String) domain; + String aliasDomain = domainName.equals(defaultDomain) ? HandlerRegistry.getUnresolvedDomain() : null; + log.info("DOMAIN: " + domainName); + log.info("ALIAS_DOMAIN: " + aliasDomain); + HandlerResolver resolver = HandlerResolverBuilder.buildResolver( + domainName, aliasDomain, registries, commandHandler + ); + handlers.add(domainName, resolver); + }); + }); return handlers; } diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomain.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomain.java index a0c21f5d..cee0ae3f 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomain.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomain.java @@ -7,18 +7,17 @@ import tools.jackson.databind.json.JsonMapper; import java.lang.reflect.Constructor; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; - @Getter @Setter -public class GenericAsyncPropsDomain, P> extends HashMap { +public class GenericAsyncPropsDomain, P> extends LinkedHashMap { private Class asyncPropsClass; private Class

propsClass; + private String defaultDomainName; public GenericAsyncPropsDomain(String defaultAppName, P defaultProperties, @@ -31,9 +30,10 @@ public GenericAsyncPropsDomain(String defaultAppName, this.asyncPropsClass = asyncPropsClass; JsonMapper mapper = JsonMapper.builder().findAndAddModules().build(); - if (!this.containsKey(DEFAULT_DOMAIN)) { - throw new InvalidConfigurationException("Required domain '" + DEFAULT_DOMAIN + "' is not configured."); + if (this.isEmpty()) { + throw new InvalidConfigurationException("At least one domain must be configured."); } + this.defaultDomainName = this.keySet().iterator().next(); super.forEach((key, value) -> { // To ensure that each domain has an appName if (value.getAppName() == null) { @@ -93,7 +93,7 @@ public static class AsyncPropsDomainBuilder< private final Class asyncPropsDomainClass; private final Constructor returnType; private String defaultAppName; - private final HashMap domains = new HashMap<>(); + private final Map domains = new LinkedHashMap<>(); private P defaultProperties; private SecretFiller

secretFiller; @@ -147,6 +147,7 @@ private static X instantiate(Class xClass, Map arg) { } + @Deprecated(forRemoval = true, since = "7.0.0") public interface SecretFiller

{ void fillWithSecret(String domain, GenericAsyncProps

props); } diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomainProperties.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomainProperties.java index c9a784f5..fd376027 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomainProperties.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/props/GenericAsyncPropsDomainProperties.java @@ -4,12 +4,12 @@ import lombok.Setter; import lombok.SneakyThrows; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; @Getter @Setter -public class GenericAsyncPropsDomainProperties, P> extends HashMap { +public class GenericAsyncPropsDomainProperties, P> extends LinkedHashMap { public GenericAsyncPropsDomainProperties(Map m) { super(m); @@ -27,7 +27,7 @@ public GenericAsyncPropsDomainProperties() { public static class AsyncPropsDomainPropertiesBuilder, P, X extends GenericAsyncPropsDomainProperties> { - private final Map domains = new HashMap<>(); + private final Map domains = new LinkedHashMap<>(); private final Class returnType; public AsyncPropsDomainPropertiesBuilder(Class returnType) { diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/DirectAsyncGatewayConfig.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/DirectAsyncGatewayConfig.java index e1654baf..2b67778f 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/DirectAsyncGatewayConfig.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/DirectAsyncGatewayConfig.java @@ -23,6 +23,6 @@ public DirectAsyncGateway genericDirectAsyncGateway(ConnectionManager manager) { ConcurrentMap directAsyncGateways = new ConcurrentHashMap<>(); manager.forDomain((domain, provider) -> directAsyncGateways.put(domain, provider.getDirectAsyncGateway())); - return new GenericDirectAsyncGateway(directAsyncGateways); + return new GenericDirectAsyncGateway(directAsyncGateways, manager.getDefaultDomain()); } } diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/EventBusConfig.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/EventBusConfig.java index b2b69e0b..f046fad2 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/EventBusConfig.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/EventBusConfig.java @@ -18,6 +18,6 @@ public class EventBusConfig { public DomainEventBus genericDomainEventBus(ConnectionManager manager) { ConcurrentMap domainEventBuses = new ConcurrentHashMap<>(); manager.forDomain((domain, provider) -> domainEventBuses.put(domain, provider.getDomainBus())); - return new GenericDomainEventBus(domainEventBuses); + return new GenericDomainEventBus(domainEventBuses, manager.getDefaultDomain()); } } diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGateway.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGateway.java index 532379f8..b8000afd 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGateway.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGateway.java @@ -1,7 +1,6 @@ package org.reactivecommons.async.starter.senders; import io.cloudevents.CloudEvent; -import lombok.RequiredArgsConstructor; import org.reactivecommons.api.domain.Command; import org.reactivecommons.async.api.AsyncQuery; import org.reactivecommons.async.api.DirectAsyncGateway; @@ -10,20 +9,23 @@ import java.util.concurrent.ConcurrentMap; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; - -@RequiredArgsConstructor public class GenericDirectAsyncGateway implements DirectAsyncGateway { private final ConcurrentMap directAsyncGateways; + private final String defaultDomain; + + public GenericDirectAsyncGateway(ConcurrentMap directAsyncGateways, String defaultDomain) { + this.directAsyncGateways = directAsyncGateways; + this.defaultDomain = defaultDomain; + } @Override public Mono sendCommand(Command command, String targetName) { - return sendCommand(command, targetName, DEFAULT_DOMAIN); + return sendCommand(command, targetName, defaultDomain); } @Override public Mono sendCommand(Command command, String targetName, long delayMillis) { - return sendCommand(command, targetName, delayMillis, DEFAULT_DOMAIN); + return sendCommand(command, targetName, delayMillis, defaultDomain); } @Override @@ -38,12 +40,12 @@ public Mono sendCommand(Command command, String targetName, long de @Override public Mono sendCommand(CloudEvent command, String targetName) { - return sendCommand(command, targetName, DEFAULT_DOMAIN); + return sendCommand(command, targetName, defaultDomain); } @Override public Mono sendCommand(CloudEvent command, String targetName, long delayMillis) { - return sendCommand(command, targetName, delayMillis, DEFAULT_DOMAIN); + return sendCommand(command, targetName, delayMillis, defaultDomain); } @Override @@ -58,7 +60,7 @@ public Mono sendCommand(CloudEvent command, String targetName, long delayM @Override public Mono requestReply(AsyncQuery query, String targetName, Class type) { - return requestReply(query, targetName, type, DEFAULT_DOMAIN); + return requestReply(query, targetName, type, defaultDomain); } @Override @@ -68,7 +70,7 @@ public Mono requestReply(AsyncQuery query, String targetName, Class @Override public Mono requestReply(CloudEvent query, String targetName, Class type) { - return requestReply(query, targetName, type, DEFAULT_DOMAIN); + return requestReply(query, targetName, type, defaultDomain); } @Override @@ -78,6 +80,6 @@ public Mono requestReply(CloudEvent query, String targ @Override public Mono reply(T response, From from) { - return directAsyncGateways.get(DEFAULT_DOMAIN).reply(response, from); + return directAsyncGateways.get(defaultDomain).reply(response, from); } } diff --git a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDomainEventBus.java b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDomainEventBus.java index fd7fbe25..4ceaf806 100644 --- a/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDomainEventBus.java +++ b/starters/async-commons-starter/src/main/java/org/reactivecommons/async/starter/senders/GenericDomainEventBus.java @@ -11,17 +11,15 @@ import java.util.concurrent.ConcurrentMap; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; - @RequiredArgsConstructor public class GenericDomainEventBus implements DomainEventBus { private static final String DOMAIN_NOT_FOUND = "Domain not found: "; private final ConcurrentMap domainEventBuses; - + private final String defaultDomain; @Override public Publisher emit(DomainEvent event) { - return emit(DEFAULT_DOMAIN, event); + return emit(defaultDomain, event); } @Override @@ -35,7 +33,7 @@ public Publisher emit(String domain, DomainEvent event) { @Override public Publisher emit(CloudEvent event) { - return emit(DEFAULT_DOMAIN, event); + return emit(defaultDomain, event); } @Override @@ -49,7 +47,7 @@ public Publisher emit(String domain, CloudEvent event) { @Override public Publisher emit(RawMessage event) { - return emit(DEFAULT_DOMAIN, event); + return emit(defaultDomain, event); } @Override diff --git a/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGatewayTest.java b/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGatewayTest.java index 5b6ca9bd..bb8843dd 100644 --- a/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGatewayTest.java +++ b/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDirectAsyncGatewayTest.java @@ -51,7 +51,7 @@ void setUp() { ConcurrentHashMap directAsyncGateways = new ConcurrentHashMap<>(); directAsyncGateways.put(DEFAULT_DOMAIN, directAsyncGateway1); directAsyncGateways.put(DOMAIN_2, directAsyncGateway2); - genericDirectAsyncGateway = new GenericDirectAsyncGateway(directAsyncGateways); + genericDirectAsyncGateway = new GenericDirectAsyncGateway(directAsyncGateways, DEFAULT_DOMAIN); } @Test diff --git a/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDomainEventBusTest.java b/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDomainEventBusTest.java index c05dac31..1fe08a3a 100644 --- a/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDomainEventBusTest.java +++ b/starters/async-commons-starter/src/test/java/org/reactivecommons/async/starter/senders/GenericDomainEventBusTest.java @@ -39,7 +39,7 @@ void setUp() { ConcurrentHashMap domainEventBuses = new ConcurrentHashMap<>(); domainEventBuses.put(DEFAULT_DOMAIN, domainEventBus1); domainEventBuses.put(DOMAIN_2, domainEventBus2); - genericDomainEventBus = new GenericDomainEventBus(domainEventBuses); + genericDomainEventBus = new GenericDomainEventBus(domainEventBuses, DEFAULT_DOMAIN); } @Test diff --git a/starters/async-kafka-starter/src/main/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomain.java b/starters/async-kafka-starter/src/main/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomain.java index ea9f9496..5a4be32e 100644 --- a/starters/async-kafka-starter/src/main/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomain.java +++ b/starters/async-kafka-starter/src/main/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomain.java @@ -3,7 +3,10 @@ import lombok.Getter; import lombok.Setter; import org.reactivecommons.async.kafka.config.KafkaProperties; +import org.reactivecommons.async.starter.exceptions.InvalidConfigurationException; import org.reactivecommons.async.starter.props.GenericAsyncPropsDomain; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import java.lang.reflect.Constructor; @@ -12,7 +15,17 @@ @Setter public class AsyncKafkaPropsDomain extends GenericAsyncPropsDomain { + @Autowired public AsyncKafkaPropsDomain(@Value("${spring.application.name}") String defaultAppName, + KafkaProperties defaultKafkaProperties, + AsyncKafkaPropsDomainProperties configured, + KafkaSecretFiller kafkaSecretFiller, + ObjectProvider customizer) { + super(defaultAppName, defaultKafkaProperties, applyCustomizer(configured, customizer.getIfAvailable()), + kafkaSecretFiller, AsyncKafkaProps.class, KafkaProperties.class); + } + + public AsyncKafkaPropsDomain(String defaultAppName, KafkaProperties defaultKafkaProperties, AsyncKafkaPropsDomainProperties configured, KafkaSecretFiller kafkaSecretFiller) { @@ -20,15 +33,47 @@ public AsyncKafkaPropsDomain(@Value("${spring.application.name}") String default KafkaProperties.class); } - @SuppressWarnings("unchecked") public static AsyncPropsDomainBuilder builder() { - return GenericAsyncPropsDomain.builder(KafkaProperties.class, - AsyncKafkaPropsDomainProperties.class, - (Constructor) AsyncKafkaPropsDomain.class.getDeclaredConstructors()[0]); + try { + Constructor ctor = AsyncKafkaPropsDomain.class.getDeclaredConstructor( + String.class, KafkaProperties.class, AsyncKafkaPropsDomainProperties.class, + KafkaSecretFiller.class); + return GenericAsyncPropsDomain.builder(KafkaProperties.class, + AsyncKafkaPropsDomainProperties.class, ctor); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Constructor not found", e); + } } + private static AsyncKafkaPropsDomainProperties applyCustomizer( + AsyncKafkaPropsDomainProperties configured, KafkaPropsCustomizer customizer) { + if (customizer != null) { + customizer.customize(configured); + if (configured.isEmpty()) { + throw new InvalidConfigurationException(""" + KafkaPropsCustomizer was applied but no domain is defined. \ + When using KafkaPropsCustomizer, you must declare at least one \ + domain in your application.yaml (reactive.commons.kafka..*), or add new \ + domains directly inside the customizer using \ + domainProperties.put("", AsyncKafkaProps.builder()...build())."""); + } + } + return configured; + } + + @Deprecated(forRemoval = true, since = "7.0.0") public interface KafkaSecretFiller extends GenericAsyncPropsDomain.SecretFiller { } + /** + * Customizer interface for Kafka async properties. + * Allows programmatic modification of properties loaded from YAML configuration. + * Properties modified through this customizer take precedence over YAML values. + */ + @FunctionalInterface + public interface KafkaPropsCustomizer { + void customize(AsyncKafkaPropsDomainProperties domainProperties); + } + } diff --git a/starters/async-kafka-starter/src/test/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomainCustomizerTest.java b/starters/async-kafka-starter/src/test/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomainCustomizerTest.java new file mode 100644 index 00000000..36da54d3 --- /dev/null +++ b/starters/async-kafka-starter/src/test/java/org/reactivecommons/async/kafka/config/props/AsyncKafkaPropsDomainCustomizerTest.java @@ -0,0 +1,161 @@ +package org.reactivecommons.async.kafka.config.props; + +import org.junit.jupiter.api.Test; +import org.reactivecommons.async.kafka.config.KafkaProperties; +import org.springframework.beans.factory.ObjectProvider; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; + +class AsyncKafkaPropsDomainCustomizerTest { + + @Test + void shouldMergeCustomizerWithYamlProperties() { + // Arrange - simulate YAML-loaded properties + AsyncKafkaPropsDomainProperties yamlProps = new AsyncKafkaPropsDomainProperties(); + AsyncKafkaProps appProps = AsyncKafkaProps.builder() + .withDLQRetry(false) + .maxRetries(3) + .retryDelay(10000) + .checkExistingTopics(true) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + KafkaProperties defaultKafkaProperties = new KafkaProperties(); + defaultKafkaProperties.setBootstrapServers(List.of("localhost:9092")); + + // Arrange - customizer that overrides specific properties + KafkaProperties customConnProps = new KafkaProperties(); + customConnProps.setBootstrapServers(List.of("custom-host:9093")); + + AsyncKafkaPropsDomain.KafkaPropsCustomizer customizer = domainProperties -> { + AsyncKafkaProps props = domainProperties.get(DEFAULT_DOMAIN); + if (props != null) { + props.setConnectionProperties(customConnProps); + props.setRetryDelay(500000); + } + }; + + @SuppressWarnings("unchecked") + ObjectProvider customizerProvider = mock(ObjectProvider.class); + when(customizerProvider.getIfAvailable()).thenReturn(customizer); + + AsyncKafkaPropsDomain.KafkaSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncKafkaPropsDomain propsDomain = new AsyncKafkaPropsDomain( + "test-app", defaultKafkaProperties, yamlProps, secretFiller, customizerProvider); + + // Assert - customizer values take precedence + AsyncKafkaProps result = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(result.getRetryDelay()).isEqualTo(500000); + assertThat(result.getConnectionProperties().getBootstrapServers()).containsExactly("custom-host:9093"); + + // Assert - YAML values are preserved for non-customized properties + assertThat(result.getWithDLQRetry()).isFalse(); + assertThat(result.getMaxRetries()).isEqualTo(3); + assertThat(result.getCheckExistingTopics()).isTrue(); + } + + @Test + void shouldWorkWithoutCustomizer() { + // Arrange + AsyncKafkaPropsDomainProperties yamlProps = new AsyncKafkaPropsDomainProperties(); + AsyncKafkaProps appProps = AsyncKafkaProps.builder() + .maxRetries(5) + .retryDelay(2000) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + KafkaProperties defaultKafkaProperties = new KafkaProperties(); + + @SuppressWarnings("unchecked") + ObjectProvider customizerProvider = mock(ObjectProvider.class); + when(customizerProvider.getIfAvailable()).thenReturn(null); + + AsyncKafkaPropsDomain.KafkaSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncKafkaPropsDomain propsDomain = new AsyncKafkaPropsDomain( + "test-app", defaultKafkaProperties, yamlProps, secretFiller, customizerProvider); + + // Assert - YAML values are preserved + AsyncKafkaProps result = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(result.getMaxRetries()).isEqualTo(5); + assertThat(result.getRetryDelay()).isEqualTo(2000); + } + + @Test + void shouldAllowCustomizerToAddNewDomains() { + // Arrange - YAML has only default domain + AsyncKafkaPropsDomainProperties yamlProps = new AsyncKafkaPropsDomainProperties(); + AsyncKafkaProps appProps = AsyncKafkaProps.builder() + .maxRetries(3) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + KafkaProperties defaultKafkaProperties = new KafkaProperties(); + defaultKafkaProperties.setBootstrapServers(List.of("localhost:9092")); + + KafkaProperties accountsConnProps = new KafkaProperties(); + accountsConnProps.setBootstrapServers(List.of("accounts-host:9093")); + + // Customizer adds a new domain + AsyncKafkaPropsDomain.KafkaPropsCustomizer customizer = domainProperties -> { + AsyncKafkaProps accountsProps = AsyncKafkaProps.builder() + .connectionProperties(accountsConnProps) + .maxRetries(10) + .build(); + domainProperties.put("accounts", accountsProps); + }; + + @SuppressWarnings("unchecked") + ObjectProvider customizerProvider = mock(ObjectProvider.class); + when(customizerProvider.getIfAvailable()).thenReturn(customizer); + + AsyncKafkaPropsDomain.KafkaSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncKafkaPropsDomain propsDomain = new AsyncKafkaPropsDomain( + "test-app", defaultKafkaProperties, yamlProps, secretFiller, customizerProvider); + + // Assert - original domain is preserved + AsyncKafkaProps appResult = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(appResult.getMaxRetries()).isEqualTo(3); + + // Assert - new domain was added by customizer + AsyncKafkaProps accountsResult = propsDomain.getProps("accounts"); + assertThat(accountsResult.getConnectionProperties().getBootstrapServers()).containsExactly("accounts-host:9093"); + assertThat(accountsResult.getMaxRetries()).isEqualTo(10); + } + + @Test + void shouldWorkWithFourParamConstructor() { + // Arrange - backward compatibility + AsyncKafkaPropsDomainProperties yamlProps = new AsyncKafkaPropsDomainProperties(); + AsyncKafkaProps appProps = AsyncKafkaProps.builder() + .maxRetries(7) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + KafkaProperties defaultKafkaProperties = new KafkaProperties(); + + AsyncKafkaPropsDomain.KafkaSecretFiller secretFiller = (domain, props) -> { + }; + + // Act - uses 4-param constructor (no customizer) + AsyncKafkaPropsDomain propsDomain = new AsyncKafkaPropsDomain( + "test-app", defaultKafkaProperties, yamlProps, secretFiller); + + // Assert + AsyncKafkaProps result = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(result.getMaxRetries()).isEqualTo(7); + } +} diff --git a/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomain.java b/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomain.java index d72aaff8..6a66d1a1 100644 --- a/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomain.java +++ b/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomain.java @@ -3,7 +3,10 @@ import lombok.Getter; import lombok.Setter; import org.reactivecommons.async.rabbit.config.RabbitProperties; +import org.reactivecommons.async.starter.exceptions.InvalidConfigurationException; import org.reactivecommons.async.starter.props.GenericAsyncPropsDomain; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import java.lang.reflect.Constructor; @@ -11,7 +14,18 @@ @Getter @Setter public class AsyncPropsDomain extends GenericAsyncPropsDomain { + + @Autowired public AsyncPropsDomain(@Value("${spring.application.name}") String defaultAppName, + RabbitProperties defaultRabbitProperties, + AsyncRabbitPropsDomainProperties configured, + RabbitSecretFiller secretFiller, + ObjectProvider customizer) { + super(defaultAppName, defaultRabbitProperties, applyCustomizer(configured, customizer.getIfAvailable()), + secretFiller, AsyncProps.class, RabbitProperties.class); + } + + public AsyncPropsDomain(String defaultAppName, RabbitProperties defaultRabbitProperties, AsyncRabbitPropsDomainProperties configured, RabbitSecretFiller secretFiller) { @@ -19,12 +33,17 @@ public AsyncPropsDomain(@Value("${spring.application.name}") String defaultAppNa RabbitProperties.class); } - @SuppressWarnings("unchecked") public static AsyncPropsDomainBuilder builder() { - return GenericAsyncPropsDomain.builder(RabbitProperties.class, - AsyncRabbitPropsDomainProperties.class, - (Constructor) AsyncPropsDomain.class.getDeclaredConstructors()[0]); + try { + Constructor ctor = AsyncPropsDomain.class.getDeclaredConstructor( + String.class, RabbitProperties.class, AsyncRabbitPropsDomainProperties.class, + RabbitSecretFiller.class); + return GenericAsyncPropsDomain.builder(RabbitProperties.class, + AsyncRabbitPropsDomainProperties.class, ctor); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Constructor not found", e); + } } @Override @@ -34,7 +53,34 @@ protected void fillCustoms(AsyncProps asyncProps) { } } + private static AsyncRabbitPropsDomainProperties applyCustomizer( + AsyncRabbitPropsDomainProperties configured, RabbitPropsCustomizer customizer) { + if (customizer != null) { + customizer.customize(configured); + if (configured.isEmpty()) { + throw new InvalidConfigurationException(""" + RabbitPropsCustomizer was applied but no domain is defined. \ + When using RabbitPropsCustomizer, you must declare at least one \ + domain in your application.yaml (app.async..*), or add new \ + domains directly inside the customizer using \ + domainProperties.put("", AsyncProps.builder()...build())."""); + } + } + return configured; + } + + @Deprecated(forRemoval = true, since = "7.0.0") public interface RabbitSecretFiller extends SecretFiller { } + /** + * Customizer interface for RabbitMQ async properties. + * Allows programmatic modification of properties loaded from YAML configuration. + * Properties modified through this customizer take precedence over YAML values. + */ + @FunctionalInterface + public interface RabbitPropsCustomizer { + void customize(AsyncRabbitPropsDomainProperties domainProperties); + } + } diff --git a/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/starter/impl/listener/rabbit/RabbitMQListenerOnlyConfig.java b/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/starter/impl/listener/rabbit/RabbitMQListenerOnlyConfig.java index 098cc414..22bab404 100644 --- a/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/starter/impl/listener/rabbit/RabbitMQListenerOnlyConfig.java +++ b/starters/async-rabbit-starter/src/main/java/org/reactivecommons/async/starter/impl/listener/rabbit/RabbitMQListenerOnlyConfig.java @@ -14,17 +14,16 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; - @Configuration public class RabbitMQListenerOnlyConfig { @Bean @ConditionalOnMissingBean(DynamicRegistry.class) public DynamicRegistry dynamicRegistry(AsyncPropsDomain asyncPropsDomain, DomainHandlers handlers, ConnectionFactoryCustomizer cfCustomizer) { - AsyncProps props = asyncPropsDomain.getProps(DEFAULT_DOMAIN); + String defaultDomain = asyncPropsDomain.getDefaultDomainName(); + AsyncProps props = asyncPropsDomain.getProps(defaultDomain); TopologyCreator topologyCreator = RabbitMQSetupUtils.createTopologyCreator(props, cfCustomizer); - IBrokerConfigProps brokerConfigProps = new BrokerConfigProps(asyncPropsDomain.getProps(DEFAULT_DOMAIN)); - return new DynamicRegistryImp(handlers.get(DEFAULT_DOMAIN), topologyCreator, brokerConfigProps); + IBrokerConfigProps brokerConfigProps = new BrokerConfigProps(asyncPropsDomain.getProps(defaultDomain)); + return new DynamicRegistryImp(handlers.get(defaultDomain), topologyCreator, brokerConfigProps); } } diff --git a/starters/async-rabbit-starter/src/test/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomainCustomizerTest.java b/starters/async-rabbit-starter/src/test/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomainCustomizerTest.java new file mode 100644 index 00000000..699c3b17 --- /dev/null +++ b/starters/async-rabbit-starter/src/test/java/org/reactivecommons/async/rabbit/config/props/AsyncPropsDomainCustomizerTest.java @@ -0,0 +1,243 @@ +package org.reactivecommons.async.rabbit.config.props; + +import org.junit.jupiter.api.Test; +import org.reactivecommons.async.rabbit.config.RabbitProperties; +import org.springframework.beans.factory.ObjectProvider; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.reactivecommons.async.api.HandlerRegistry.DEFAULT_DOMAIN; + +class AsyncPropsDomainCustomizerTest { + + @SuppressWarnings("unchecked") + private ObjectProvider customizerProviderOf( + AsyncPropsDomain.RabbitPropsCustomizer customizer) { + ObjectProvider customizerProvider = mock(ObjectProvider.class); + when(customizerProvider.getIfAvailable()).thenReturn(customizer); + return customizerProvider; + } + + @Test + void shouldMergeCustomizerWithYamlProperties() { + // Arrange - simulate YAML-loaded properties + AsyncRabbitPropsDomainProperties yamlProps = new AsyncRabbitPropsDomainProperties(); + AsyncProps appProps = AsyncProps.builder() + .withDLQRetry(false) + .maxRetries(3) + .retryDelay(10000) + .listenReplies(false) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + RabbitProperties defaultRabbitProperties = new RabbitProperties(); + defaultRabbitProperties.setHost("localhost"); + defaultRabbitProperties.setPort(5672); + + // Arrange - customizer that overrides specific properties + RabbitProperties customConnProps = new RabbitProperties(); + customConnProps.setHost("custom-host"); + customConnProps.setPort(5673); + + AsyncPropsDomain.RabbitPropsCustomizer customizer = domainProperties -> { + AsyncProps props = domainProperties.get(DEFAULT_DOMAIN); + if (props != null) { + props.setConnectionProperties(customConnProps); + props.setRetryDelay(500000); + } + }; + + AsyncPropsDomain.RabbitSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncPropsDomain propsDomain = new AsyncPropsDomain( + "test-app", defaultRabbitProperties, yamlProps, secretFiller, customizerProviderOf(customizer)); + + // Assert - customizer values take precedence + AsyncProps result = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(result.getRetryDelay()).isEqualTo(500000); + assertThat(result.getConnectionProperties().getHost()).isEqualTo("custom-host"); + assertThat(result.getConnectionProperties().getPort()).isEqualTo(5673); + + // Assert - YAML values are preserved for non-customized properties + assertThat(result.getWithDLQRetry()).isFalse(); + assertThat(result.getMaxRetries()).isEqualTo(3); + assertThat(result.getListenReplies()).isFalse(); + } + + @Test + void shouldWorkWithoutCustomizer() { + // Arrange - simulate YAML-loaded properties + AsyncRabbitPropsDomainProperties yamlProps = new AsyncRabbitPropsDomainProperties(); + AsyncProps appProps = AsyncProps.builder() + .maxRetries(5) + .retryDelay(2000) + .listenReplies(true) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + RabbitProperties defaultRabbitProperties = new RabbitProperties(); + + AsyncPropsDomain.RabbitSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncPropsDomain propsDomain = new AsyncPropsDomain( + "test-app", defaultRabbitProperties, yamlProps, secretFiller, customizerProviderOf(null)); + + // Assert - YAML values are preserved + AsyncProps result = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(result.getMaxRetries()).isEqualTo(5); + assertThat(result.getRetryDelay()).isEqualTo(2000); + assertThat(result.getListenReplies()).isTrue(); + } + + @Test + void shouldAllowCustomizerToAddNewDomains() { + // Arrange - YAML has only default domain + AsyncRabbitPropsDomainProperties yamlProps = new AsyncRabbitPropsDomainProperties(); + AsyncProps appProps = AsyncProps.builder() + .maxRetries(3) + .listenReplies(true) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + RabbitProperties defaultRabbitProperties = new RabbitProperties(); + defaultRabbitProperties.setHost("localhost"); + + RabbitProperties accountsConnProps = new RabbitProperties(); + accountsConnProps.setHost("accounts-host"); + accountsConnProps.setPort(5673); + + // Customizer adds a new domain + AsyncPropsDomain.RabbitPropsCustomizer customizer = domainProperties -> { + AsyncProps accountsProps = AsyncProps.builder() + .connectionProperties(accountsConnProps) + .maxRetries(10) + .listenReplies(false) + .build(); + domainProperties.put("accounts", accountsProps); + }; + + AsyncPropsDomain.RabbitSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncPropsDomain propsDomain = new AsyncPropsDomain( + "test-app", defaultRabbitProperties, yamlProps, secretFiller, customizerProviderOf(customizer)); + + // Assert - original domain is preserved + AsyncProps appResult = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(appResult.getMaxRetries()).isEqualTo(3); + + // Assert - new domain was added by customizer + AsyncProps accountsResult = propsDomain.getProps("accounts"); + assertThat(accountsResult.getConnectionProperties().getHost()).isEqualTo("accounts-host"); + assertThat(accountsResult.getMaxRetries()).isEqualTo(10); + } + + @Test + void shouldCustomizeMultipleYamlDefinedDomains() { + // Arrange - simulate YAML with two custom domains + AsyncRabbitPropsDomainProperties yamlProps = new AsyncRabbitPropsDomainProperties(); + AsyncProps pushProps = AsyncProps.builder() + .withDLQRetry(true) + .maxRetries(2) + .listenReplies(false) + .build(); + yamlProps.put("push", pushProps); + + AsyncProps accountsProps = AsyncProps.builder() + .listenReplies(false) + .build(); + RabbitProperties accountsConnProps = new RabbitProperties(); + accountsConnProps.setHost("localhost"); + accountsConnProps.setPort(5673); + accountsConnProps.setUsername("guest"); + accountsConnProps.setPassword("guest"); + accountsProps.setConnectionProperties(accountsConnProps); + yamlProps.put("accounts", accountsProps); + + RabbitProperties defaultRabbitProperties = new RabbitProperties(); + defaultRabbitProperties.setHost("localhost"); + defaultRabbitProperties.setPort(5672); + + // Arrange - customizer overrides connection properties on both domains + RabbitProperties customConnProps = new RabbitProperties(); + customConnProps.setHost("custom-rabbit-host"); + customConnProps.setPort(5671); + customConnProps.setUsername("admin"); + customConnProps.setPassword("secret"); + + AsyncPropsDomain.RabbitPropsCustomizer customizer = domainProperties -> { + AsyncProps push = domainProperties.get("push"); + if (push != null) { + push.setConnectionProperties(customConnProps); + push.setListenReplies(true); + push.setMaxRetries(3); + } + AsyncProps accounts = domainProperties.get("accounts"); + if (accounts != null) { + accounts.setConnectionProperties(customConnProps); + accounts.setListenReplies(true); + accounts.setMaxRetries(3); + } + }; + + AsyncPropsDomain.RabbitSecretFiller secretFiller = (domain, props) -> { + }; + + // Act + AsyncPropsDomain propsDomain = new AsyncPropsDomain( + "ms_sender", defaultRabbitProperties, yamlProps, secretFiller, customizerProviderOf(customizer)); + + // Assert - push domain: customizer values take precedence + AsyncProps pushResult = propsDomain.getProps("push"); + assertThat(pushResult.getConnectionProperties().getHost()).isEqualTo("custom-rabbit-host"); + assertThat(pushResult.getConnectionProperties().getPort()).isEqualTo(5671); + assertThat(pushResult.getListenReplies()).isTrue(); + assertThat(pushResult.getMaxRetries()).isEqualTo(3); + // YAML values preserved for non-customized properties + assertThat(pushResult.getWithDLQRetry()).isTrue(); + + // Assert - accounts domain: customizer values take precedence + AsyncProps accountsResult = propsDomain.getProps("accounts"); + assertThat(accountsResult.getConnectionProperties().getHost()).isEqualTo("custom-rabbit-host"); + assertThat(accountsResult.getConnectionProperties().getPort()).isEqualTo(5671); + assertThat(accountsResult.getListenReplies()).isTrue(); + assertThat(accountsResult.getMaxRetries()).isEqualTo(3); + + // Assert - defaultDomainName is set to one of the configured domains + assertThat(propsDomain.getDefaultDomainName()).isIn("push", "accounts"); + + // Assert - both domains have the app name set + assertThat(pushResult.getAppName()).isEqualTo("ms_sender"); + assertThat(accountsResult.getAppName()).isEqualTo("ms_sender"); + } + + @Test + void shouldWorkWithFourParamConstructor() { + // Arrange - backward compatibility + AsyncRabbitPropsDomainProperties yamlProps = new AsyncRabbitPropsDomainProperties(); + AsyncProps appProps = AsyncProps.builder() + .maxRetries(7) + .listenReplies(true) + .build(); + yamlProps.put(DEFAULT_DOMAIN, appProps); + + RabbitProperties defaultRabbitProperties = new RabbitProperties(); + + AsyncPropsDomain.RabbitSecretFiller secretFiller = (domain, props) -> { + }; + + // Act - uses 4-param constructor (no customizer) + AsyncPropsDomain propsDomain = new AsyncPropsDomain( + "test-app", defaultRabbitProperties, yamlProps, secretFiller); + + // Assert + AsyncProps result = propsDomain.getProps(DEFAULT_DOMAIN); + assertThat(result.getMaxRetries()).isEqualTo(7); + } +}