From 88522d6ef7c1881c8a67f4924f405ee067856fb2 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Thu, 5 Dec 2024 09:31:06 +0100 Subject: [PATCH 01/58] Minor Quickstart refactoring --- manual/src/main/asciidoc/5-min-quickstart.adoc | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/manual/src/main/asciidoc/5-min-quickstart.adoc b/manual/src/main/asciidoc/5-min-quickstart.adoc index e05ee75e7..a25a45dd4 100644 --- a/manual/src/main/asciidoc/5-min-quickstart.adoc +++ b/manual/src/main/asciidoc/5-min-quickstart.adoc @@ -51,9 +51,14 @@ Try accessing https://localhost:9443/cxs/cluster with username/password: karaf/k 1) Install JDK 11 (https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) and make sure you set the JAVA_HOME variable https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/ (see our <> guide for more information on JDK compatibility) -2) Download ElasticSearch here : https://www.elastic.co/downloads/past-releases/elasticsearch-7-17-5 (please make sure you use the proper version : 7.17.5) +2) Download ElasticSearch here : https://www.elastic.co/downloads/past-releases/elasticsearch-7-17-5 (please *make sure* you use the proper version : 7.17.5) -3) Uncompress it and change the `config/elasticsearch.yml` to include the following config : cluster.name: contextElasticSearch +3) Uncompress it and change the `config/elasticsearch.yml` to include the following config : + +[source,yaml] +---- +cluster.name: contextElasticSearch +---- 4) Launch ElasticSearch using : `bin/elasticsearch` From d64bb8c1c074ad294e555ad9b9703799f8721a1d Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Thu, 5 Dec 2024 09:52:53 +0100 Subject: [PATCH 02/58] Merge changes from master branch --- .github/workflows/codeql-analysis-java.yml | 10 +- .../workflows/codeql-analysis-javascript.yml | 2 +- KEYS | 66 +- .../main/java/org/apache/unomi/api/Item.java | 8 +- .../apache/unomi/api/utils/ParserHelper.java | 16 +- .../unomi/geonames/rest/GeonamesEndPoint.java | 4 +- .../services/GeonamesServiceImpl.java | 20 +- extensions/groovy-actions/karaf-kar/pom.xml | 2 +- .../actions/rest/GroovyActionsEndPoint.java | 6 +- .../actions/GroovyActionDispatcher.java | 6 +- .../GroovyBundleResourceConnector.java | 6 +- .../listener/GroovyActionListener.java | 16 +- .../impl/GroovyActionsServiceImpl.java | 25 +- extensions/healthcheck/README.md | 85 + extensions/healthcheck/pom.xml | 141 ++ .../unomi/healthcheck/HealthCheckConfig.java | 95 ++ .../healthcheck/HealthCheckProvider.java | 14 +- .../healthcheck/HealthCheckResponse.java | 166 ++ .../unomi/healthcheck/HealthCheckService.java | 147 ++ .../provider/ClusterHealthCheckProvider.java | 109 ++ .../ElasticSearchHealthCheckProvider.java | 130 ++ .../PersistenceHealthCheckProvider.java | 91 + .../UnomiBundlesHealthCheckProvider.java | 88 + .../servlet/HealthCheckAuthorization.java | 51 + .../servlet/HealthCheckHttpContext.java | 117 ++ .../servlet/HealthCheckServlet.java | 79 + .../unomi/healthcheck/util/CachedValue.java | 48 + .../org.apache.unomi.healthcheck.cfg | 31 + .../unomi/schema/rest/JsonSchemaEndPoint.java | 4 +- .../unomi/schema/impl/SchemaServiceImpl.java | 42 +- .../unomi/schema/keyword/ScopeValidator.java | 6 +- .../schema/listener/JsonSchemaListener.java | 14 +- extensions/lists-extension/pom.xml | 2 +- .../lists/rest/UserListServiceEndPoint.java | 4 +- extensions/log4j-extension/pom.xml | 105 ++ ...SafeExtendedThrowablePatternConverter.java | 206 +++ extensions/pom.xml | 2 + extensions/privacy-extension/pom.xml | 2 +- .../privacy/internal/PrivacyServiceImpl.java | 5 +- .../core/context/RouterCamelContext.java | 21 +- .../event/UpdateCamelRouteEventHandler.java | 12 +- .../ExportRouteCompletionProcessor.java | 6 +- .../ImportConfigByFileNameProcessor.java | 6 +- .../ImportRouteCompletionProcessor.java | 4 +- .../core/processor/LineBuildProcessor.java | 7 - .../processor/LineSplitFailureHandler.java | 8 +- .../core/processor/LineSplitProcessor.java | 23 +- .../ProfileExportCollectRouteBuilder.java | 11 +- .../ProfileExportProducerRouteBuilder.java | 4 +- .../ProfileImportFromSourceRouteBuilder.java | 6 +- .../ProfileImportOneShotRouteBuilder.java | 4 +- .../ProfileImportToUnomiRouteBuilder.java | 4 +- extensions/router/router-rest/pom.xml | 2 +- .../ExportConfigurationServiceEndPoint.java | 4 +- .../ImportConfigurationServiceEndPoint.java | 6 +- .../ExportConfigurationServiceImpl.java | 4 +- .../ImportConfigurationServiceImpl.java | 4 +- .../services/ProfileExportServiceImpl.java | 4 +- .../services/ProfileImportServiceImpl.java | 20 +- .../salesforce-connector/actions/pom.xml | 2 +- .../salesforce-connector/karaf-kar/pom.xml | 2 +- .../services/internal/SFDCServiceImpl.java | 245 ++- .../actions/WeatherUpdateAction.java | 37 +- extensions/web-tracker/wab/yarn.lock | 444 ++--- .../DeleteProfilePropertiesCommand.java | 8 +- .../commands/ProcessEventsCommand.java | 14 +- .../graphql/fetchers/BaseDataFetcher.java | 4 +- .../graphql/schema/GraphQLSchemaProvider.java | 11 +- .../graphql/schema/json/JSONObjectType.java | 4 +- .../graphql/schema/json/JSONTypeFactory.java | 4 +- .../websocket/ExecutionResultSubscriber.java | 10 +- .../websocket/SubscriptionWebSocket.java | 10 +- .../META-INF/cxs/rules/updateConsent.json | 20 - .../META-INF/cxs/rules/updateLists.json | 24 - graphql/graphql-playground/yarn.lock | 1476 ++++++++--------- .../java/org/apache/unomi/itests/AllITs.java | 3 +- .../apache/unomi/itests/HealthCheckIT.java | 214 +++ .../unomi/itests/LoggerConfigurationIT.java | 98 ++ .../java/org/apache/unomi/itests/PatchIT.java | 2 +- .../apache/unomi/itests/ProfileExportIT.java | 4 +- .../unomi/itests/ProfileImportBasicIT.java | 6 +- .../unomi/itests/ProfileImportSurfersIT.java | 8 +- .../org.apache.unomi.healthcheck.cfg | 31 + .../unomi/lifecycle/BundleWatcherImpl.java | 28 +- manual/pom.xml | 2 +- manual/src/main/asciidoc/configuration.adoc | 123 +- .../unomi/metrics/commands/ViewCommand.java | 4 +- .../resources/etc/org.ops4j.pax.logging.cfg | 2 +- .../src/main/resources/etc/users.properties | 1 + .../unomi/persistence/spi/PropertyHelper.java | 13 +- plugins/baseplugin/pom.xml | 4 + .../actions/CopyPropertiesAction.java | 12 +- .../EvaluateVisitPropertiesAction.java | 10 +- .../actions/IncrementPropertyAction.java | 14 +- .../actions/ModifyConsentAction.java | 10 +- .../baseplugin/actions/SetPropertyAction.java | 4 +- .../actions/UpdatePropertiesAction.java | 4 +- .../BooleanConditionESQueryBuilder.java | 14 +- .../HardcodedPropertyAccessorRegistry.java | 4 - .../org/apache/unomi/kafka/KafkaInjector.java | 3 - .../plugins/mail/actions/SendMailAction.java | 6 +- .../actions/SetRemoteHostInfoAction.java | 40 +- .../UserAgentDetectorServiceImpl.java | 12 +- .../actions/UserAgentDetectorTest.java | 15 +- .../ContextRequestDeserializer.java | 4 - .../EventsCollectorRequestDeserializer.java | 4 - .../endpoints/CampaignsServiceEndPoint.java | 4 +- .../endpoints/ClusterServiceEndPoint.java | 10 +- .../rest/endpoints/ContextJsonEndpoint.java | 10 +- .../endpoints/DefinitionsServiceEndPoint.java | 4 - .../rest/endpoints/QueryServiceEndPoint.java | 4 +- .../rest/endpoints/ScopeServiceEndPoint.java | 4 +- .../endpoints/ScoringServiceEndPoint.java | 4 +- .../endpoints/UserListServiceEndPoint.java | 4 +- .../InvalidRequestExceptionMapper.java | 6 +- .../exception/RuntimeExceptionMapper.java | 6 +- .../exception/ValidationExceptionMapper.java | 10 +- .../apache/unomi/rest/server/RestServer.java | 25 +- .../rest/service/impl/LocalizationHelper.java | 4 - .../org/apache/unomi/utils/HttpUtils.java | 4 +- samples/login-integration/pom.xml | 2 +- .../main/webapp/javascript/login-example.js | 6 +- samples/trainingplugin/pom.xml | 2 +- samples/tweet-button-plugin/pom.xml | 2 +- .../src/main/webapp/index.html | 9 +- .../unomi/scripting/ExpressionFilter.java | 16 +- .../internal/ExpressionFilterFactoryImpl.java | 8 +- .../impl/ActionExecutorDispatcherImpl.java | 10 +- .../impl/cluster/ClusterServiceImpl.java | 25 +- .../ClusterSystemStatisticsEventHandler.java | 10 +- .../ConfigSharingServiceImpl.java | 16 +- .../definitions/DefinitionsServiceImpl.java | 38 +- .../services/impl/goals/GoalsServiceImpl.java | 22 +- .../impl/lists/UserListServiceImpl.java | 8 +- .../impl/patches/PatchServiceImpl.java | 20 +- .../impl/queries/QueryServiceImpl.java | 17 +- .../impl/scheduler/SchedulerServiceImpl.java | 6 +- tools/pom.xml | 2 +- .../migration/service/MigrationContext.java | 8 +- .../shell/migration/utils/HttpUtils.java | 20 +- .../shell/migration/utils/MigrationUtils.java | 42 +- .../org/apache/unomi/web/ClientServlet.java | 6 +- .../org/apache/unomi/web/ContextServlet.java | 6 +- .../unomi/web/EventsCollectorServlet.java | 6 +- .../web/HttpServletRequestForwardWrapper.java | 4 +- 145 files changed, 3789 insertions(+), 1766 deletions(-) create mode 100644 extensions/healthcheck/README.md create mode 100644 extensions/healthcheck/pom.xml create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java rename tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless => extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckProvider.java (73%) create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckResponse.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ClusterHealthCheckProvider.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/PersistenceHealthCheckProvider.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/UnomiBundlesHealthCheckProvider.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckAuthorization.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckHttpContext.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckServlet.java create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/util/CachedValue.java create mode 100644 extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg create mode 100644 extensions/log4j-extension/pom.xml create mode 100644 extensions/log4j-extension/src/main/java/org/apache/unomi/extensions/log4j/SafeExtendedThrowablePatternConverter.java delete mode 100644 graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json delete mode 100644 graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json create mode 100644 itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java create mode 100644 itests/src/test/java/org/apache/unomi/itests/LoggerConfigurationIT.java create mode 100644 itests/src/test/resources/org.apache.unomi.healthcheck.cfg diff --git a/.github/workflows/codeql-analysis-java.yml b/.github/workflows/codeql-analysis-java.yml index 7e46387bf..546e91b17 100644 --- a/.github/workflows/codeql-analysis-java.yml +++ b/.github/workflows/codeql-analysis-java.yml @@ -26,11 +26,11 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: config-file: ./.github/codeql/codeql-config.yml languages: java @@ -39,9 +39,13 @@ jobs: # Prefix the list here with "+" to use these queries and those in the config file. # queries: ./path/to/local/query, your-org/your-repo/queries@main + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 - run: mvn -U -ntp -e clean install -DskipTests - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 with: upload: false diff --git a/.github/workflows/codeql-analysis-javascript.yml b/.github/workflows/codeql-analysis-javascript.yml index ce6239fd0..94b361d47 100644 --- a/.github/workflows/codeql-analysis-javascript.yml +++ b/.github/workflows/codeql-analysis-javascript.yml @@ -35,7 +35,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/KEYS b/KEYS index c9d064e12..6d17befb8 100644 --- a/KEYS +++ b/KEYS @@ -2,12 +2,12 @@ This file contains the PGP keys of various developers. Users: pgp < KEYS gpg --import KEYS -Developers: +Developers: pgp -kxa and append it to this file. (pgpk -ll && pgpk -xa ) >> this file. (gpg --list-sigs && gpg --armor --export ) >> this file. - + pub 1024D/D3CCC68F 2004-08-17 uid Serge Huber sig 3 D3CCC68F 2015-11-28 Serge Huber @@ -233,4 +233,64 @@ f0pUP/7Kw0MdmMwZnepz2itSa8u6MwOGx14LDUWxnt5q/TIM/52KoL6qYahV92Kg WI6+VR+QVcCnAFM+yvCa5DLXTbKczj2VVVm/6gRERJYW4o/eUSxXgE2kgzLSrcH+ SIFgvTXN5InBSs+XEagL18j7gYxdJ64FxuZkqw8l5TxdNg== =WYQb ------END PGP PUBLIC KEY BLOCK----- \ No newline at end of file +-----END PGP PUBLIC KEY BLOCK----- + +pub rsa4096 2024-09-02 [SC] + 2518A55A61447F846B494C62D0EEBF15121B4740 +uid [ ultime ] Jonathan Sinovassin-naik (CODE SIGNING KEY) +sig 3 D0EEBF15121B4740 2024-09-02 Jonathan Sinovassin-naik (CODE SIGNING KEY) +sub rsa4096 2024-09-02 [E] +sig D0EEBF15121B4740 2024-09-02 Jonathan Sinovassin-naik (CODE SIGNING KEY) + +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=Dslh +-----END PGP PUBLIC KEY BLOCK----- diff --git a/api/src/main/java/org/apache/unomi/api/Item.java b/api/src/main/java/org/apache/unomi/api/Item.java index 2d5ff7134..de283ebe9 100644 --- a/api/src/main/java/org/apache/unomi/api/Item.java +++ b/api/src/main/java/org/apache/unomi/api/Item.java @@ -37,7 +37,7 @@ * defines a built-in scope ({@link Metadata#SYSTEM_SCOPE}) that clients can use to share data across scopes. */ public abstract class Item implements Serializable { - private static final Logger logger = LoggerFactory.getLogger(Item.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(Item.class.getName()); private static final long serialVersionUID = 7446061538573517071L; @@ -53,9 +53,9 @@ public static String getItemType(Class clazz) { itemTypeCache.put(clazz, itemType); return itemType; } catch (NoSuchFieldException e) { - logger.error("Class " + clazz.getName() + " doesn't define a publicly accessible ITEM_TYPE field", e); + LOGGER.error("Class {} doesn't define a publicly accessible ITEM_TYPE field", clazz.getName(), e); } catch (IllegalAccessException e) { - logger.error("Error resolving itemType for class " + clazz.getName(), e); + LOGGER.error("Error resolving itemType for class {}", clazz.getName(), e); } return null; } @@ -69,7 +69,7 @@ public static String getItemType(Class clazz) { public Item() { this.itemType = getItemType(this.getClass()); if (itemType == null) { - logger.error("Item implementations must provide a public String constant named ITEM_TYPE to uniquely identify this Item for the persistence service."); + LOGGER.error("Item implementations must provide a public String constant named ITEM_TYPE to uniquely identify this Item for the persistence service."); } } diff --git a/api/src/main/java/org/apache/unomi/api/utils/ParserHelper.java b/api/src/main/java/org/apache/unomi/api/utils/ParserHelper.java index a79d2d6cf..12043fc3d 100644 --- a/api/src/main/java/org/apache/unomi/api/utils/ParserHelper.java +++ b/api/src/main/java/org/apache/unomi/api/utils/ParserHelper.java @@ -39,7 +39,7 @@ */ public class ParserHelper { - private static final Logger logger = LoggerFactory.getLogger(ParserHelper.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ParserHelper.class); private static final Set unresolvedActionTypes = new HashSet<>(); private static final Set unresolvedConditionTypes = new HashSet<>(); @@ -69,7 +69,7 @@ public interface ValueExtractor { public static boolean resolveConditionType(final DefinitionsService definitionsService, Condition rootCondition, String contextObjectName) { if (rootCondition == null) { - logger.warn("Couldn't resolve null condition for {}", contextObjectName); + LOGGER.warn("Couldn't resolve null condition for {}", contextObjectName); return false; } final List result = new ArrayList(); @@ -85,7 +85,7 @@ public void visit(Condition condition) { result.add(condition.getConditionTypeId()); if (!unresolvedConditionTypes.contains(condition.getConditionTypeId())) { unresolvedConditionTypes.add(condition.getConditionTypeId()); - logger.warn("Couldn't resolve condition type: {} for {}", condition.getConditionTypeId(), contextObjectName); + LOGGER.warn("Couldn't resolve condition type: {} for {}", condition.getConditionTypeId(), contextObjectName); } } } @@ -138,13 +138,13 @@ public static boolean resolveActionTypes(DefinitionsService definitionsService, boolean result = true; if (rule.getActions() == null) { if (!ignoreErrors) { - logger.warn("Rule {}:{} has null actions", rule.getItemId(), rule.getMetadata().getName()); + LOGGER.warn("Rule {}:{} has null actions", rule.getItemId(), rule.getMetadata().getName()); } return false; } if (rule.getActions().isEmpty()) { if (!ignoreErrors) { - logger.warn("Rule {}:{} has empty actions", rule.getItemId(), rule.getMetadata().getName()); + LOGGER.warn("Rule {}:{} has empty actions", rule.getItemId(), rule.getMetadata().getName()); } return false; } @@ -165,7 +165,7 @@ public static boolean resolveActionType(DefinitionsService definitionsService, A action.setActionType(actionType); } else { if (!unresolvedActionTypes.contains(action.getActionTypeId())) { - logger.warn("Couldn't resolve action type : " + action.getActionTypeId()); + LOGGER.warn("Couldn't resolve action type : {}", action.getActionTypeId()); unresolvedActionTypes.add(action.getActionTypeId()); } return false; @@ -203,11 +203,11 @@ public void visit(Condition condition) { if ("eventTypeCondition".equals(condition.getConditionTypeId())) { String eventTypeId = (String) condition.getParameter("eventTypeId"); if (eventTypeId == null) { - logger.warn("Null eventTypeId found!"); + LOGGER.warn("Null eventTypeId found!"); } else { // we must now check the stack to see how many notConditions we have in the parent stack if (conditionTypeStack.contains("notCondition")) { - logger.warn("Found complex negative event type condition, will always evaluate rule"); + LOGGER.warn("Found complex negative event type condition, will always evaluate rule"); eventTypeIds.add("*"); } else { eventTypeIds.add(eventTypeId); diff --git a/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java b/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java index f16e31a54..d17bc53d1 100644 --- a/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java +++ b/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java @@ -46,13 +46,13 @@ @Component(service=GeonamesEndPoint.class,property = "osgi.jaxrs.resource=true") public class GeonamesEndPoint { - private static final Logger logger = LoggerFactory.getLogger(GeonamesEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GeonamesEndPoint.class.getName()); @Reference private GeonamesService geonamesService; public GeonamesEndPoint() { - logger.info("Initializing geonames service endpoint..."); + LOGGER.info("Initializing geonames service endpoint..."); } @WebMethod(exclude = true) diff --git a/extensions/geonames/services/src/main/java/org/apache/unomi/geonames/services/GeonamesServiceImpl.java b/extensions/geonames/services/src/main/java/org/apache/unomi/geonames/services/GeonamesServiceImpl.java index 9d4cd9a2e..a19725035 100644 --- a/extensions/geonames/services/src/main/java/org/apache/unomi/geonames/services/GeonamesServiceImpl.java +++ b/extensions/geonames/services/src/main/java/org/apache/unomi/geonames/services/GeonamesServiceImpl.java @@ -39,7 +39,7 @@ public class GeonamesServiceImpl implements GeonamesService { public static final String GEOCODING_MAX_DISTANCE = "100km"; - private static final Logger logger = LoggerFactory.getLogger(GeonamesServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GeonamesServiceImpl.class.getName()); private DefinitionsService definitionsService; private PersistenceService persistenceService; private SchedulerService schedulerService; @@ -84,16 +84,16 @@ public void importDatabase() { if (forceDbImport) { persistenceService.removeIndex(GeonameEntry.ITEM_TYPE); persistenceService.createIndex(GeonameEntry.ITEM_TYPE); - logger.info("Geonames index removed and recreated"); + LOGGER.info("Geonames index removed and recreated"); } else if (persistenceService.getAllItemsCount(GeonameEntry.ITEM_TYPE) > 0) { return; } } else { - logger.info("Geonames index created"); + LOGGER.info("Geonames index created"); } if (pathToGeonamesDatabase == null) { - logger.info("No geonames DB provided"); + LOGGER.info("No geonames DB provided"); return; } final File f = new File(pathToGeonamesDatabase); @@ -110,7 +110,7 @@ public void run() { private void importGeoNameDatabase(final File f) { Map> typeMappings = persistenceService.getPropertiesMapping(GeonameEntry.ITEM_TYPE); if (typeMappings == null || typeMappings.size() == 0) { - logger.warn("Type mappings for type {} are not yet installed, delaying import until they are ready!", GeonameEntry.ITEM_TYPE); + LOGGER.warn("Type mappings for type {} are not yet installed, delaying import until they are ready!", GeonameEntry.ITEM_TYPE); schedulerService.getSharedScheduleExecutorService().schedule(new TimerTask() { @Override public void run() { @@ -130,7 +130,7 @@ public void run() { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String line; - logger.info("Starting to import geonames database from file {}...", f); + LOGGER.info("Starting to import geonames database from file {}...", f); long charCount = 0; double lastCompletionPourcentage = 0.0; long lastCharCount = 0; @@ -157,20 +157,20 @@ public void run() { double completionPourcentage = 100.0 * charCount / fileSize; if (completionPourcentage - lastCompletionPourcentage > 1.0) { int roundedPourcentage = (int) completionPourcentage; - logger.info("{}% imported from file {}", roundedPourcentage, f); + LOGGER.info("{}% imported from file {}", roundedPourcentage, f); lastCompletionPourcentage = completionPourcentage; } } else { if (charCount - lastCharCount > (100*1024*1024)) { - logger.info("{}MB imported from file {}", charCount / (1024*1024), f); + LOGGER.info("{}MB imported from file {}", charCount / (1024*1024), f); lastCharCount = charCount; } } } long totalTimeMillis = System.currentTimeMillis()-importStartTime; - logger.info("{} characters from Geonames database file {} imported in {}ms. Speed={}MB/s", charCount, f, totalTimeMillis, charCount / (1024*1024) / (totalTimeMillis / 1000)); + LOGGER.info("{} characters from Geonames database file {} imported in {}ms. Speed={}MB/s", charCount, f, totalTimeMillis, charCount / (1024*1024) / (totalTimeMillis / 1000)); } catch (Exception e) { - logger.error(e.getMessage(), e); + LOGGER.error(e.getMessage(), e); } } diff --git a/extensions/groovy-actions/karaf-kar/pom.xml b/extensions/groovy-actions/karaf-kar/pom.xml index 8d71be0a6..20fe1fce2 100644 --- a/extensions/groovy-actions/karaf-kar/pom.xml +++ b/extensions/groovy-actions/karaf-kar/pom.xml @@ -56,4 +56,4 @@ - \ No newline at end of file + diff --git a/extensions/groovy-actions/rest/src/main/java/org/apache/unomi/groovy/actions/rest/GroovyActionsEndPoint.java b/extensions/groovy-actions/rest/src/main/java/org/apache/unomi/groovy/actions/rest/GroovyActionsEndPoint.java index 86cc09228..ae2236c01 100644 --- a/extensions/groovy-actions/rest/src/main/java/org/apache/unomi/groovy/actions/rest/GroovyActionsEndPoint.java +++ b/extensions/groovy-actions/rest/src/main/java/org/apache/unomi/groovy/actions/rest/GroovyActionsEndPoint.java @@ -46,13 +46,13 @@ @Component(service = GroovyActionsEndPoint.class, property = "osgi.jaxrs.resource=true") public class GroovyActionsEndPoint { - private static final Logger logger = LoggerFactory.getLogger(GroovyActionsEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GroovyActionsEndPoint.class.getName()); @Reference private GroovyActionsService groovyActionsService; public GroovyActionsEndPoint() { - logger.info("Initializing groovy actions service endpoint..."); + LOGGER.info("Initializing groovy actions service endpoint..."); } @WebMethod(exclude = true) @@ -75,7 +75,7 @@ public Response save(@Multipart(value = "file") Attachment file) { groovyActionsService .save(file.getContentDisposition().getFilename().replace(".groovy", ""), IOUtils.toString(file.getDataHandler().getInputStream())); } catch (IOException e) { - logger.error("Error while processing groovy file", e); + LOGGER.error("Error while processing groovy file", e); return Response.serverError().build(); } return Response.ok().build(); diff --git a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyActionDispatcher.java b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyActionDispatcher.java index f5276ab37..87ed6108b 100644 --- a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyActionDispatcher.java +++ b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyActionDispatcher.java @@ -37,7 +37,7 @@ @Component(service = ActionDispatcher.class) public class GroovyActionDispatcher implements ActionDispatcher { - private static final Logger logger = LoggerFactory.getLogger(GroovyActionDispatcher.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GroovyActionDispatcher.class.getName()); private static final String GROOVY_PREFIX = "groovy"; @@ -61,7 +61,7 @@ public String getPrefix() { public Integer execute(Action action, Event event, String actionName) { GroovyCodeSource groovyCodeSource = groovyActionsService.getGroovyCodeSource(actionName); if (groovyCodeSource == null) { - logger.warn("Couldn't find a Groovy action with name {}, action will not execute !", actionName); + LOGGER.warn("Couldn't find a Groovy action with name {}, action will not execute !", actionName); } else { GroovyShell groovyShell = groovyActionsService.getGroovyShell(); groovyShell.setVariable("action", action); @@ -75,7 +75,7 @@ public Integer execute(Object... args) throws Exception { } }.runWithTimer(); } catch (Exception e) { - logger.error("Error executing Groovy action with key=" + actionName, e); + LOGGER.error("Error executing Groovy action with key={}", actionName, e); } } return 0; diff --git a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyBundleResourceConnector.java b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyBundleResourceConnector.java index e790d967c..cea5961be 100644 --- a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyBundleResourceConnector.java +++ b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/GroovyBundleResourceConnector.java @@ -35,7 +35,7 @@ */ public class GroovyBundleResourceConnector implements ResourceConnector { - private static final Logger logger = LoggerFactory.getLogger(GroovyBundleResourceConnector.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GroovyBundleResourceConnector.class.getName()); private BundleContext bundleContext; @@ -57,10 +57,10 @@ public URLConnection getResourceConnection(String resourcePath) throws ResourceE File resourceFile = new File(resourcesSourceFolder, resourcePath); if (resourceFile.exists()) { try { - logger.info("Loading file {} from module source !", resourcePath); + LOGGER.info("Loading file {} from module source !", resourcePath); resourceURL = resourceFile.toURI().toURL(); } catch (MalformedURLException e) { - logger.warn("Error loading file "+resourcePath+" from module source code", e); + LOGGER.warn("Error loading file {} from module source code", resourcePath, e); } } } diff --git a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/listener/GroovyActionListener.java b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/listener/GroovyActionListener.java index 1dacf8af4..21778bb0d 100644 --- a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/listener/GroovyActionListener.java +++ b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/listener/GroovyActionListener.java @@ -43,7 +43,7 @@ @Component(service = SynchronousBundleListener.class) public class GroovyActionListener implements SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(GroovyActionListener.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GroovyActionListener.class.getName()); public static final String ENTRIES_LOCATION = "META-INF/cxs/actions"; private GroovyActionsService groovyActionsService; @@ -57,7 +57,7 @@ public void setGroovyActionsService(GroovyActionsService groovyActionsService) { @Activate public void postConstruct(BundleContext bundleContext) { this.bundleContext = bundleContext; - logger.debug("postConstruct {}", bundleContext.getBundle()); + LOGGER.debug("postConstruct {}", bundleContext.getBundle()); loadGroovyActions(bundleContext); for (Bundle bundle : bundleContext.getBundles()) { if (bundle.getBundleContext() != null && bundle.getBundleId() != bundleContext.getBundle().getBundleId()) { @@ -66,14 +66,14 @@ public void postConstruct(BundleContext bundleContext) { } bundleContext.addBundleListener(this); - logger.info("Groovy Action Dispatcher initialized."); + LOGGER.info("Groovy Action Dispatcher initialized."); } @Deactivate public void preDestroy() { processBundleStop(bundleContext); bundleContext.removeBundleListener(this); - logger.info("Groovy Action Dispatcher shutdown."); + LOGGER.info("Groovy Action Dispatcher shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -108,14 +108,14 @@ private void addGroovyAction(URL groovyActionURL) { groovyActionsService.save(FilenameUtils.getName(groovyActionURL.getPath()).replace(".groovy", ""), IOUtils.toString(groovyActionURL.openStream())); } catch (IOException e) { - logger.error("Failed to load the groovy action {}", groovyActionURL.getPath(), e); + LOGGER.error("Failed to load the groovy action {}", groovyActionURL.getPath(), e); } } private void removeGroovyAction(URL groovyActionURL) { String actionName = FilenameUtils.getName(groovyActionURL.getPath()).replace(".groovy", ""); groovyActionsService.remove(actionName); - logger.info("The script {} has been removed.", actionName); + LOGGER.info("The script {} has been removed.", actionName); } private void loadGroovyActions(BundleContext bundleContext) { @@ -125,7 +125,7 @@ private void loadGroovyActions(BundleContext bundleContext) { } while (bundleGroovyActions.hasMoreElements()) { URL groovyActionURL = bundleGroovyActions.nextElement(); - logger.debug("Found Groovy action at {}, loading... ", groovyActionURL.getPath()); + LOGGER.debug("Found Groovy action at {}, loading... ", groovyActionURL.getPath()); addGroovyAction(groovyActionURL); } } @@ -138,7 +138,7 @@ private void unloadGroovyActions(BundleContext bundleContext) { while (bundleGroovyActions.hasMoreElements()) { URL groovyActionURL = bundleGroovyActions.nextElement(); - logger.debug("Found Groovy action at {}, loading... ", groovyActionURL.getPath()); + LOGGER.debug("Found Groovy action at {}, loading... ", groovyActionURL.getPath()); removeGroovyAction(groovyActionURL); } } diff --git a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/services/impl/GroovyActionsServiceImpl.java b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/services/impl/GroovyActionsServiceImpl.java index 7b215c187..bee011cd6 100644 --- a/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/services/impl/GroovyActionsServiceImpl.java +++ b/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/services/impl/GroovyActionsServiceImpl.java @@ -67,17 +67,12 @@ public class GroovyActionsServiceImpl implements GroovyActionsService { } private BundleContext bundleContext; - private GroovyScriptEngine groovyScriptEngine; - private GroovyShell groovyShell; - private Map groovyCodeSourceMap; - private ScheduledFuture scheduledFuture; - private static final Logger logger = LoggerFactory.getLogger(GroovyActionsServiceImpl.class.getName()); - + private static final Logger LOGGER = LoggerFactory.getLogger(GroovyActionsServiceImpl.class.getName()); private static final String BASE_SCRIPT_NAME = "BaseScript"; private DefinitionsService definitionsService; @@ -112,7 +107,7 @@ public GroovyShell getGroovyShell() { @Activate public void start(GroovyActionsServiceConfig config, BundleContext bundleContext) { - logger.debug("postConstruct {}", bundleContext.getBundle()); + LOGGER.debug("postConstruct {}", bundleContext.getBundle()); this.config = config; this.bundleContext = bundleContext; @@ -126,15 +121,15 @@ public void start(GroovyActionsServiceConfig config, BundleContext bundleContext try { loadBaseScript(); } catch (IOException e) { - logger.error("Failed to load base script", e); + LOGGER.error("Failed to load base script", e); } initializeTimers(); - logger.info("Groovy action service initialized."); + LOGGER.info("Groovy action service initialized."); } @Deactivate public void onDestroy() { - logger.debug("onDestroy Method called"); + LOGGER.debug("onDestroy Method called"); if (scheduledFuture != null && !scheduledFuture.isCancelled()) { scheduledFuture.cancel(true); } @@ -156,7 +151,7 @@ private void loadBaseScript() throws IOException { if (groovyBaseScriptURL == null) { return; } - logger.debug("Found Groovy base script at {}, loading... ", groovyBaseScriptURL.getPath()); + LOGGER.debug("Found Groovy base script at {}, loading... ", groovyBaseScriptURL.getPath()); GroovyCodeSource groovyCodeSource = new GroovyCodeSource(IOUtils.toString(groovyBaseScriptURL.openStream()), BASE_SCRIPT_NAME, "/groovy/script"); groovyScriptEngine.getGroovyClassLoader().parseClass(groovyCodeSource, true); } @@ -189,9 +184,9 @@ public void save(String actionName, String groovyScript) { try { saveActionType(groovyShell.parse(groovyCodeSource).getClass().getMethod("execute").getAnnotation(Action.class)); saveScript(actionName, groovyScript); - logger.info("The script {} has been loaded.", actionName); + LOGGER.info("The script {} has been loaded.", actionName); } catch (NoSuchMethodException e) { - logger.error("Failed to save the script {}", actionName, e); + LOGGER.error("Failed to save the script {}", actionName, e); } } @@ -221,7 +216,7 @@ public void remove(String id) { definitionsService.removeActionType( groovyShell.parse(groovyCodeSourceMap.get(id)).getClass().getMethod("execute").getAnnotation(Action.class).id()); } catch (NoSuchMethodException e) { - logger.error("Failed to delete the action type for the id {}", id, e); + LOGGER.error("Failed to delete the action type for the id {}", id, e); } persistenceService.remove(id, GroovyAction.class); } @@ -246,7 +241,7 @@ private GroovyCodeSource buildClassScript(String groovyScript, String actionName private void saveScript(String actionName, String script) { GroovyAction groovyScript = new GroovyAction(actionName, script); persistenceService.save(groovyScript); - logger.info("The script {} has been persisted.", actionName); + LOGGER.info("The script {} has been persisted.", actionName); } private void refreshGroovyActions() { diff --git a/extensions/healthcheck/README.md b/extensions/healthcheck/README.md new file mode 100644 index 000000000..83a560789 --- /dev/null +++ b/extensions/healthcheck/README.md @@ -0,0 +1,85 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF licenses this file to You under the Apache License, Version 2.0 +* (the "License"); you may not use this file except in compliance with +* the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +# Health Check Extension + +The Health Check extension provides a simple health check endpoint that can be used to determine if the server is up and running. +The health check endpoint is available at + +``` +/health/check +``` +and returns a simple JSON response that includes all health check provider responses. + +Basic Http Authentication is enabled by default for the health check endpoint. The user needs to have the role `health` to access the endpoint. Users and roles can be configured in the etc/users.properties file. By default a user health/health is configured. + +The healthcheck is available even if unomi is not started. It gives health information about : + - Karaf (as soon as the karaf container is started) + - Elasticsearch (connection to elasticsearch cluster and its health) + - Unomi (unomi bundles status) + - Persistence (unomi to elasticsearch binding) + - Cluster health (unomi cluster status and nodes information) + +All healthcheck can have a status : + - DOWN (service is not available) + - UP (service is up but does not respond to request (starting or misconfigured)) + - LIVE (service is ready to serve request) + - ERROR (an error occurred during service health check) + +Any subsystem health check have a timeout of 500ms where check is cancelled and will be returned as error. + +Typical response to /health/check when unomi NOT started is : + +```json +[ + { + "name":"karaf", + "status":"LIVE", + "collectingTime":0 + }, + { + "name":"cluster", + "status":"DOWN", + "collectingTime":0 + }, + { + "name":"elasticsearch", + "status":"LIVE", + "collectingTime":6 + }, + { + "name":"persistence", + "status":"DOWN", + "collectingTime":0 + }, + { + "name":"unomi", + "status":"DOWN", + "collectingTime":0 + } +] +``` + +## Configuration + +Configuration is located in the file etc/org.apache.unomi.healthcheck.cfg + +Extension can be disabled by setting the property `enabled` to `false`. An environment variable can be used to set this property : UNOMI_HEALTHCHECK_ENABLED + +By default, all healthcheck providers are included but the list of those included providers can be customized by setting the property `providers` with a comma separated list of provider names. An environment variable can be used to set this property : UNOMI_HEALTHCHECK_PROVIDERS + +The timeout used for each health check can be set by setting the property `timeout` to the desired value in milliseconds. An environment variable can be used to set this property : UNOMI_HEALTHCHECK_TIMEOUT diff --git a/extensions/healthcheck/pom.xml b/extensions/healthcheck/pom.xml new file mode 100644 index 000000000..aa399e370 --- /dev/null +++ b/extensions/healthcheck/pom.xml @@ -0,0 +1,141 @@ + + + + + 4.0.0 + + org.apache.unomi + unomi-extensions + 2.6.0-SNAPSHOT + + + healthcheck + Apache Unomi :: Extensions :: HealthCheck + Apache Unomi HealthCheck extension that provide liveliness information about unomi + bundle + + + + org.apache.unomi + unomi-api + ${project.version} + provided + + + org.apache.unomi + unomi-lifecycle-watcher + ${project.version} + provided + + + org.apache.unomi + unomi-persistence-spi + ${project.version} + provided + + + org.apache.unomi + shell-commands + ${project.version} + provided + + + javax.servlet + javax.servlet-api + provided + + + org.osgi + osgi.cmpn + provided + + + org.apache.httpcomponents + httpclient-osgi + provided + + + org.apache.httpcomponents + httpcore-osgi + provided + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-json-provider + provided + + + org.apache.karaf.jaas + org.apache.karaf.jaas.boot + ${karaf.version} + provided + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + *;scope=compile|runtime + + sun.misc;resolution:=optional, + * + + + org.apache.unomi.healthcheck;version=${project.version}, + org.osgi.service.useradmin;version=1.1.0 + + <_dsannotations> + org.apache.unomi.healthcheck.*, + org.apache.unomi.healthcheck.provider.*, + org.apache.unomi.healthcheck.servlet.*, + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + + src/main/resources/org.apache.unomi.healthcheck.cfg + + cfg + healthcheck + + + + + + + + + diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java new file mode 100644 index 000000000..a36501fda --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck; + +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Modified; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Health check configuration. + */ +@Component(immediate = true, service = HealthCheckConfig.class, configurationPid = {"org.apache.unomi.healthcheck"}) +public class HealthCheckConfig { + + private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckConfig.class.getName()); + + public static final String CONFIG_ES_ADDRESSES = "esAddresses"; + public static final String CONFIG_ES_SSL_ENABLED = "esSSLEnabled"; + public static final String CONFIG_ES_LOGIN = "esLogin"; + public static final String CONFIG_ES_PASSWORD = "esPassword"; + public static final String CONFIG_TRUST_ALL_CERTIFICATES = "httpClient.trustAllCertificates"; + public static final String CONFIG_AUTH_REALM = "authentication.realm"; + public static final String ENABLED = "healthcheck.enabled"; + public static final String PROVIDERS = "healthcheck.providers"; + public static final String TIMEOUT = "healthcheck.timeout"; + + private Map config = new HashMap<>(); + private boolean enabled = true; + private List enabledProviders = new ArrayList<>(); + private int timeout = 400; + + @Activate + @Modified + public void modified(Map config) { + LOGGER.info("Updating healthcheck configuration, config size: {}", config.size()); + this.setConfig(config); + this.setEnabled(config.getOrDefault(ENABLED, "true").equalsIgnoreCase("true")); + this.setEnabledProviders(config.getOrDefault(PROVIDERS, "").isEmpty() ? new ArrayList<>() : List.of(config.get(PROVIDERS).split(","))); + this.setTimeout(Integer.parseInt(config.getOrDefault(TIMEOUT, "400"))); + } + + public String get(String configKey) { + return this.config.get(configKey); + } + + public boolean isEnabled() { + return enabled; + } + + public List getEnabledProviders() { + return enabledProviders; + } + + public int getTimeout() { + return timeout; + } + + public void setConfig(Map config) { + this.config = config; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setEnabledProviders(List enabledProviders) { + this.enabledProviders = enabledProviders; + } + + public void setTimeout(int timeout) { + this.timeout = timeout; + } +} diff --git a/tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckProvider.java similarity index 73% rename from tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless rename to extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckProvider.java index 6e3b6d248..982ea8a5b 100644 --- a/tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckProvider.java @@ -15,8 +15,16 @@ * limitations under the License. */ -if (ctx._source.profile != null) { - if (ctx._source.profile.systemProperties != null && ctx._source.profile.systemProperties.pastEvents != null) { - ctx._source.profile.systemProperties.remove('pastEvents'); +package org.apache.unomi.healthcheck; + +public interface HealthCheckProvider { + + String name(); + + HealthCheckResponse execute(); + + default HealthCheckResponse timeout() { + return new HealthCheckResponse.Builder().name(name()).withData("error.cause", "timeout").error().build(); } + } diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckResponse.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckResponse.java new file mode 100644 index 000000000..1201a60b2 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckResponse.java @@ -0,0 +1,166 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A Health Check response. + */ +public class HealthCheckResponse { + + private final String name; + private final Status status; + private final long collectingTime; + private final Map data; + + protected HealthCheckResponse(String name, Status status, long collectingTime, Map data) { + this.name = name; + this.status = status; + this.collectingTime = collectingTime; + this.data = data; + } + + public String getName() { + return name; + } + + public Status getStatus() { + return status; + } + + public long getCollectingTime() { + return collectingTime; + } + + public Map getData() { + return data; + } + + public static Builder builder() { + return new Builder(); + } + + public static Builder named(String name) { + return new Builder().name(name); + } + + public static HealthCheckResponse up(String name) { + return named(name).up().build(); + } + + public static HealthCheckResponse live(String name) { + return named(name).live().build(); + } + + public static HealthCheckResponse down(String name) { + return named(name).down().build(); + } + + public static HealthCheckResponse error(String name) { + return named(name).error().build(); + } + + @JsonIgnore + public boolean isLive() { + return this.status == Status.LIVE; + } + + @JsonIgnore + public boolean isUp() { + return this.status == Status.UP; + } + + @JsonIgnore + public boolean isDown() { + return this.status == Status.DOWN; + } + + @JsonIgnore + public boolean isError() { + return this.status == Status.ERROR; + } + + public static class Builder { + private final long borntime; + private String name; + private HealthCheckResponse.Status status; + private final Map data; + + public Builder() { + this.borntime = System.currentTimeMillis(); + this.status = Status.DOWN; + this.data = new LinkedHashMap<>(); + } + + public Builder name(String name) { + this.name = name; + return this; + } + + public Builder withData(String key, String value) { + this.data.put(key, value); + return this; + } + + public Builder withData(String key, long value) { + this.data.put(key, value); + return this; + } + + public Builder withData(String key, boolean value) { + this.data.put(key, value); + return this; + } + + public Builder up() { + this.status = Status.UP; + return this; + } + + public Builder live() { + this.status = Status.LIVE; + return this; + } + + public Builder down() { + this.status = Status.DOWN; + return this; + } + + public Builder error() { + this.status = Status.ERROR; + return this; + } + + public HealthCheckResponse build() { + return new HealthCheckResponse(this.name, this.status, (System.currentTimeMillis() - borntime), this.data.isEmpty() ? null : this.data); + } + } + + public enum Status { + DOWN, //Not available + UP, //Running or starting + LIVE, //Ready to serve requests + ERROR //Errors during check + } + +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java new file mode 100644 index 000000000..54a288063 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck; + +import org.apache.unomi.healthcheck.servlet.HealthCheckHttpContext; +import org.apache.unomi.healthcheck.servlet.HealthCheckServlet; +import org.osgi.service.component.annotations.*; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.NamespaceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import java.util.*; +import java.util.concurrent.*; +import java.util.stream.Collectors; + +import static org.apache.unomi.healthcheck.HealthCheckConfig.CONFIG_AUTH_REALM; + +/** + * Health check service that aggregates health checks from multiple providers and ensure asynchronous execution. The service is + * aware of any configuration changes. + */ +@Component (service = HealthCheckService.class, immediate = true) +public class HealthCheckService { + + private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckService.class.getName()); + + private final List providers = new ArrayList<>(); + private ExecutorService executor; + private boolean busy = false; + private boolean registered = false; + + @Reference + protected HttpService httpService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY, updated = "updated") + private HealthCheckConfig config; + + public HealthCheckService() { + LOGGER.info("Building healthcheck service..."); + } + + public void setConfig(HealthCheckConfig config) { + this.config = config; + } + + @Activate + public void activate() throws ServletException, NamespaceException { + if (config.isEnabled()) { + LOGGER.info("Activating healthcheck service..."); + executor = Executors.newSingleThreadExecutor(); + httpService.registerServlet("/health/check", new HealthCheckServlet(this), null, + new HealthCheckHttpContext(config.get(CONFIG_AUTH_REALM))); + this.registered = true; + } else { + LOGGER.info("Healthcheck service is disabled"); + } + } + + public void updated() throws ServletException, NamespaceException { + if (config.isEnabled()) { + LOGGER.info("Updating healthcheck service..."); + if (registered) { + httpService.unregister("/health/check"); + registered = false; + } + httpService.registerServlet("/health/check", new HealthCheckServlet(this), null, + new HealthCheckHttpContext(config.get(CONFIG_AUTH_REALM))); + registered = true; + } else { + LOGGER.info("Healthcheck service is disabled"); + } + } + + @Deactivate + public void deactivate() { + LOGGER.info("Deactivating healthcheck service..."); + if (registered) { + httpService.unregister("/health/check"); + registered = false; + } + if (executor != null) { + executor.shutdown(); + } + } + + @Reference(service = HealthCheckProvider.class, cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, unbind = "unbind") + protected void bind(HealthCheckProvider provider) { + LOGGER.info("Binding provider {}", provider.name()); + providers.add(provider); + } + + protected void unbind(HealthCheckProvider provider) { + LOGGER.info("Unbinding provider {}", provider.name()); + providers.remove(provider); + } + + public List check() throws RejectedExecutionException { + if (config.isEnabled()) { + LOGGER.debug("Health check called"); + if (busy) { + throw new RejectedExecutionException("Health check already in progress"); + } else { + try { + busy = true; + List health = new ArrayList<>(); + health.add(HealthCheckResponse.live("karaf")); + for (HealthCheckProvider provider : providers.stream().filter(p -> config.getEnabledProviders().contains(p.name())).collect(Collectors.toList())) { + Future future = executor.submit(provider::execute); + try { + HealthCheckResponse response = future.get(config.getTimeout(), TimeUnit.MILLISECONDS); + health.add(response); + } catch (TimeoutException e) { + future.cancel(true); + health.add(provider.timeout()); + } catch (Exception e) { + LOGGER.error("Error while executing health check", e); + } + } + return health; + } finally { + busy = false; + } + } + } else { + LOGGER.info("Healthcheck service is disabled"); + return Collections.emptyList(); + } + } + +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ClusterHealthCheckProvider.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ClusterHealthCheckProvider.java new file mode 100644 index 000000000..26e3628a8 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ClusterHealthCheckProvider.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.provider; + +import org.apache.unomi.api.ClusterNode; +import org.apache.unomi.api.services.ClusterService; +import org.apache.unomi.healthcheck.HealthCheckResponse; +import org.apache.unomi.healthcheck.HealthCheckProvider; +import org.apache.unomi.healthcheck.util.CachedValue; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.List; + +/** + * A Health Check that checks the status of the Unomi cluster service. + */ +@Component(service = HealthCheckProvider.class, immediate = true) +public class ClusterHealthCheckProvider implements HealthCheckProvider { + + public static final String NAME = "cluster"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ClusterHealthCheckProvider.class.getName()); + private final CachedValue cache = new CachedValue<>(10, java.util.concurrent.TimeUnit.SECONDS); + + @Reference(service = ClusterService.class, cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, bind = "bind", unbind = "unbind") + private volatile ClusterService service; + + public ClusterHealthCheckProvider() { + LOGGER.info("Building cluster health provider service..."); + } + + public void bind(ClusterService service) { + this.service = service; + } + + public void unbind(ClusterService service) { + this.service = null; + } + + @Override public String name() { + return NAME; + } + + @Override public HealthCheckResponse execute() { + LOGGER.debug("Health check cluster"); + if (cache.isStaled() || cache.getValue().isDown() || cache.getValue().isError()) { + cache.setValue(refresh()); + } + return cache.getValue(); + } + + private HealthCheckResponse refresh() { + LOGGER.debug("Refresh"); + HealthCheckResponse.Builder builder = new HealthCheckResponse.Builder(); + builder.name(NAME).down(); + try { + if (service != null) { + builder.up(); + List nodes = service.getClusterNodes(); + builder.withData("cluster.size", nodes.size()); + if (nodes.isEmpty()) { + builder.down(); + } + int idx = 1; + for (ClusterNode node : nodes) { + if (!nodes.isEmpty() || node.isMaster()) { + builder.live(); + } + builder.withData("cluster.node." + idx + ".uptime", node.getUptime()); + builder.withData("cluster.node." + idx + ".cpuload", Double.toString(node.getCpuLoad())); + builder.withData("cluster.node." + idx + ".loadAverage", Arrays.stream(node.getLoadAverage()).mapToObj( + Double::toString).collect(java.util.stream.Collectors.joining(","))); + builder.withData("cluster.node." + idx + ".public", node.getPublicHostAddress()); + builder.withData("cluster.node." + idx + ".internal", node.getInternalHostAddress()); + if (node.isData() || node.isMaster()) { + builder.withData("cluster.node." + idx + ".role", + (node.isMaster() ? "master" : "") + (node.isData() ? "data" : "")); + } + idx++; + } + } + } catch (Exception e) { + builder.error().withData("error", e.getMessage()); + LOGGER.error("Error checking cluster health", e); + } + return builder.build(); + } +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java new file mode 100644 index 000000000..361e68df7 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.provider; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.apache.unomi.healthcheck.HealthCheckConfig; +import org.apache.unomi.healthcheck.HealthCheckResponse; +import org.apache.unomi.healthcheck.HealthCheckProvider; +import org.apache.unomi.healthcheck.util.CachedValue; +import org.apache.unomi.shell.migration.utils.HttpUtils; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * A Health Check that checks the status of the ElasticSearch connectivity according to the provided configuration. + * This connectivity should be LIVE before any try to start Unomi. + */ +@Component(service = HealthCheckProvider.class, immediate = true) +public class ElasticSearchHealthCheckProvider implements HealthCheckProvider { + + public static final String NAME = "elasticsearch"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ElasticSearchHealthCheckProvider.class.getName()); + private final CachedValue cache = new CachedValue<>(10, TimeUnit.SECONDS); + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private HealthCheckConfig config; + + private CloseableHttpClient httpClient; + + public ElasticSearchHealthCheckProvider() { + LOGGER.info("Building elasticsearch health provider service..."); + } + + @Activate + public void activate() { + LOGGER.info("Activating elasticsearch health provider service..."); + CredentialsProvider credentialsProvider = null; + String login = config.get(HealthCheckConfig.CONFIG_ES_LOGIN); + if (StringUtils.isNotEmpty(login)) { + credentialsProvider = new BasicCredentialsProvider(); + UsernamePasswordCredentials credentials + = new UsernamePasswordCredentials(login, config.get(HealthCheckConfig.CONFIG_ES_PASSWORD)); + credentialsProvider.setCredentials(AuthScope.ANY, credentials); + } + try { + httpClient = HttpUtils.initHttpClient( + Boolean.parseBoolean(config.get(HealthCheckConfig.CONFIG_TRUST_ALL_CERTIFICATES)), credentialsProvider); + } catch (IOException e) { + LOGGER.error("Unable to initialize http client", e); + } + } + + public void setConfig(HealthCheckConfig config) { + this.config = config; + } + + @Override public String name() { + return NAME; + } + + @Override public HealthCheckResponse execute() { + LOGGER.debug("Health check elasticsearch"); + if (cache.isStaled() || cache.getValue().isDown() || cache.getValue().isError()) { + cache.setValue(refresh()); + } + return cache.getValue(); + } + + private HealthCheckResponse refresh() { + LOGGER.debug("Refresh"); + HealthCheckResponse.Builder builder = new HealthCheckResponse.Builder(); + builder.name(NAME).down(); + String url = (config.get(HealthCheckConfig.CONFIG_ES_SSL_ENABLED).equals("true") ? "https://" : "http://") + .concat(config.get(HealthCheckConfig.CONFIG_ES_ADDRESSES).split(",")[0].trim()) + .concat("/_cluster/health"); + CloseableHttpResponse response = null; + try { + response = httpClient.execute(new HttpGet(url)); + if (response != null && response.getStatusLine().getStatusCode() == 200) { + builder.up(); + HttpEntity entity = response.getEntity(); + if (entity != null && EntityUtils.toString(entity).contains("\"status\":\"green\"")) { + builder.live(); + //TODO parse and add cluster data + } + } + } catch (IOException e) { + builder.error().withData("error", e.getMessage()); + LOGGER.error("Error while checking elasticsearch health", e); + } finally { + if (response != null) { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + return builder.build(); + } +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/PersistenceHealthCheckProvider.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/PersistenceHealthCheckProvider.java new file mode 100644 index 000000000..b0d2725dc --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/PersistenceHealthCheckProvider.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.provider; + +import org.apache.unomi.api.PropertyType; +import org.apache.unomi.healthcheck.HealthCheckResponse; +import org.apache.unomi.healthcheck.HealthCheckProvider; +import org.apache.unomi.healthcheck.util.CachedValue; +import org.apache.unomi.persistence.spi.PersistenceService; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +/** + * A health check that track the Unomi persistence layer availability. An evolution would be to check the persistence migration status to + * ensure that running instance is aligned with the underlying persistence migration status and structures. + */ +@Component(service = HealthCheckProvider.class, immediate = true) +public class PersistenceHealthCheckProvider implements HealthCheckProvider { + + public static final String NAME = "persistence"; + + private static final Logger LOGGER = LoggerFactory.getLogger(PersistenceHealthCheckProvider.class.getName()); + private final CachedValue cache = new CachedValue<>(5, TimeUnit.MINUTES); + + @Reference(service = PersistenceService.class, cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, bind = "bind", unbind = "unbind") + private volatile PersistenceService service; + + public PersistenceHealthCheckProvider() { + LOGGER.info("Building persistence health provider service..."); + } + + public void bind(PersistenceService service) { + this.service = service; + } + + public void unbind(PersistenceService service) { + this.service = null; + } + + @Override public String name() { + return NAME; + } + + @Override public HealthCheckResponse execute() { + LOGGER.debug("Health check persistence"); + if (cache.isStaled() || cache.getValue().isDown() || cache.getValue().isError()) { + cache.setValue(refresh()); + } + return cache.getValue(); + } + + private HealthCheckResponse refresh() { + LOGGER.debug("Refresh value"); + HealthCheckResponse.Builder builder = new HealthCheckResponse.Builder(); + builder.name(NAME).down(); + try { + if (service != null) { + builder.up(); + //TODO replace by the expected persistence version when migrations steps will be stored in the persistence service + if (!service.query("target", "profiles", null, PropertyType.class).isEmpty()) { + builder.live(); + } + } + } catch (Exception e) { + builder.error().withData("error", e.getMessage()); + LOGGER.error("Error while checking persistence health", e); + } + return builder.build(); + } +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/UnomiBundlesHealthCheckProvider.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/UnomiBundlesHealthCheckProvider.java new file mode 100644 index 000000000..1429330fa --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/UnomiBundlesHealthCheckProvider.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.provider; + +import org.apache.unomi.healthcheck.HealthCheckResponse; +import org.apache.unomi.healthcheck.HealthCheckProvider; +import org.apache.unomi.healthcheck.util.CachedValue; +import org.apache.unomi.lifecycle.BundleWatcher; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.component.annotations.ReferencePolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.TimeUnit; + +/** + * A health check that track the Unomi bundles availability. + */ +@Component(service = HealthCheckProvider.class, immediate = true) +public class UnomiBundlesHealthCheckProvider implements HealthCheckProvider { + + public static final String NAME = "unomi"; + + private static final Logger LOGGER = LoggerFactory.getLogger(UnomiBundlesHealthCheckProvider.class.getName()); + private final CachedValue cache = new CachedValue<>(10, TimeUnit.SECONDS); + + @Reference(service = BundleWatcher.class, cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC, bind = "bind", unbind = "unbind") + private volatile BundleWatcher service; + + public UnomiBundlesHealthCheckProvider() { + LOGGER.info("Building unomi bundles health provider service..."); + } + + public void bind(BundleWatcher service) { + this.service = service; + } + + public void unbind(BundleWatcher service) { + this.service = null; + } + + @Override public String name() { + return NAME; + } + + @Override public HealthCheckResponse execute() { + LOGGER.debug("Health check unomi bundles"); + if (cache.isStaled() || !cache.getValue().isLive()) { + cache.setValue(refresh()); + } + return cache.getValue(); + } + + private HealthCheckResponse refresh() { + LOGGER.debug("Refresh"); + HealthCheckResponse.Builder builder = new HealthCheckResponse.Builder(); + builder.name(NAME).down(); + try { + if (service != null) { + builder.up(); + if (service.isStartupComplete()) { + builder.live(); + } + } + } catch (Exception e) { + builder.error().withData("error", e.getMessage()); + LOGGER.error("Error while checking unomi bundles health", e); + } + return builder.build(); + } +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckAuthorization.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckAuthorization.java new file mode 100644 index 000000000..6a743bd14 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckAuthorization.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.servlet; + +import org.osgi.service.useradmin.Authorization; + +import java.util.Arrays; + +/** + * A simple implementation of the {@link Authorization} interface (usually provided by UserAdmin). + */ +public class HealthCheckAuthorization implements Authorization { + + private final String name; + private final String[] roles; + + public HealthCheckAuthorization(String name, String[] roles) { + this.name = name; + this.roles = roles; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean hasRole(String role) { + return Arrays.asList(roles).contains(role); + } + + @Override + public String[] getRoles() { + return roles; + } +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckHttpContext.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckHttpContext.java new file mode 100644 index 000000000..8e9331a61 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckHttpContext.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.servlet; + +import org.apache.karaf.jaas.boot.principal.RolePrincipal; +import org.apache.karaf.jaas.boot.principal.UserPrincipal; +import org.osgi.service.http.HttpContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.auth.login.LoginContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URL; +import java.util.Base64; + +/** + * A simple implementation of the {@link HttpContext} interface that provides basic authentication for health checks. + */ +public class HealthCheckHttpContext implements HttpContext { + + private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckHttpContext.class.getName()); + + private final String realm; + + public HealthCheckHttpContext(String realm) { + this.realm = realm; + } + + public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res) throws IOException { + if (req.getHeader("Authorization") == null) { + LOGGER.debug("No Authorization header found, sending 401"); + res.addHeader("WWW-Authenticate", "Basic realm=\"" + realm + "\""); + res.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + if (authenticated(req)) { + LOGGER.debug("User authenticated, allowing access"); + return true; + } else { + LOGGER.debug("User not authenticated, sending 401"); + res.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } + } + + protected boolean authenticated(HttpServletRequest request) { + request.setAttribute(AUTHENTICATION_TYPE, HttpServletRequest.BASIC_AUTH); + + String authzHeader = request.getHeader("Authorization"); + String usernameAndPassword = new String(Base64.getDecoder().decode(authzHeader.substring(6).getBytes())); + String[] parts = usernameAndPassword.split(":"); + + LOGGER.debug("Authenticating user {}", parts[0]); + try { + //We use JAAS for authentication and authorization but it could be done using UserAdmin OSGI service + LOGGER.debug("Creating Login Context for realm {}", realm); + LoginContext loginContext = new LoginContext(realm, callbacks -> { + for (Callback callback : callbacks) { + if (callback instanceof NameCallback) { + ((NameCallback) callback).setName(parts[0]); + } else if (callback instanceof PasswordCallback) { + ((PasswordCallback) callback).setPassword(parts[1].toCharArray()); + } else { + throw new UnsupportedCallbackException(callback); + } + } + }); + LOGGER.debug("Login Context created"); + loginContext.login(); + LOGGER.debug("Login Context called"); + if (loginContext.getSubject() != null) { + LOGGER.debug("User authenticated, subject is not null {}", loginContext.getSubject()); + String username = loginContext.getSubject().getPrincipals(UserPrincipal.class).stream() + .map(UserPrincipal::getName).findFirst().orElse("unknown"); + String[] roles = loginContext.getSubject().getPrincipals(RolePrincipal.class).stream().map(RolePrincipal::getName) + .toArray(String[]::new); + LOGGER.debug("User {} authenticated with roles {}", username, roles); + request.setAttribute(REMOTE_USER, username); + request.setAttribute(AUTHORIZATION, new HealthCheckAuthorization(username, roles)); + return true; + } + } catch (Exception e) { + LOGGER.error("Error while authenticating user", e); + } + return false; + } + + public URL getResource(String s) { + return null; + } + + public String getMimeType(String s) { + return null; + } + +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckServlet.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckServlet.java new file mode 100644 index 000000000..e687b6c37 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/servlet/HealthCheckServlet.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.servlet; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.unomi.healthcheck.HealthCheckResponse; +import org.apache.unomi.healthcheck.HealthCheckService; +import org.osgi.service.http.HttpContext; +import org.osgi.service.useradmin.Authorization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Comparator; +import java.util.List; + +/** + * A simple servlet that provides a health check endpoint. + */ +public class HealthCheckServlet extends HttpServlet { + + private static final Logger LOGGER = LoggerFactory.getLogger(HealthCheckServlet.class.getName()); + + private final HealthCheckService service; + private final ObjectMapper mapper; + + public HealthCheckServlet(HealthCheckService service) { + LOGGER.info("Building healthcheck servlet..."); + this.service = service; + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + } + + @Override + public void init(ServletConfig config) throws ServletException { + LOGGER.info("Initializing healthcheck servlet..."); + super.init(config); + } + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + if (request.getAttribute(HttpContext.AUTHORIZATION) == null || + !((Authorization)request.getAttribute(HttpContext.AUTHORIZATION)).hasRole("health")) { + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + List checks = service.check(); + checks.sort(Comparator.comparing(HealthCheckResponse::getName)); + response.getWriter().println(mapper.writeValueAsString(checks)); + response.setContentType("application/json"); + response.setHeader("Cache-Control", "no-cache"); + if (checks.stream().allMatch(HealthCheckResponse::isLive)) { + response.setStatus(HttpServletResponse.SC_OK); + } else { + response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); + } + } +} diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/util/CachedValue.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/util/CachedValue.java new file mode 100644 index 000000000..188e852e6 --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/util/CachedValue.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.util; + +import java.util.concurrent.TimeUnit; + +/** + * A Health Check response. + */ +public class CachedValue { + + private long ttl; + private long date; + private T value; + + public CachedValue(long value, TimeUnit unit) { + this.ttl = TimeUnit.MILLISECONDS.convert(value, unit); + } + + public boolean isStaled() { + return System.currentTimeMillis() - date > ttl; + } + + public synchronized void setValue(T value) { + this.date = System.currentTimeMillis(); + this.value = value; + } + + public synchronized T getValue() { + return isStaled()?null:value; + } + +} diff --git a/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg b/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg new file mode 100644 index 000000000..4cbe767eb --- /dev/null +++ b/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Elasticsearch configuration +esAddresses = ${org.apache.unomi.elasticsearch.addresses:-localhost:9200} +esSSLEnabled = ${org.apache.unomi.elasticsearch.sslEnable:-false} +esLogin = ${org.apache.unomi.elasticsearch.username:-} +esPassword = ${org.apache.unomi.elasticsearch.password:-} +httpClient.trustAllCertificates = ${org.apache.unomi.elasticsearch.sslTrustAllCertificates:-false} + +# Security configuration +authentication.realm = ${org.apache.unomi.security.realm:-karaf} + +# Health check configuration +healthcheck.enabled = ${org.apache.unomi.healthcheck.enabled:-false} +healthcheck.providers = ${org.apache.unomi.healthcheck.providers:-cluster,elasticsearch,unomi,persistence} +healthcheck.timeout = ${org.apache.unomi.healthcheck.timeout:-400} diff --git a/extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java b/extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java index 4064edf20..5f9caabf0 100644 --- a/extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java +++ b/extensions/json-schema/rest/src/main/java/org/apache/unomi/schema/rest/JsonSchemaEndPoint.java @@ -45,13 +45,13 @@ @Component(service = JsonSchemaEndPoint.class, property = "osgi.jaxrs.resource=true") public class JsonSchemaEndPoint { - private static final Logger logger = LoggerFactory.getLogger(JsonSchemaEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(JsonSchemaEndPoint.class.getName()); @Reference private SchemaService schemaService; public JsonSchemaEndPoint() { - logger.info("Initializing JSON schema endpoint..."); + LOGGER.info("Initializing JSON schema endpoint..."); } @WebMethod(exclude = true) diff --git a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java index e30231c92..da7efeac2 100644 --- a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java +++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/impl/SchemaServiceImpl.java @@ -31,8 +31,8 @@ import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.schema.api.JsonSchemaWrapper; import org.apache.unomi.schema.api.SchemaService; -import org.apache.unomi.schema.api.ValidationException; import org.apache.unomi.schema.api.ValidationError; +import org.apache.unomi.schema.api.ValidationException; import org.apache.unomi.schema.keyword.ScopeKeyword; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +40,6 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; -import java.text.MessageFormat; import java.util.*; import java.util.concurrent.*; import java.util.stream.Collectors; @@ -49,7 +48,7 @@ public class SchemaServiceImpl implements SchemaService { private static final String URI = "https://json-schema.org/draft/2019-09/schema"; - private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SchemaServiceImpl.class.getName()); private static final String TARGET_EVENTS = "events"; private static final String GENERIC_ERROR_KEY = "error"; @@ -86,13 +85,11 @@ public boolean isValid(String data, String schemaId) { try { JsonNode jsonNode = parseData(data); JsonSchema jsonSchema = getJsonSchema(schemaId); - return validate(jsonNode, jsonSchema).size() == 0; + return validate(jsonNode, jsonSchema).isEmpty(); } catch (ValidationException e) { - if (logger.isDebugEnabled()) { - logger.debug(e.getMessage(), e); - } - return false; + LOGGER.warn("{}", e.getMessage(), e); } + return false; } @Override @@ -103,11 +100,9 @@ public boolean isEventValid(String event, String eventType) { @Override public boolean isEventValid(String event) { try { - return validateEvent(event).size() == 0; + return validateEvent(event).isEmpty(); } catch (ValidationException e) { - if (logger.isDebugEnabled()) { - logger.debug(e.getMessage(), e); - } + LOGGER.warn("{}", e.getMessage(), e); } return false; } @@ -139,7 +134,8 @@ public Map> validateEvents(String events) throws Va } } } catch (ValidationException e) { - logger.debug("Validation error : {}", e.getMessage()); + LOGGER.warn("An error occurred during the validation of your event - switch to DEBUG log level for more information."); + LOGGER.debug("Validation error : {}", e.getMessage()); Set errors = buildCustomErrorMessage(e.getMessage()); String eventTypeOrErrorKey = eventType != null ? eventType : GENERIC_ERROR_KEY; if (errorsPerEventType.containsKey(eventTypeOrErrorKey)) { @@ -230,10 +226,10 @@ private Set validate(JsonNode jsonNode, JsonSchema jsonSchema) try { Set validationMessages = jsonSchema.validate(jsonNode); - if (logger.isDebugEnabled() && validationMessages.size() > 0) { - logger.debug("Schema validation found {} errors while validating against schema: {}", validationMessages.size(), jsonSchema.getCurrentUri()); + if (!validationMessages.isEmpty()) { + LOGGER.warn("Schema validation found {} errors while validating against schema: {}", validationMessages.size(), jsonSchema.getCurrentUri()); for (ValidationMessage validationMessage : validationMessages) { - logger.debug("Validation error: {}", validationMessage); + LOGGER.warn("Validation error: {}", validationMessage); } } @@ -342,7 +338,7 @@ private void initExtensions(Map schemas) { } extensionsReloaded.get(extendedSchemaId).add(extension.getItemId()); } else { - logger.warn("A schema cannot extends himself, please fix your schema definition for schema: {}", extendedSchemaId); + LOGGER.warn("A schema cannot extends himself, please fix your schema definition for schema: {}", extendedSchemaId); } } @@ -360,7 +356,7 @@ private String generateExtendedSchema(String id, String schema) throws JsonProce } else if (jsonSchema.at("/allOf") instanceof ArrayNode) { allOf = (ArrayNode) jsonSchema.at("/allOf"); } else { - logger.warn("Cannot extends schema allOf property, it should be an Array, please fix your schema definition for schema: {}", id); + LOGGER.warn("Cannot extends schema allOf property, it should be an Array, please fix your schema definition for schema: {}", id); return schema; } @@ -385,7 +381,7 @@ public void run() { try { refreshJSONSchemas(); } catch (Exception e) { - logger.error("Unexpected error while refreshing JSON Schemas", e); + LOGGER.error("Unexpected error while refreshing JSON Schemas", e); } } }; @@ -400,11 +396,11 @@ private void initJsonSchemaFactory() { .build()) .defaultMetaSchemaURI(URI) .uriFetcher(uri -> { - logger.debug("Fetching schema {}", uri); + LOGGER.debug("Fetching schema {}", uri); String schemaId = uri.toString(); JsonSchemaWrapper jsonSchemaWrapper = getSchema(schemaId); if (jsonSchemaWrapper == null) { - logger.error("Couldn't find schema {}", uri); + LOGGER.error("Couldn't find schema {}", uri); return null; } @@ -421,7 +417,7 @@ public void init() { scheduler = Executors.newSingleThreadScheduledExecutor(); initJsonSchemaFactory(); initTimers(); - logger.info("Schema service initialized."); + LOGGER.info("Schema service initialized."); } public void destroy() { @@ -429,7 +425,7 @@ public void destroy() { if (scheduler != null) { scheduler.shutdown(); } - logger.info("Schema service shutdown."); + LOGGER.info("Schema service shutdown."); } public void setPersistenceService(PersistenceService persistenceService) { diff --git a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/keyword/ScopeValidator.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/keyword/ScopeValidator.java index 7e8c9475d..f62e0ca35 100644 --- a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/keyword/ScopeValidator.java +++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/keyword/ScopeValidator.java @@ -27,7 +27,7 @@ import java.util.Set; public class ScopeValidator extends BaseJsonValidator implements JsonValidator { - private static final Logger logger = LoggerFactory.getLogger(ScopeValidator.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ScopeValidator.class); private ScopeService scopeService; @@ -38,9 +38,7 @@ public ScopeValidator(String schemaPath, JsonNode schemaNode, JsonSchema parentS @Override public Set validate(JsonNode node, JsonNode rootNode, String at) { - if (logger.isDebugEnabled()) { - logger.debug("validate( {}, {}, {})", node, rootNode, at); - } + LOGGER.debug("validate( {}, {}, {})", node, rootNode, at); Set errors = new LinkedHashSet<>(); if (scopeService.getScope(node.textValue()) == null) { ValidationMessage.Builder builder = new ValidationMessage.Builder(); diff --git a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java index 6a613292e..7d1261fa8 100644 --- a/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java +++ b/extensions/json-schema/services/src/main/java/org/apache/unomi/schema/listener/JsonSchemaListener.java @@ -36,7 +36,7 @@ */ public class JsonSchemaListener implements SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(JsonSchemaListener.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(JsonSchemaListener.class.getName()); public static final String ENTRIES_LOCATION = "META-INF/cxs/schemas"; private SchemaService schemaService; @@ -51,8 +51,8 @@ public void setBundleContext(BundleContext bundleContext) { } public void postConstruct() { - logger.info("JSON schema listener initializing..."); - logger.debug("postConstruct {}", bundleContext.getBundle()); + LOGGER.info("JSON schema listener initializing..."); + LOGGER.debug("postConstruct {}", bundleContext.getBundle()); loadPredefinedSchemas(bundleContext, true); @@ -64,12 +64,12 @@ public void postConstruct() { schemaService.refreshJSONSchemas(); bundleContext.addBundleListener(this); - logger.info("JSON schema listener initialized."); + LOGGER.info("JSON schema listener initialized."); } public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("JSON schema listener shutdown."); + LOGGER.info("JSON schema listener shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -107,7 +107,7 @@ private void loadPredefinedSchemas(BundleContext bundleContext, boolean load) { while (predefinedSchemas.hasMoreElements()) { URL predefinedSchemaURL = predefinedSchemas.nextElement(); - logger.debug("Found predefined JSON schema at {}, {}... ", predefinedSchemaURL, load ? "loading" : "unloading"); + LOGGER.debug("Found predefined JSON schema at {}, {}... ", predefinedSchemaURL, load ? "loading" : "unloading"); try (InputStream schemaInputStream = predefinedSchemaURL.openStream()) { if (load) { schemaService.loadPredefinedSchema(schemaInputStream); @@ -115,7 +115,7 @@ private void loadPredefinedSchemas(BundleContext bundleContext, boolean load) { schemaService.unloadPredefinedSchema(schemaInputStream); } } catch (Exception e) { - logger.error("Error while {} schema definition {}", load ? "loading" : "unloading", predefinedSchemaURL, e); + LOGGER.error("Error while {} schema definition {}", load ? "loading" : "unloading", predefinedSchemaURL, e); } } } diff --git a/extensions/lists-extension/pom.xml b/extensions/lists-extension/pom.xml index 4bf5fd843..250e15d6c 100644 --- a/extensions/lists-extension/pom.xml +++ b/extensions/lists-extension/pom.xml @@ -35,4 +35,4 @@ Apache Unomi :: Extensions :: Lists List extension for the Apache Unomi Context Server pom - \ No newline at end of file + diff --git a/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java b/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java index 98ca0f119..47f90e750 100644 --- a/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java +++ b/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java @@ -47,13 +47,13 @@ @Component(service=UserListServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class UserListServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(UserListServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(UserListServiceEndPoint.class.getName()); @Reference private UserListService userListService; public UserListServiceEndPoint() { - logger.info("Initializing user list service endpoint..."); + LOGGER.info("Initializing user list service endpoint..."); } @WebMethod(exclude = true) diff --git a/extensions/log4j-extension/pom.xml b/extensions/log4j-extension/pom.xml new file mode 100644 index 000000000..a4231adf0 --- /dev/null +++ b/extensions/log4j-extension/pom.xml @@ -0,0 +1,105 @@ + + + + + + 4.0.0 + + + org.apache.unomi + unomi-extensions + 2.6.0-SNAPSHOT + ../pom.xml + + + log4j-extension + bundle + Apache Unomi :: Extensions :: Log4j Extension + Apache Unomi log4j extensions + + + UTF-8 + 1.8 + 1.8 + + + + + + org.apache.commons + commons-lang3 + 3.15.0 + + + + org.apache.logging.log4j + log4j-core + 2.19.0 + provided + + + + + + + maven-compiler-plugin + + + log4j2-plugin-processor + + compile + + process-classes + + only + + org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor + + + + + + + org.apache.felix + maven-bundle-plugin + true + true + + + org.ops4j.pax.logging.pax-logging-log4j2 + + org.apache.unomi.extensions.log4j + + + org.osgi.framework;version="[1.8,2.0)", + org.apache.logging.log4j*;version="[2,3)";resolution:=optional, + * + + + org.apache.commons.lang3* + + + {maven-resources}, + META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat=target/classes/META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat + + + + + + + diff --git a/extensions/log4j-extension/src/main/java/org/apache/unomi/extensions/log4j/SafeExtendedThrowablePatternConverter.java b/extensions/log4j-extension/src/main/java/org/apache/unomi/extensions/log4j/SafeExtendedThrowablePatternConverter.java new file mode 100644 index 000000000..5a1ec25ac --- /dev/null +++ b/extensions/log4j-extension/src/main/java/org/apache/unomi/extensions/log4j/SafeExtendedThrowablePatternConverter.java @@ -0,0 +1,206 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.extensions.log4j; + +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.plugins.Plugin; +import org.apache.logging.log4j.core.impl.ThrowableProxy; +import org.apache.logging.log4j.core.pattern.ConverterKeys; +import org.apache.logging.log4j.core.pattern.PatternConverter; +import org.apache.logging.log4j.core.pattern.ThrowablePatternConverter; +import org.apache.logging.log4j.util.Strings; + +/** + * Outputs the Throwable portion of the LoggingEvent as a full stack trace + * unless this converter's option is 'short', where it just outputs the first line of the trace, or if + * the number of lines to print is explicitly specified. + *

+ * The extended stack trace will also include the location of where the class was loaded from and the + * version of the jar if available. + *

+ * If the message of the throwable contains a carriage return or line feed character, it gets encoded + * to prevent log injection. + * + * Originally written by Benjamin Papez (Jahia) benjamin.papez@jahia.com + * Contributed to Apache Unomi by Jahia Solutions Group SA + */ +@Plugin( + name = "SafeExtendedThrowablePatternConverter", + category = PatternConverter.CATEGORY, + elementType = "converter", + printObject = true +) +@ConverterKeys({ "sxEx", "sxThrowable", "sxException" }) +public final class SafeExtendedThrowablePatternConverter extends ThrowablePatternConverter { + + private static final String STACKTRACE_LINE_START = "\n\tat"; + private static final String NESTED_STACKTRACE_LINE_START = "\n\t\tat"; + + /** + * Private constructor. + * + * @param config + * @param options options, may be null. + */ + private SafeExtendedThrowablePatternConverter(final Configuration config, final String[] options) { + super("SafeExtendedThrowable", "throwable", options, config); + } + + /** + * Gets an instance of the class. + * + * @param config The current Configuration. + * @param options pattern options, may be null. If first element is "short", + * only the first line of the throwable will be formatted. + * @return instance of class. + */ + public static SafeExtendedThrowablePatternConverter newInstance(final Configuration config, final String[] options) { + return new SafeExtendedThrowablePatternConverter(config, options); + } + + /** + * {@inheritDoc} + */ + @Override + public void format(final LogEvent event, final StringBuilder toAppendTo) { + final ThrowableProxy proxy = event.getThrownProxy(); + final Throwable throwable = event.getThrown(); + if ((throwable != null || proxy != null) && options.anyLines()) { + if (proxy == null) { + super.format(event, toAppendTo); + return; + } + final String suffix = getSuffix(event); + final String extStackTrace = proxy.getExtendedStackTraceAsString(options.getIgnorePackages(), options.getTextRenderer(), suffix); + final int len = toAppendTo.length(); + if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 1))) { + toAppendTo.append(' '); + } + this.appendExtendedStackTrace(toAppendTo, extStackTrace); + } + } + + private void appendExtendedStackTrace(final StringBuilder toAppendTo, final String extStackTrace) { + if (!options.allLines() || !Strings.LINE_SEPARATOR.equals(options.getSeparator())) { + toAppendTo.append(replaceLineSeparator(extStackTrace)); + } else { + int firstMessageWithCRLFIndex = indexOfMessageWithCRLF(extStackTrace); + if (firstMessageWithCRLFIndex != -1) { + toAppendTo.append(replaceLineSeparatorInMessages(extStackTrace, firstMessageWithCRLFIndex)); + } else { + toAppendTo.append(extStackTrace); + } + } + } + + private String replaceLineSeparator(String extStackTrace) { + String[] array = extStackTrace.split(Strings.LINE_SEPARATOR); + return StringUtils.join(array, options.getSeparator(), 0, options.minLines(array.length)); + } + + private int indexOfMessageWithCRLF(String extStackTrace) { + int messageStartIndex = 0; + int stackTraceStartIndex; + do { + stackTraceStartIndex = getNextIndex(extStackTrace.indexOf(STACKTRACE_LINE_START, messageStartIndex), + extStackTrace.indexOf(NESTED_STACKTRACE_LINE_START, messageStartIndex)); + if (stackTraceStartIndex != -1) { + stackTraceStartIndex--; + if (StringUtils.lastIndexOf(extStackTrace, '\r', stackTraceStartIndex) >= messageStartIndex + || StringUtils.lastIndexOf(extStackTrace, '\n', stackTraceStartIndex) >= messageStartIndex) { + return messageStartIndex; + } else if (stackTraceStartIndex != -1) { + messageStartIndex = getNextNestedMessageIndex(extStackTrace, stackTraceStartIndex); + } + } + } while (messageStartIndex != -1 && stackTraceStartIndex != -1); + return -1; + } + + private int getNextNestedMessageIndex(String extStackTrace, int stackTraceStartIndex) { + return getNextIndex(extStackTrace.indexOf("Caused by:", stackTraceStartIndex), + extStackTrace.indexOf("Suppressed:", stackTraceStartIndex)); + } + + private int getNextNestedMessageIndex(StringBuilder extStackTrace, int stackTraceStartIndex) { + return getNextIndex(extStackTrace.indexOf("Caused by:", stackTraceStartIndex), + extStackTrace.indexOf("Suppressed:", stackTraceStartIndex)); + } + + private int getNextIndex(int firstIndex, int secondIndex) { + if (secondIndex == -1) { + return firstIndex; + } else if (firstIndex == -1) { + return secondIndex; + } else { + return Math.min(firstIndex, secondIndex); + } + } + + private String replaceLineSeparatorInMessages(String extStackTrace, int messageWithCRLFIndex) { + final StringBuilder sb = new StringBuilder(extStackTrace); + do { + int beginningOfStackTrace = getNextIndex(sb.indexOf(STACKTRACE_LINE_START, messageWithCRLFIndex), + sb.indexOf(NESTED_STACKTRACE_LINE_START, messageWithCRLFIndex)); + replaceCRLF(sb, messageWithCRLFIndex, beginningOfStackTrace); + messageWithCRLFIndex = indexOfNestedExceptionMessageWithCRLF(sb, beginningOfStackTrace); + } while (messageWithCRLFIndex != -1); + return sb.toString(); + } + + private int indexOfNestedExceptionMessageWithCRLF(StringBuilder extStackTrace, int startIndex) { + int stackTraceStartIndex; + do { + startIndex = getNextNestedMessageIndex(extStackTrace, startIndex); + if (startIndex == -1) { + return startIndex; + } + stackTraceStartIndex = getNextIndex(extStackTrace.indexOf(STACKTRACE_LINE_START, startIndex), + extStackTrace.indexOf(NESTED_STACKTRACE_LINE_START, startIndex)); + if (stackTraceStartIndex != -1) { + stackTraceStartIndex--; + if (StringUtils.lastIndexOf(extStackTrace, '\r', stackTraceStartIndex) >= startIndex + || StringUtils.lastIndexOf(extStackTrace, '\n', stackTraceStartIndex) >= startIndex) { + return startIndex; + } + } + startIndex = stackTraceStartIndex; + } while (startIndex != -1 && stackTraceStartIndex != -1); + return -1; + } + + private void replaceCRLF(StringBuilder toAppendTo, int start, int end) { + for (int i = end - 1; i >= start; i--) { + final char c = toAppendTo.charAt(i); + switch (c) { + case '\r': + toAppendTo.setCharAt(i, '\\'); + toAppendTo.insert(i + 1, 'r'); + break; + case '\n': + toAppendTo.setCharAt(i, '\\'); + toAppendTo.insert(i + 1, 'n'); + break; + default: + break; + } + } + } + +} diff --git a/extensions/pom.xml b/extensions/pom.xml index 131111764..fc756fbd4 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -40,6 +40,8 @@ web-tracker groovy-actions json-schema + log4j-extension + healthcheck diff --git a/extensions/privacy-extension/pom.xml b/extensions/privacy-extension/pom.xml index 36c13f191..deb5955c0 100644 --- a/extensions/privacy-extension/pom.xml +++ b/extensions/privacy-extension/pom.xml @@ -35,4 +35,4 @@ Privacy management extension for the Apache Unomi Context Server pom - \ No newline at end of file + diff --git a/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java b/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java index 5d6abb828..44c24cc91 100644 --- a/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java +++ b/extensions/privacy-extension/services/src/main/java/org/apache/unomi/privacy/internal/PrivacyServiceImpl.java @@ -24,7 +24,6 @@ import org.apache.unomi.lifecycle.BundleWatcher; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; -import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,7 +34,7 @@ */ public class PrivacyServiceImpl implements PrivacyService { - private static final Logger logger = LoggerFactory.getLogger(PrivacyServiceImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(PrivacyServiceImpl.class); private PersistenceService persistenceService; private ProfileService profileService; @@ -43,7 +42,7 @@ public class PrivacyServiceImpl implements PrivacyService { private BundleWatcher bundleWatcher; public PrivacyServiceImpl() { - logger.info("Initializing privacy service..."); + LOGGER.info("Initializing privacy service..."); } public void setPersistenceService(PersistenceService persistenceService) { diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/context/RouterCamelContext.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/context/RouterCamelContext.java index 4ad24e2d1..67219f9c5 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/context/RouterCamelContext.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/context/RouterCamelContext.java @@ -24,7 +24,6 @@ import org.apache.unomi.api.services.ClusterService; import org.apache.unomi.api.services.ConfigSharingService; import org.apache.unomi.api.services.ProfileService; -import org.apache.unomi.api.services.SchedulerService; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.router.api.ExportConfiguration; import org.apache.unomi.router.api.IRouterCamelContext; @@ -56,7 +55,7 @@ */ public class RouterCamelContext implements IRouterCamelContext { - private Logger logger = LoggerFactory.getLogger(RouterCamelContext.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(RouterCamelContext.class.getName()); private CamelContext camelContext; private UnomiStorageProcessor unomiStorageProcessor; private ImportRouteCompletionProcessor importRouteCompletionProcessor; @@ -112,7 +111,7 @@ public void setTracing(boolean tracing) { } public void init() throws Exception { - logger.info("Initialize Camel Context..."); + LOGGER.info("Initialize Camel Context..."); scheduler = Executors.newSingleThreadScheduledExecutor(); configSharingService.setProperty(RouterConstants.IMPORT_ONESHOT_UPLOAD_DIR, uploadDir); @@ -121,7 +120,7 @@ public void init() throws Exception { initCamel(); initTimers(); - logger.info("Camel Context initialized successfully."); + LOGGER.info("Camel Context initialized successfully."); } public void destroy() throws Exception { @@ -132,7 +131,7 @@ public void destroy() throws Exception { //This is to shutdown Camel context //(will stop all routes/components/endpoints etc and clear internal state/cache) this.camelContext.stop(); - logger.info("Camel context for profile import is shutdown."); + LOGGER.info("Camel context for profile import is shutdown."); } private void initTimers() { @@ -151,7 +150,8 @@ public void run() { killExistingRoute(importConfigToRefresh.getKey(), true); } } catch (Exception e) { - logger.error("Unexpected error while refreshing(" + importConfigToRefresh.getValue() + ") camel route: " + importConfigToRefresh.getKey(), e); + LOGGER.error("Unexpected error while refreshing({}) camel route: {}", importConfigToRefresh.getValue(), + importConfigToRefresh.getKey(), e); } } @@ -164,11 +164,12 @@ public void run() { killExistingRoute(exportConfigToRefresh.getKey(), true); } } catch (Exception e) { - logger.error("Unexpected error while refreshing(" + exportConfigToRefresh.getValue() + ") camel route: " + exportConfigToRefresh.getKey(), e); + LOGGER.error("Unexpected error while refreshing({}) camel route: {}", exportConfigToRefresh.getValue(), + exportConfigToRefresh.getKey(), e); } } } catch (Exception e) { - logger.error("Unexpected error while refreshing import/export camel routes", e); + LOGGER.error("Unexpected error while refreshing import/export camel routes", e); } } }; @@ -252,7 +253,7 @@ public void updateProfileImportReaderRoute(String configId, boolean fireEvent) t ImportConfiguration importConfiguration = importConfigurationService.load(configId); if (importConfiguration == null) { - logger.warn("Cannot update profile import reader route, config: {} not found", configId); + LOGGER.warn("Cannot update profile import reader route, config: {} not found", configId); return; } @@ -278,7 +279,7 @@ public void updateProfileExportReaderRoute(String configId, boolean fireEvent) t ExportConfiguration exportConfiguration = exportConfigurationService.load(configId); if (exportConfiguration == null) { - logger.warn("Cannot update profile export reader route, config: {} not found", configId); + LOGGER.warn("Cannot update profile export reader route, config: {} not found", configId); return; } diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/event/UpdateCamelRouteEventHandler.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/event/UpdateCamelRouteEventHandler.java index 91cd09df1..f43f2b629 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/event/UpdateCamelRouteEventHandler.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/event/UpdateCamelRouteEventHandler.java @@ -30,23 +30,23 @@ * @author dgaillard */ public class UpdateCamelRouteEventHandler extends CellarSupport implements EventHandler { - private static final Logger logger = LoggerFactory.getLogger(UpdateCamelRouteEventHandler.class.getName()); + private static final Logger LLOGGER = LoggerFactory.getLogger(UpdateCamelRouteEventHandler.class.getName()); private RouterCamelContext routerCamelContext; @Override public void handle(UpdateCamelRouteEvent event) { - logger.debug("Handle event"); + LLOGGER.debug("Handle event"); if (isAllowed(event.getSourceGroup(), Constants.CATEGORY, event.getId(), EventType.INBOUND)) { - logger.debug("Event is allowed"); + LLOGGER.debug("Event is allowed"); // check if it's not a "local" event if (event.getSourceNode() != null && event.getSourceNode().getId().equalsIgnoreCase(clusterManager.getNode().getId())) { - logger.debug("Cluster event is local (coming from local synchronizer or listener)"); + LLOGGER.debug("Cluster event is local (coming from local synchronizer or listener)"); return; } try { - logger.debug("Event id is {}", event.getId()); + LLOGGER.debug("Event id is {}", event.getId()); if (event.getId().equals(RouterCamelContext.EVENT_ID_REMOVE) && StringUtils.isNotBlank(event.getRouteId())) { routerCamelContext.killExistingRoute(event.getRouteId(), false); } else if ((event.getId().equals(RouterCamelContext.EVENT_ID_IMPORT))) { @@ -55,7 +55,7 @@ public void handle(UpdateCamelRouteEvent event) { routerCamelContext.updateProfileExportReaderRoute(event.getRouteId(), false); } } catch (Exception e) { - logger.error("Error when executing event", e); + LLOGGER.error("Error when executing event", e); } } } diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ExportRouteCompletionProcessor.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ExportRouteCompletionProcessor.java index 414e1c00f..d9794a8de 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ExportRouteCompletionProcessor.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ExportRouteCompletionProcessor.java @@ -34,7 +34,7 @@ */ public class ExportRouteCompletionProcessor implements Processor { - private static final Logger logger = LoggerFactory.getLogger(ExportRouteCompletionProcessor.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ExportRouteCompletionProcessor.class.getName()); private ImportExportConfigurationService exportConfigurationService; private int executionsHistorySize; @@ -43,7 +43,7 @@ public void process(Exchange exchange) throws Exception { // We load the conf from ES because we are going to increment the execution number ExportConfiguration exportConfiguration = exportConfigurationService.load(exchange.getFromRouteId()); if (exportConfiguration == null) { - logger.warn("Unable to complete export, config cannot not found: {}", exchange.getFromRouteId()); + LOGGER.warn("Unable to complete export, config cannot not found: {}", exchange.getFromRouteId()); return; } @@ -56,7 +56,7 @@ public void process(Exchange exchange) throws Exception { exportConfigurationService.save(exportConfiguration, false); - logger.info("Processing route {} completed.", exchange.getFromRouteId()); + LOGGER.info("Processing route {} completed.", exchange.getFromRouteId()); } public void setExportConfigurationService(ImportExportConfigurationService exportConfigurationService) { diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportConfigByFileNameProcessor.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportConfigByFileNameProcessor.java index c40142acd..61c6ed408 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportConfigByFileNameProcessor.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportConfigByFileNameProcessor.java @@ -30,7 +30,7 @@ */ public class ImportConfigByFileNameProcessor implements Processor { - private static final Logger logger = LoggerFactory.getLogger(ImportConfigByFileNameProcessor.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ImportConfigByFileNameProcessor.class.getName()); private ImportExportConfigurationService importConfigurationService; @@ -41,10 +41,10 @@ public void process(Exchange exchange) throws Exception { String importConfigId = fileName.substring(0, fileName.indexOf('.')); ImportConfiguration importConfiguration = importConfigurationService.load(importConfigId); if(importConfiguration != null) { - logger.debug("Set a header with import configuration found for ID : {}", importConfigId); + LOGGER.debug("Set a header with import configuration found for ID : {}", importConfigId); exchange.getIn().setHeader(RouterConstants.HEADER_IMPORT_CONFIG_ONESHOT, importConfiguration); } else { - logger.warn("No import configuration found with ID : {}", importConfigId); + LOGGER.warn("No import configuration found with ID : {}", importConfigId); exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE); } } diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportRouteCompletionProcessor.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportRouteCompletionProcessor.java index 38797e38d..7554ab3fe 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportRouteCompletionProcessor.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/ImportRouteCompletionProcessor.java @@ -30,7 +30,7 @@ */ public class ImportRouteCompletionProcessor implements Processor { - private static final Logger logger = LoggerFactory.getLogger(ImportRouteCompletionProcessor.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ImportRouteCompletionProcessor.class.getName()); private ImportExportConfigurationService importConfigurationService; private int executionsHistorySize; private int execErrReportSize; @@ -86,7 +86,7 @@ public void process(Exchange exchange) throws Exception { importConfiguration.setStatus(RouterConstants.CONFIG_STATUS_COMPLETE_SUCCESS); } importConfigurationService.save(importConfiguration, false); - logger.info("Processing route {} completed. completion date: {}.", exchange.getFromRouteId(), new Date()); + LOGGER.info("Processing route {} completed. completion date: {}.", exchange.getFromRouteId(), new Date()); } public void setImportConfigurationService(ImportExportConfigurationService importConfigurationService) { diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineBuildProcessor.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineBuildProcessor.java index 6dfcf6993..ecfab189f 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineBuildProcessor.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineBuildProcessor.java @@ -19,21 +19,14 @@ import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.unomi.api.Profile; -import org.apache.unomi.api.PropertyType; import org.apache.unomi.router.api.ExportConfiguration; import org.apache.unomi.router.api.services.ProfileExportService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collection; /** * Created by amidani on 28/06/2017. */ public class LineBuildProcessor implements Processor { - private static final Logger logger = LoggerFactory.getLogger(LineBuildProcessor.class); - private ProfileExportService profileExportService; public LineBuildProcessor(ProfileExportService profileExportService) { diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitFailureHandler.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitFailureHandler.java index a7aeb1a57..3cf8ff6b6 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitFailureHandler.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitFailureHandler.java @@ -29,10 +29,10 @@ */ public class LineSplitFailureHandler implements Processor { - private static final Logger logger = LoggerFactory.getLogger(LineSplitFailureHandler.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(LineSplitFailureHandler.class.getName()); public void process(Exchange exchange) throws Exception { - logger.error("Route: {}, Error: {}", exchange.getProperty(Exchange.FAILURE_ROUTE_ID), exchange.getProperty(Exchange.EXCEPTION_CAUGHT)); + LOGGER.error("Route: {}, Error: {}", exchange.getProperty(Exchange.FAILURE_ROUTE_ID), exchange.getProperty(Exchange.EXCEPTION_CAUGHT)); ImportLineError importLineError = new ImportLineError(); if (exchange.getProperty(Exchange.EXCEPTION_CAUGHT) instanceof BadProfileDataFormatException) { importLineError.setErrorCode(((BadProfileDataFormatException) exchange.getProperty(Exchange.EXCEPTION_CAUGHT)).getCause().getMessage()); @@ -47,7 +47,7 @@ public void process(Exchange exchange) throws Exception { } importLineError.setLineContent(exchange.getIn().getBody(String.class)); importLineError.setLineNb(((Integer) exchange.getProperty("CamelSplitIndex") + 1)); - exchange.getIn().setHeader(RouterConstants.HEADER_FAILED_MESSAGE, new Boolean(true)); + exchange.getIn().setHeader(RouterConstants.HEADER_FAILED_MESSAGE, Boolean.TRUE); exchange.getIn().setBody(importLineError, ImportLineError.class); } -} \ No newline at end of file +} diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitProcessor.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitProcessor.java index 94c60e9a5..265fec8f5 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitProcessor.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/processor/LineSplitProcessor.java @@ -24,7 +24,6 @@ import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.apache.unomi.api.PropertyType; -import org.apache.unomi.api.services.ProfileService; import org.apache.unomi.router.api.ImportConfiguration; import org.apache.unomi.router.api.ProfileToImport; import org.apache.unomi.router.api.RouterConstants; @@ -40,7 +39,7 @@ */ public class LineSplitProcessor implements Processor { - private static final Logger logger = LoggerFactory.getLogger(LineSplitProcessor.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(LineSplitProcessor.class.getName()); private Map fieldsMapping; private List propertiesToOverwrite; @@ -82,7 +81,7 @@ public void process(Exchange exchange) throws Exception { .withSeparator(columnSeparator.charAt(0)) .build(); - logger.debug("$$$$ : LineSplitProcessor : BODY : " + (String) exchange.getIn().getBody()); + LOGGER.debug("$$$$ : LineSplitProcessor : BODY : {}", exchange.getIn().getBody()); String[] profileData = rfc4180Parser.parseLine(((String) exchange.getIn().getBody())); @@ -97,24 +96,24 @@ public void process(Exchange exchange) throws Exception { ) { throw new BadProfileDataFormatException("The mapping does not match the number of column : line [" + ((Integer) exchange.getProperty("CamelSplitIndex") + 1) + "]", new Throwable("MAPPING_COLUMN_MATCH")); } - logger.debug("$$$$ : LineSplitProcessor : MAPPING : " + fieldsMapping.keySet()); + LOGGER.debug("$$$$ : LineSplitProcessor : MAPPING : {}", fieldsMapping.keySet()); Map properties = new HashMap<>(); for (String fieldMappingKey : fieldsMapping.keySet()) { PropertyType propertyType = RouterUtils.getPropertyTypeById(profilePropertyTypes, fieldMappingKey); if (fieldMappingKey != null && fieldsMapping.get(fieldMappingKey) != null && profileData != null && profileData[fieldsMapping.get(fieldMappingKey)] != null) { - logger.debug("$$$$ : LineSplitProcessor : PropType value : {}", profileData[fieldsMapping.get(fieldMappingKey)].trim()); + LOGGER.debug("$$$$ : LineSplitProcessor : PropType value : {}", profileData[fieldsMapping.get(fieldMappingKey)].trim()); } else { - logger.debug("$$$$ : LineSplitProcessor : no profileData found for fieldMappingKey=" + fieldMappingKey); + LOGGER.debug("$$$$ : LineSplitProcessor : no profileData found for fieldMappingKey={}", fieldMappingKey); } if (profileData.length > fieldsMapping.get(fieldMappingKey)) { try { if (propertyType == null) { - logger.error("No valid property type found for propertyTypeId=" + fieldMappingKey); + LOGGER.error("No valid property type found for propertyTypeId={}", fieldMappingKey); } else { if (propertyType.getValueTypeId() == null) { - logger.error("No value type id found for property type " + propertyType.getItemId()); + LOGGER.error("No value type id found for property type {}", propertyType.getItemId()); } } if (propertyType.getValueTypeId().equals("string") || propertyType.getValueTypeId().equals("email") || @@ -139,14 +138,14 @@ public void process(Exchange exchange) throws Exception { properties.put(fieldMappingKey, singleValue); } } else if (propertyType.getValueTypeId().equals("boolean")) { - properties.put(fieldMappingKey, new Boolean(profileData[fieldsMapping.get(fieldMappingKey)].trim())); + properties.put(fieldMappingKey, Boolean.valueOf(profileData[fieldsMapping.get(fieldMappingKey)].trim())); } else if (propertyType.getValueTypeId().equals("integer")) { - properties.put(fieldMappingKey, new Integer(profileData[fieldsMapping.get(fieldMappingKey)].trim())); + properties.put(fieldMappingKey, Integer.valueOf(profileData[fieldsMapping.get(fieldMappingKey)].trim())); } else if (propertyType.getValueTypeId().equals("long")) { - properties.put(fieldMappingKey, new Long(profileData[fieldsMapping.get(fieldMappingKey)].trim())); + properties.put(fieldMappingKey, Long.valueOf(profileData[fieldsMapping.get(fieldMappingKey)].trim())); } } catch (Throwable t) { - logger.error("Error converting profileData", t); + LOGGER.error("Error converting profileData", t); if (fieldMappingKey != null && fieldsMapping.get(fieldMappingKey) != null && profileData != null && profileData[fieldsMapping.get(fieldMappingKey)] != null) { throw new BadProfileDataFormatException("Unable to convert '" + profileData[fieldsMapping.get(fieldMappingKey)].trim() + "' to " + propertyType!=null?propertyType.getValueTypeId():"Null propertyType ", new Throwable("DATA_TYPE")); } else { diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportCollectRouteBuilder.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportCollectRouteBuilder.java index e87ec50be..5529c109b 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportCollectRouteBuilder.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportCollectRouteBuilder.java @@ -23,7 +23,6 @@ import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.router.api.ExportConfiguration; import org.apache.unomi.router.api.RouterConstants; -import org.apache.unomi.router.api.services.ImportExportConfigurationService; import org.apache.unomi.router.core.bean.CollectProfileBean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +35,7 @@ */ public class ProfileExportCollectRouteBuilder extends RouterAbstractRouteBuilder { - private static final Logger logger = LoggerFactory.getLogger(ProfileExportCollectRouteBuilder.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileExportCollectRouteBuilder.class); private List exportConfigurationList; private PersistenceService persistenceService; @@ -52,7 +51,7 @@ public void configure() throws Exception { return; } - logger.info("Configure Recurrent Route 'Export :: Collect Data'"); + LOGGER.info("Configure Recurrent Route 'Export :: Collect Data'"); CollectProfileBean collectProfileBean = new CollectProfileBean(); collectProfileBean.setPersistenceService(persistenceService); @@ -83,13 +82,13 @@ public void configure() throws Exception { prDef.to((String) getEndpointURI(RouterConstants.DIRECTION_FROM, RouterConstants.DIRECT_EXPORT_DEPOSIT_BUFFER)); } } else { - logger.error("Endpoint scheme {} is not allowed, route {} will be skipped.", destinationEndpoint.substring(0, destinationEndpoint.indexOf(':')), exportConfiguration.getItemId()); + LOGGER.error("Endpoint scheme {} is not allowed, route {} will be skipped.", destinationEndpoint.substring(0, destinationEndpoint.indexOf(':')), exportConfiguration.getItemId()); } } else { - logger.warn("Mapping is null in export configuration, route {} will be skipped!", exportConfiguration.getItemId()); + LOGGER.warn("Mapping is null in export configuration, route {} will be skipped!", exportConfiguration.getItemId()); } } else { - logger.warn("Export configuration incomplete, route {} will be skipped!", exportConfiguration.getItemId()); + LOGGER.warn("Export configuration incomplete, route {} will be skipped!", exportConfiguration.getItemId()); } } } diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportProducerRouteBuilder.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportProducerRouteBuilder.java index 86288019f..e11378590 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportProducerRouteBuilder.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileExportProducerRouteBuilder.java @@ -33,7 +33,7 @@ */ public class ProfileExportProducerRouteBuilder extends RouterAbstractRouteBuilder { - private static final Logger logger = LoggerFactory.getLogger(ProfileExportProducerRouteBuilder.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileExportProducerRouteBuilder.class); private ExportRouteCompletionProcessor exportRouteCompletionProcessor; @@ -50,7 +50,7 @@ public void setProfileExportService(ProfileExportService profileExportService) { @Override public void configure() throws Exception { - logger.info("Configure Recurrent Route 'Export :: Data Producer'"); + LOGGER.info("Configure Recurrent Route 'Export :: Data Producer'"); RouteDefinition rtDef; if (RouterConstants.CONFIG_TYPE_KAFKA.equals(configType)) { diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportFromSourceRouteBuilder.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportFromSourceRouteBuilder.java index 8c28cae8d..1ebc5c388 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportFromSourceRouteBuilder.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportFromSourceRouteBuilder.java @@ -42,7 +42,7 @@ public class ProfileImportFromSourceRouteBuilder extends RouterAbstractRouteBuilder { - private static final Logger logger = LoggerFactory.getLogger(ProfileImportFromSourceRouteBuilder.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileImportFromSourceRouteBuilder.class.getName()); private List importConfigurationList; private ImportExportConfigurationService importConfigurationService; @@ -54,7 +54,7 @@ public ProfileImportFromSourceRouteBuilder(Map kafkaProps, Strin @Override public void configure() throws Exception { - logger.info("Configure Recurrent Route 'From Source'"); + LOGGER.info("Configure Recurrent Route 'From Source'"); if (importConfigurationList == null) { importConfigurationList = importConfigurationService.getAll(); @@ -126,7 +126,7 @@ public void process(Exchange exchange) throws Exception { prDef.to((String) getEndpointURI(RouterConstants.DIRECTION_FROM, RouterConstants.DIRECT_IMPORT_DEPOSIT_BUFFER)); } } else { - logger.error("Endpoint scheme {} is not allowed, route {} will be skipped.", endpoint.substring(0, endpoint.indexOf(':')), importConfiguration.getItemId()); + LOGGER.error("Endpoint scheme {} is not allowed, route {} will be skipped.", endpoint.substring(0, endpoint.indexOf(':')), importConfiguration.getItemId()); } } } diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportOneShotRouteBuilder.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportOneShotRouteBuilder.java index 5b4d1e253..863437032 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportOneShotRouteBuilder.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportOneShotRouteBuilder.java @@ -34,7 +34,7 @@ */ public class ProfileImportOneShotRouteBuilder extends RouterAbstractRouteBuilder { - private Logger logger = LoggerFactory.getLogger(ProfileImportOneShotRouteBuilder.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileImportOneShotRouteBuilder.class.getName()); private ImportConfigByFileNameProcessor importConfigByFileNameProcessor; private String uploadDir; @@ -45,7 +45,7 @@ public ProfileImportOneShotRouteBuilder(Map kafkaProps, String c @Override public void configure() throws Exception { - logger.info("Configure OneShot Route..."); + LOGGER.info("Configure OneShot Route..."); ProcessorDefinition prDefErr = onException(BadProfileDataFormatException.class) .log(LoggingLevel.ERROR, "Error processing record ${exchangeProperty.CamelSplitIndex}++ !") diff --git a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportToUnomiRouteBuilder.java b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportToUnomiRouteBuilder.java index 8336bf85c..ff4942c75 100644 --- a/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportToUnomiRouteBuilder.java +++ b/extensions/router/router-core/src/main/java/org/apache/unomi/router/core/route/ProfileImportToUnomiRouteBuilder.java @@ -33,7 +33,7 @@ */ public class ProfileImportToUnomiRouteBuilder extends RouterAbstractRouteBuilder { - private Logger logger = LoggerFactory.getLogger(ProfileImportToUnomiRouteBuilder.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileImportToUnomiRouteBuilder.class.getName()); private UnomiStorageProcessor unomiStorageProcessor; private ImportRouteCompletionProcessor importRouteCompletionProcessor; @@ -45,7 +45,7 @@ public ProfileImportToUnomiRouteBuilder(Map kafkaProps, String c @Override public void configure() throws Exception { - logger.info("Configure Recurrent Route 'To Target'"); + LOGGER.info("Configure Recurrent Route 'To Target'"); RouteDefinition rtDef; if (RouterConstants.CONFIG_TYPE_KAFKA.equals(configType)) { diff --git a/extensions/router/router-rest/pom.xml b/extensions/router/router-rest/pom.xml index 554eca61d..c97ae54d6 100644 --- a/extensions/router/router-rest/pom.xml +++ b/extensions/router/router-rest/pom.xml @@ -92,4 +92,4 @@ - \ No newline at end of file + diff --git a/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ExportConfigurationServiceEndPoint.java b/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ExportConfigurationServiceEndPoint.java index ff31a891d..b9462c0b6 100644 --- a/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ExportConfigurationServiceEndPoint.java +++ b/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ExportConfigurationServiceEndPoint.java @@ -52,7 +52,7 @@ @Component(service=ExportConfigurationServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class ExportConfigurationServiceEndPoint extends AbstractConfigurationServiceEndpoint { - private static final Logger logger = LoggerFactory.getLogger(ExportConfigurationServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ExportConfigurationServiceEndPoint.class.getName()); @Reference private ProfileExportService profileExportService; @@ -61,7 +61,7 @@ public class ExportConfigurationServiceEndPoint extends AbstractConfigurationSer private ProfileService profileService; public ExportConfigurationServiceEndPoint() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { - logger.info("Initializing export configuration service endpoint..."); + LOGGER.info("Initializing export configuration service endpoint..."); } @WebMethod(exclude = true) diff --git a/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java b/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java index db0f15159..37dd38bb9 100644 --- a/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java +++ b/extensions/router/router-rest/src/main/java/org/apache/unomi/router/rest/ImportConfigurationServiceEndPoint.java @@ -58,7 +58,7 @@ @Component(service=ImportConfigurationServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class ImportConfigurationServiceEndPoint extends AbstractConfigurationServiceEndpoint { - private static final Logger logger = LoggerFactory.getLogger(ImportConfigurationServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ImportConfigurationServiceEndPoint.class.getName()); @Reference protected ConfigSharingService configSharingService; @@ -69,7 +69,7 @@ public void setConfigSharingService(ConfigSharingService configSharingService) { } public ImportConfigurationServiceEndPoint() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { - logger.info("Initializing import configuration service endpoint..."); + LOGGER.info("Initializing import configuration service endpoint..."); } @WebMethod(exclude = true) @@ -118,7 +118,7 @@ public Response processOneshotImportConfigurationCSV(@Multipart(value = "importC Files.copy(in, path); } catch (IOException e) { - logger.error("Error processing one shot configuration CSV", e); + LOGGER.error("Error processing one shot configuration CSV", e); return Response.serverError().build(); } return Response.ok().build(); diff --git a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ExportConfigurationServiceImpl.java b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ExportConfigurationServiceImpl.java index d1b8d8f75..86088c9ca 100644 --- a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ExportConfigurationServiceImpl.java +++ b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ExportConfigurationServiceImpl.java @@ -32,7 +32,7 @@ */ public class ExportConfigurationServiceImpl implements ImportExportConfigurationService { - private static final Logger logger = LoggerFactory.getLogger(ExportConfigurationServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ExportConfigurationServiceImpl.class.getName()); private PersistenceService persistenceService; @@ -44,7 +44,7 @@ public void setPersistenceService(PersistenceService persistenceService) { private final Map camelConfigsToRefresh = new ConcurrentHashMap<>(); public ExportConfigurationServiceImpl() { - logger.info("Initializing export configuration service..."); + LOGGER.info("Initializing export configuration service..."); } @Override diff --git a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ImportConfigurationServiceImpl.java b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ImportConfigurationServiceImpl.java index a12d2991f..c88e3e560 100644 --- a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ImportConfigurationServiceImpl.java +++ b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ImportConfigurationServiceImpl.java @@ -32,7 +32,7 @@ */ public class ImportConfigurationServiceImpl implements ImportExportConfigurationService { - private static final Logger logger = LoggerFactory.getLogger(ImportConfigurationServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ImportConfigurationServiceImpl.class.getName()); private PersistenceService persistenceService; @@ -43,7 +43,7 @@ public void setPersistenceService(PersistenceService persistenceService) { private final Map camelConfigsToRefresh = new ConcurrentHashMap<>(); public ImportConfigurationServiceImpl() { - logger.info("Initializing import configuration service..."); + LOGGER.info("Initializing import configuration service..."); } @Override diff --git a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileExportServiceImpl.java b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileExportServiceImpl.java index c3197b61e..7a1fc34ec 100644 --- a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileExportServiceImpl.java +++ b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileExportServiceImpl.java @@ -39,7 +39,7 @@ */ public class ProfileExportServiceImpl implements ProfileExportService { - private static final Logger logger = LoggerFactory.getLogger(ProfileExportServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileExportServiceImpl.class.getName()); private PersistenceService persistenceService; @@ -101,7 +101,7 @@ public String convertProfileToCSVLine(Profile profile, ExportConfiguration expor for (int i = 0; i < mapping.size(); i++) { String propertyName = mapping.get(String.valueOf(i)); if (propertyName == null) { - logger.error("No index {} found in the provided mapping!", i); + LOGGER.error("No index {} found in the provided mapping!", i); return ""; } PropertyType propType = RouterUtils.getPropertyTypeById(propertiesDef, propertyName); diff --git a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileImportServiceImpl.java b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileImportServiceImpl.java index 578aee22c..52692fa97 100644 --- a/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileImportServiceImpl.java +++ b/extensions/router/router-service/src/main/java/org/apache/unomi/router/services/ProfileImportServiceImpl.java @@ -32,7 +32,7 @@ */ public class ProfileImportServiceImpl implements ProfileImportService { - private static final Logger logger = LoggerFactory.getLogger(ProfileImportServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileImportServiceImpl.class.getName()); private PersistenceService persistenceService; @@ -41,48 +41,48 @@ public void setPersistenceService(PersistenceService persistenceService) { } public boolean saveMergeDeleteImportedProfile(ProfileToImport profileToImport) throws InvocationTargetException, IllegalAccessException { - logger.debug("Importing profile with ID : {}", profileToImport.getItemId()); + LOGGER.debug("Importing profile with ID : {}", profileToImport.getItemId()); Profile existingProfile = new Profile(); if(profileToImport.getProperties().get(profileToImport.getMergingProperty()) != null) { List existingProfiles = persistenceService.query("properties." + profileToImport.getMergingProperty(), profileToImport.getProperties().get(profileToImport.getMergingProperty()).toString(), null, Profile.class); - logger.debug("Query existing profile with mergingProperty: {}. Found: {}", profileToImport.getMergingProperty(), existingProfiles.size()); + LOGGER.debug("Query existing profile with mergingProperty: {}. Found: {}", profileToImport.getMergingProperty(), existingProfiles.size()); //Profile already exist, and import config allow to overwrite profiles if (existingProfiles.size() == 1) { existingProfile = existingProfiles.get(0); if (profileToImport.isProfileToDelete()) { - logger.debug("Profile is to delete!"); + LOGGER.debug("Profile is to delete!"); persistenceService.remove(existingProfile.getItemId(), Profile.class); return true; } List propertiesToOverwrite = profileToImport.getPropertiesToOverwrite(); if (profileToImport.isOverwriteExistingProfiles() && propertiesToOverwrite != null && propertiesToOverwrite.size() > 0) { // We overwrite only properties marked to overwrite - logger.debug("Properties to overwrite: {}", propertiesToOverwrite); + LOGGER.debug("Properties to overwrite: {}", propertiesToOverwrite); for (String propName : propertiesToOverwrite) { existingProfile.getProperties().put(propName, profileToImport.getProperties().get(propName)); } } else { //If no property is marked to overwrite we replace the whole properties map - logger.debug("Overwrite all properties"); + LOGGER.debug("Overwrite all properties"); existingProfile.setProperties(profileToImport.getProperties()); } //update segments and scores existingProfile.setSegments(profileToImport.getSegments()); existingProfile.setScores(profileToImport.getScores()); } else if (existingProfiles.size() == 0 && !profileToImport.isProfileToDelete()) { - logger.debug("New profile to add..."); + LOGGER.debug("New profile to add..."); BeanUtils.copyProperties(existingProfile, profileToImport); } else { - logger.warn("{} occurences found for profile with {} = {}. Profile import is skipped", existingProfiles.size(), + LOGGER.warn("{} occurrence(s) found for profile with {} = {}. Profile import is skipped", existingProfiles.size(), profileToImport.getMergingProperty(), profileToImport.getProperties().get(profileToImport.getMergingProperty()).toString()); } - logger.debug("-------------------------------------"); + LOGGER.debug("-------------------------------------"); if (!profileToImport.isProfileToDelete()) { return persistenceService.save(existingProfile, true); } else { return false; } } else { - logger.error("Merging property '{}' has no value in the current profile.", profileToImport.getMergingProperty()); + LOGGER.error("Merging property '{}' has no value in the current profile.", profileToImport.getMergingProperty()); return false; } } diff --git a/extensions/salesforce-connector/actions/pom.xml b/extensions/salesforce-connector/actions/pom.xml index 9ec1f70c7..f75adbff1 100644 --- a/extensions/salesforce-connector/actions/pom.xml +++ b/extensions/salesforce-connector/actions/pom.xml @@ -46,4 +46,4 @@ - \ No newline at end of file + diff --git a/extensions/salesforce-connector/karaf-kar/pom.xml b/extensions/salesforce-connector/karaf-kar/pom.xml index 8c56bd8d8..011bfd538 100644 --- a/extensions/salesforce-connector/karaf-kar/pom.xml +++ b/extensions/salesforce-connector/karaf-kar/pom.xml @@ -88,4 +88,4 @@ - \ No newline at end of file + diff --git a/extensions/salesforce-connector/services/src/main/java/org/apache/unomi/sfdc/services/internal/SFDCServiceImpl.java b/extensions/salesforce-connector/services/src/main/java/org/apache/unomi/sfdc/services/internal/SFDCServiceImpl.java index 1ecb22a6e..31b66a354 100644 --- a/extensions/salesforce-connector/services/src/main/java/org/apache/unomi/sfdc/services/internal/SFDCServiceImpl.java +++ b/extensions/salesforce-connector/services/src/main/java/org/apache/unomi/sfdc/services/internal/SFDCServiceImpl.java @@ -30,7 +30,6 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicNameValuePair; -import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import org.apache.unomi.api.Consent; import org.apache.unomi.api.Profile; @@ -64,7 +63,7 @@ * Implementation of the Salesforce connector interface */ public class SFDCServiceImpl implements SFDCService { - private static final Logger logger = LoggerFactory.getLogger(SFDCServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SFDCServiceImpl.class.getName()); private static final String REST_ENDPOINT_URI = "/services/data/v38.0"; private static final String STREAMING_ENDPOINT_URI = "/cometd/38.0"; @@ -118,15 +117,12 @@ public boolean saveConfiguration(SFDCConfiguration sfdcConfiguration) { if (login(sfdcConfiguration)) { return true; } - } catch (HttpException e) { - logger.warn("Error trying to login with new configuration {}", sfdcConfiguration, e); - result = false; - } catch (IOException e) { - logger.warn("Error trying to login with new configuration {}", sfdcConfiguration, e); + } catch (HttpException | IOException e) { + LOGGER.warn("Error trying to login with new configuration {}", sfdcConfiguration, e); result = false; } } else { - logger.error("Error trying to save new Salesforce connection configuration !"); + LOGGER.error("Error trying to save new Salesforce connection configuration !"); } return result; } @@ -149,14 +145,12 @@ public void start() { } sfdcLeadMandatoryFields = getLeadMandatoryFields(); // setupPushTopics(SFDCSession.getEndPoint(), SFDCSession.getSessionId()); - logger.info("Salesforce connector initialized successfully."); + LOGGER.info("Salesforce connector initialized successfully."); } else { - logger.warn("Salesforce connector is not yet configured."); + LOGGER.warn("Salesforce connector is not yet configured."); } - } catch (HttpException | IOException e) { - logger.error("Failed to init SFDCService properly", e); } catch (Exception e) { - logger.error("Failed to init SFDCService properly", e); + LOGGER.error("Failed to init SFDCService properly", e); } } @@ -175,12 +169,12 @@ public Set getRecentLeadIds() { try { Object responseObject = handleRequest(getRecentLeads); if (responseObject == null) { - logger.warn("Couldn't retrieve recent leads"); + LOGGER.warn("Couldn't retrieve recent leads"); return null; } Map queryResponse = (Map) responseObject; if (queryResponse.containsKey("recentItems")) { - logger.debug("Response received from Salesforce: {}", queryResponse); + LOGGER.debug("Response received from Salesforce: {}", queryResponse); Object[] recentItems = (Object[]) queryResponse.get("recentItems"); for (Object recentItem : recentItems) { Map recentItemMap = (Map) recentItem; @@ -188,10 +182,8 @@ public Set getRecentLeadIds() { } } - } catch (IOException e) { - logger.error("Error getting recent leads", e); - } catch (HttpException e) { - logger.error("Error getting recent leads", e); + } catch (IOException | HttpException e) { + LOGGER.error("Error getting recent leads", e); } return recentLeadIds; @@ -209,19 +201,17 @@ public Map getSObject(String sobjectName, String objectId) { try { Object responseObject = handleRequest(getSObject); if (responseObject == null) { - logger.warn("Couldn't retrieve sobject {} with id {}", sobjectName, objectId); + LOGGER.warn("Couldn't retrieve sobject {} with id {}", sobjectName, objectId); return null; } Map queryResponse = (Map) responseObject; if (queryResponse != null) { - logger.debug("Response received from Salesforce: {}", queryResponse); + LOGGER.debug("Response received from Salesforce: {}", queryResponse); sobjectMap = new LinkedHashMap<>(queryResponse); } - } catch (IOException e) { - logger.error("Error getting sobject {} with id {}", sobjectName, objectId, e); - } catch (HttpException e) { - logger.error("Error getting sobject {} with id {}", sobjectName, objectId, e); + } catch (IOException | HttpException e) { + LOGGER.error("Error getting sobject {} with id {}", sobjectName, objectId, e); } return sobjectMap; } @@ -238,19 +228,17 @@ public Map getSObjectDescribe(String sobjectName) { try { Object responseObject = handleRequest(getSObjectDescribe); if (responseObject == null) { - logger.warn("Couldn't retrieve sobject {} describe", sobjectName); + LOGGER.warn("Couldn't retrieve sobject {} describe", sobjectName); return null; } Map queryResponse = (Map) responseObject; if (queryResponse != null) { - logger.debug("Response received from Salesforce: {}", queryResponse); + LOGGER.debug("Response received from Salesforce: {}", queryResponse); sobjectDescribe = new LinkedHashMap<>(queryResponse); } - } catch (IOException e) { - logger.error("Error getting sobject {}", sobjectName, e); - } catch (HttpException e) { - logger.error("Error getting sobject {}", sobjectName, e); + } catch (IOException | HttpException e) { + LOGGER.error("Error getting sobject {}", sobjectName, e); } return sobjectDescribe; } @@ -301,10 +289,8 @@ public boolean deleteLead(String leadId) { HttpDelete deleteLead = new HttpDelete(baseUrl); try { Object responseObject = handleRequest(deleteLead); - } catch (IOException e) { - logger.error("Error deleting lead {}", leadId, e); - } catch (HttpException e) { - logger.error("Error deleting lead {}", leadId, e); + } catch (IOException | HttpException e) { + LOGGER.error("Error deleting lead {}", leadId, e); } return true; } @@ -341,15 +327,13 @@ public Set findLeadIdsByIdentifierValue(String identifierFieldValue) { private boolean isProfileInContacts(String identifierFieldValue) { if (sfdcConfiguration.isSfdcCheckIfContactExistBeforeLeadCreation()) { - logger.info("Checking if we have a contact for identifier value {}...", identifierFieldValue); + LOGGER.info("Checking if we have a contact for identifier value {}...", identifierFieldValue); Object response; Set queryResult = new LinkedHashSet<>(); response = query("SELECT Id FROM Contact WHERE " + sfdcConfiguration.getSfdcIdentifierField() + "='" + identifierFieldValue + "'"); queryResult = mappingResponse(response, queryResult); - if (queryResult.size() > 0) { - return true; - } + return !queryResult.isEmpty(); } return false; } @@ -359,21 +343,20 @@ private void addConsents(Profile profile, Map sfdcLeadFields) { String mappingConsentsString = sfdcConfiguration.getSfdcFieldsConsents(); if (!mappingConsentsString.isEmpty()) { String[] mappingConsents = mappingConsentsString.split(","); - if (mappingConsents.length > 0) { - for (String mappingConsent : mappingConsents) { - String[] mappingConsentArray = mappingConsent.split("<=>"); - if (mappingConsentArray.length <= 0) { - logger.error("Error with the mapping for field {}, this field will not be mapped please check the cfg file", mappingConsentsString); + for (String mappingConsent : mappingConsents) { + String[] mappingConsentArray = mappingConsent.split("<=>"); + if (mappingConsentArray.length <= 0) { + LOGGER.error("Error with the mapping for field {}, this field will not be mapped please check the cfg file", + mappingConsentsString); + } else { + String consentUnomiId = mappingConsentArray[0]; + if (consents.containsKey(consentUnomiId)) { + String consentSfdcId = mappingConsentArray[1]; + String consentValue = consents.get(consentUnomiId).getStatus().toString(); + sfdcLeadFields.put(consentSfdcId, consentValue); + LOGGER.debug("Consent {} with value {} was mapped with {}", consentUnomiId, consentValue, consentSfdcId); } else { - String consentUnomiId = mappingConsentArray[0]; - if (consents.containsKey(consentUnomiId)) { - String consentSfdcId = mappingConsentArray[1]; - String consentValue = consents.get(consentUnomiId).getStatus().toString(); - sfdcLeadFields.put(consentSfdcId, consentValue); - logger.debug("Consent {} with value {} was mapped with {}", consentUnomiId, consentValue, consentSfdcId); - } else { - logger.warn("Consent {} not found in current profile or not answered yet", consentUnomiId); - } + LOGGER.warn("Consent {} not found in current profile or not answered yet", consentUnomiId); } } } @@ -388,12 +371,12 @@ public String createOrUpdateLead(Profile profile) { // first we must check if an existing contact exists for the profile. String unomiIdentifierValue = (String) profile.getProperty(sfdcConfiguration.getUnomiIdentifierField()); if (isProfileInContacts(unomiIdentifierValue)) { - logger.info("Contact {} found in SFDC... No SFDC field value to send, will not send anything to " + + LOGGER.info("Contact {} found in SFDC... No SFDC field value to send, will not send anything to " + "Salesforce. ", unomiIdentifierValue); return null; } // then we must check if an existing lead exists for the profile. - logger.info("Checking if we have a lead for identifier value {}...", unomiIdentifierValue); + LOGGER.info("Checking if we have a lead for identifier value {}...", unomiIdentifierValue); Set foundExistingSfdcLeadIds = findLeadIdsByIdentifierValue(unomiIdentifierValue); Map sfdcLeadFields = new HashMap<>(); @@ -402,23 +385,23 @@ public String createOrUpdateLead(Profile profile) { if (foundExistingSfdcLeadIds.size() > 1) { // we found multiple leads matching the identifier value ! - logger.warn("Found multiple matching leads for identifier value {}, will use first matching one !", + LOGGER.warn("Found multiple matching leads for identifier value {}, will use first matching one !", unomiIdentifierValue); } - if (foundExistingSfdcLeadIds.size() > 0) { - logger.info("Found an existing lead, attempting to update it..."); + if (!foundExistingSfdcLeadIds.isEmpty()) { + LOGGER.info("Found an existing lead, attempting to update it..."); // we found an existing lead we must update it existingSfdcLeadFields = getLead(foundExistingSfdcLeadIds.iterator().next()); if (existingSfdcLeadFields.get("LastModifiedDate") != null) { try { sfdcLastModified = iso8601DateFormat.parse((String) existingSfdcLeadFields.get("LastModifiedDate")); } catch (ParseException e) { - logger.error("Error parsing date {}", existingSfdcLeadFields.get("LastModifiedDate"), e); + LOGGER.error("Error parsing date {}", existingSfdcLeadFields.get("LastModifiedDate"), e); } } } else { - logger.info("No existing lead found."); + LOGGER.info("No existing lead found."); } for (String profilePropertyKey : profile.getProperties().keySet()) { @@ -430,35 +413,35 @@ public String createOrUpdateLead(Profile profile) { Object unomiPropertyValue = profile.getProperties().get(profilePropertyKey); if (existingSfdcLeadFields.get(sfdcFieldName) == null) { // we only set the field if it didn't have a value. - logger.info("Setting SFDC field {} value to {}", sfdcFieldName, unomiPropertyValue); + LOGGER.info("Setting SFDC field {} value to {}", sfdcFieldName, unomiPropertyValue); sfdcLeadFields.put(sfdcFieldName, unomiPropertyValue); } else { // current strategy : Unomi field value wins if different from Salesforce value // @todo we should probably improve this by tracking last modification dates on profile/lead properties Object sfdcLeadFieldValue = existingSfdcLeadFields.get(sfdcFieldName); if (!unomiPropertyValue.equals(sfdcLeadFieldValue)) { - logger.info("Overwriting SFDC field {} value to {}", sfdcFieldName, unomiPropertyValue); + LOGGER.info("Overwriting SFDC field {} value to {}", sfdcFieldName, unomiPropertyValue); sfdcLeadFields.put(sfdcFieldName, unomiPropertyValue); } } } addConsents(profile, sfdcLeadFields); - if (sfdcLeadFields.size() == 0) { - logger.info("No SFDC field value to send, will not send anything to Salesforce."); - if (foundExistingSfdcLeadIds.size() == 0) { + if (sfdcLeadFields.isEmpty()) { + LOGGER.info("No SFDC field value to send, will not send anything to Salesforce."); + if (foundExistingSfdcLeadIds.isEmpty()) { return null; } else { return foundExistingSfdcLeadIds.iterator().next(); } } - if (existingSfdcLeadFields.size() == 0) { + if (existingSfdcLeadFields.isEmpty()) { // if we are creating a lead, let's make sure we have all the mandatory fields before sending the request boolean missingMandatoryFields = false; for (String leadMandatoryFieldName : sfdcLeadMandatoryFields) { if (sfdcLeadFields.get(leadMandatoryFieldName) == null) { - logger.warn("Missing mandatory field {}, aborting sending to Salesforce", leadMandatoryFieldName); + LOGGER.warn("Missing mandatory field {}, aborting sending to Salesforce", leadMandatoryFieldName); missingMandatoryFields = true; } } @@ -469,7 +452,7 @@ public String createOrUpdateLead(Profile profile) { String baseUrl = sfdcSession.getEndPoint() + REST_ENDPOINT_URI + "/sobjects/Lead"; HttpEntityEnclosingRequestBase request = new HttpPost(baseUrl); - if (foundExistingSfdcLeadIds.size() > 0) { + if (!foundExistingSfdcLeadIds.isEmpty()) { baseUrl = sfdcSession.getEndPoint() + REST_ENDPOINT_URI + "/sobjects/Lead/" + foundExistingSfdcLeadIds .iterator().next(); sfdcLeadFields.remove("Id"); @@ -490,18 +473,16 @@ public String createOrUpdateLead(Profile profile) { Map responseData = (Map) responseObject; if (responseData.get("id") != null) { String sfdcId = (String) responseData.get("id"); - logger.info("Lead successfully created/updated in Salesforce. sfdcId={}", sfdcId); + LOGGER.info("Lead successfully created/updated in Salesforce. sfdcId={}", sfdcId); return sfdcId; } } - logger.info("Response received from Salesforce: {}", responseObject); - } catch (IOException e) { - logger.error("Error creating or updating lead for profile {}", profile, e); - } catch (HttpException e) { - logger.error("Error creating or updating lead for profile {}", profile, e); + LOGGER.info("Response received from Salesforce: {}", responseObject); + } catch (IOException | HttpException e) { + LOGGER.error("Error creating or updating lead for profile {}", profile, e); } - if (foundExistingSfdcLeadIds.size() == 0) { + if (foundExistingSfdcLeadIds.isEmpty()) { return null; } else { return foundExistingSfdcLeadIds.iterator().next(); @@ -515,19 +496,19 @@ public boolean updateProfileFromLead(Profile profile) { } String unomiIdentifierValue = (String) profile.getProperty(sfdcConfiguration.getUnomiIdentifierField()); Set foundSfdcLeadIds = findLeadIdsByIdentifierValue(unomiIdentifierValue); - if (foundSfdcLeadIds.size() == 0) { - logger.info("No lead found in Salesforce corresponding to profile {}", profile); + if (foundSfdcLeadIds.isEmpty()) { + LOGGER.info("No lead found in Salesforce corresponding to profile {}", profile); // we didn't find a corresponding lead in salesforce. return false; } else if (foundSfdcLeadIds.size() > 1) { - logger.warn("Found multiple leads in Salesforce for identifier value {}, will use first one.", + LOGGER.warn("Found multiple leads in Salesforce for identifier value {}, will use first one.", foundSfdcLeadIds); } else { - logger.info("Found corresponding lead with identifier value {}", unomiIdentifierValue); + LOGGER.info("Found corresponding lead with identifier value {}", unomiIdentifierValue); } Map sfdcLead = getLead(foundSfdcLeadIds.iterator().next()); if (sfdcLead == null) { - logger.error("Error retrieving lead {} from Salesforce", foundSfdcLeadIds); + LOGGER.error("Error retrieving lead {} from Salesforce", foundSfdcLeadIds); return false; } boolean profileUpdated = false; @@ -543,7 +524,7 @@ public boolean updateProfileFromLead(Profile profile) { } } } - logger.info("Updated profile {} from Salesforce lead {}", profile, sfdcLead); + LOGGER.info("Updated profile {} from Salesforce lead {}", profile, sfdcLead); return profileUpdated; } @@ -558,28 +539,14 @@ public Map query(String query) { try { baseUrl = sfdcSession.getEndPoint() + REST_ENDPOINT_URI + "/query?q=" + URLEncoder.encode(query, "UTF-8"); HttpGet get = new HttpGet(baseUrl); - Object responseObject = handleRequest(get); - if (responseObject == null) { - return null; - } - if (responseObject != null && responseObject instanceof Map) { + if (responseObject instanceof Map) { return (Map) responseObject; } - return null; - } catch (UnsupportedEncodingException e) { - logger.error("Error executing query {}", query, e); - return null; - } catch (ClientProtocolException e) { - logger.error("Error executing query {}", query, e); - return null; - } catch (IOException e) { - logger.error("Error executing query {}", query, e); - return null; - } catch (HttpException e) { - logger.error("Error executing query {}", query, e); - return null; + } catch (IOException | HttpException e) { + LOGGER.error("Error executing query {}", query, e); } + return null; } @Override @@ -591,29 +558,14 @@ public Map getLimits() { try { baseUrl = sfdcSession.getEndPoint() + REST_ENDPOINT_URI + "/limits"; HttpGet get = new HttpGet(baseUrl); - Object responseObject = handleRequest(get); - if (responseObject == null) { - return null; - } - if (responseObject instanceof Map) { return (Map) responseObject; } - return null; - } catch (UnsupportedEncodingException e) { - logger.error("Error retrieving Salesforce API Limits", e); - return null; - } catch (ClientProtocolException e) { - logger.error("Error retrieving Salesforce API Limits", e); - return null; - } catch (IOException e) { - logger.error("Error retrieving Salesforce API Limits", e); - return null; - } catch (HttpException e) { - logger.error("Error retrieving Salesforce API Limits", e); - return null; + } catch (IOException | HttpException e) { + LOGGER.error("Error retrieving Salesforce API Limits", e); } + return null; } private BayeuxClient makeClient() throws Exception { @@ -623,11 +575,10 @@ private BayeuxClient makeClient() throws Exception { httpClient.start(); if (sfdcSession == null) { - logger.error("Invalid session !"); + LOGGER.error("Invalid session !"); return null; } - logger.info("Login successful!\nServer URL: " + sfdcSession.getEndPoint() - + "\nSession ID=" + sfdcSession.getSessionId()); + LOGGER.info("Login successful!\nServer URL: {}\nSession ID={}", sfdcSession.getEndPoint(), sfdcSession.getSessionId()); Map options = new HashMap(); options.put(ClientTransport.MAX_NETWORK_DELAY_OPTION, READ_TIMEOUT); @@ -659,18 +610,18 @@ public void setupPushListener(String channelName, ClientSessionChannel.MessageLi @Override public void onMessage(ClientSessionChannel channel, Message message) { - logger.info("[CHANNEL:META_HANDSHAKE]: " + message); + LOGGER.info("[CHANNEL:META_HANDSHAKE]: {}", message); boolean success = message.isSuccessful(); if (!success) { String error = (String) message.get("error"); if (error != null) { - logger.error("Error during HANDSHAKE: " + error); + LOGGER.error("Error during HANDSHAKE: {}", error); } Exception exception = (Exception) message.get("exception"); if (exception != null) { - logger.error("Exception during HANDSHAKE: ", exception); + LOGGER.error("Exception during HANDSHAKE: ", exception); } } } @@ -681,13 +632,13 @@ public void onMessage(ClientSessionChannel channel, Message message) { new ClientSessionChannel.MessageListener() { public void onMessage(ClientSessionChannel channel, Message message) { - logger.info("[CHANNEL:META_CONNECT]: " + message); + LOGGER.info("[CHANNEL:META_CONNECT]: {}", message); boolean success = message.isSuccessful(); if (!success) { String error = (String) message.get("error"); if (error != null) { - logger.error("Error during CONNECT: " + error); + LOGGER.error("Error during CONNECT: {}", error); } } } @@ -699,26 +650,26 @@ public void onMessage(ClientSessionChannel channel, Message message) { public void onMessage(ClientSessionChannel channel, Message message) { - logger.debug("[CHANNEL:META_SUBSCRIBE]: " + message); + LOGGER.debug("[CHANNEL:META_SUBSCRIBE]: {}", message); boolean success = message.isSuccessful(); if (!success) { String error = (String) message.get("error"); if (error != null) { - logger.error("Error during SUBSCRIBE: " + error); + LOGGER.error("Error during SUBSCRIBE: {}", error); } } } }); client.handshake(); - logger.debug("Waiting for handshake"); + LOGGER.debug("Waiting for handshake"); boolean handshaken = client.waitFor(10 * 1000, BayeuxClient.State.CONNECTED); if (!handshaken) { - logger.error("Failed to handshake: " + client); + LOGGER.error("Failed to handshake: {}", client); } - logger.info("Subscribing for channel: " + channelName); + LOGGER.info("Subscribing for channel: {}", channelName); client.getChannel(channelName).subscribe(messageListener); @@ -737,7 +688,7 @@ private void setupPushTopics(String host, String sessionId) throws HttpException Map queryResponse = (Map) handleRequest(get); if (queryResponse != null && queryResponse.containsKey("count")) { - logger.info("Push topics setup successfully"); + LOGGER.info("Push topics setup successfully"); } } @@ -784,11 +735,8 @@ private SFDCSession getValidSession() { if (loginSuccessful && sfdcSession != null) { return sfdcSession; } - } catch (HttpException e) { - logger.error("Error logging in", e); - return null; - } catch (IOException e) { - logger.error("Error logging in", e); + } catch (HttpException | IOException e) { + LOGGER.error("Error logging in", e); return null; } return null; @@ -798,10 +746,7 @@ private boolean isSessionValid() { if (sfdcSession == null) { return false; } - if (sfdcSession.isExpired()) { - return false; - } - return true; + return !sfdcSession.isExpired(); } private Object handleRequest(HttpUriRequest request) throws IOException, HttpException { @@ -814,11 +759,11 @@ private Object handleRequest(HttpUriRequest request, int retryCount, boolean add if (addAuthorizationHeader) { SFDCSession sfdcSession = getValidSession(); if (sfdcSession == null) { - logger.error("Couldn't get a valid session !"); + LOGGER.error("Couldn't get a valid session !"); return null; } if (request.containsHeader("Authorization")) { - logger.debug("Replacing existing authorization header with an updated one."); + LOGGER.debug("Replacing existing authorization header with an updated one."); Header[] authorizationHeaders = request.getHeaders("Authorization"); for (Header authorizationHeader : authorizationHeaders) { request.removeHeader(authorizationHeader); @@ -832,19 +777,19 @@ private Object handleRequest(HttpUriRequest request, int retryCount, boolean add if ((response.getStatusLine().getStatusCode() == 401 || response.getStatusLine().getStatusCode() == 403) && retryCount > 0) { // probably the session has expired, let's try to login again - logger.warn("Unauthorized request, attempting to login again..."); + LOGGER.warn("Unauthorized request, attempting to login again..."); boolean loginSuccessful = login(sfdcConfiguration); if (!loginSuccessful) { - logger.error("Login failed, cannot execute request {}", request); + LOGGER.error("Login failed, cannot execute request {}", request); return null; } - logger.warn("Retrying request {} once again...", request); + LOGGER.warn("Retrying request {} once again...", request); return handleRequest(request, 0, true); } else { - logger.error("Error executing request {}: {}-{}", request, response.getStatusLine().getStatusCode(), + LOGGER.error("Error executing request {}: {}-{}", request, response.getStatusLine().getStatusCode(), response.getStatusLine().getReasonPhrase()); if (response.getEntity() != null) { - logger.error("Entity={}", EntityUtils.toString(response.getEntity())); + LOGGER.error("Entity={}", EntityUtils.toString(response.getEntity())); } } return null; @@ -857,7 +802,7 @@ private Object handleRequest(HttpUriRequest request, int retryCount, boolean add public boolean isConfigured() { if (!sfdcConfiguration.isComplete()) { - logger.warn("Connection to Salesforce is not properly configured !"); + LOGGER.warn("Connection to Salesforce is not properly configured !"); return false; } return true; @@ -868,11 +813,11 @@ public boolean isConnected() { return false; } if (sfdcSession == null) { - logger.warn("Not connected to SalesForce, operation will not execute."); + LOGGER.warn("Not connected to SalesForce, operation will not execute."); return false; } else { if (sfdcSession.isExpired()) { - logger.warn("Connection to Salesforce has expired, will reconnect on next request"); + LOGGER.warn("Connection to Salesforce has expired, will reconnect on next request"); return true; } } diff --git a/extensions/weather-update/core/src/main/java/org/apache/unomi/weatherupdate/actions/WeatherUpdateAction.java b/extensions/weather-update/core/src/main/java/org/apache/unomi/weatherupdate/actions/WeatherUpdateAction.java index 0f9e75691..a3ffffd2f 100644 --- a/extensions/weather-update/core/src/main/java/org/apache/unomi/weatherupdate/actions/WeatherUpdateAction.java +++ b/extensions/weather-update/core/src/main/java/org/apache/unomi/weatherupdate/actions/WeatherUpdateAction.java @@ -44,6 +44,8 @@ */ public class WeatherUpdateAction implements ActionExecutor { + private static final Logger LOGGER = LoggerFactory.getLogger(WeatherUpdateAction.class); + private static final double KELVIN = 273.15; private static final double ROUND_TO_THE_TENTH = 0.5; private static final double SECOND_TO_HOUR = 3.6; @@ -60,7 +62,6 @@ public class WeatherUpdateAction implements ActionExecutor { private static final String WEATHER_WIND_SPEED = "weatherWindSpeed"; private static final String LOCATION = "location"; private static final String MESSAGE = "message"; - private static Logger logger = LoggerFactory.getLogger(WeatherUpdateAction.class); private CloseableHttpClient httpClient; private String weatherApiKey; private String weatherUrlBase; @@ -74,20 +75,20 @@ public int execute(Action action, Event event) { Session session = event.getSession(); if (weatherApiKey == null || weatherUrlBase == null || weatherUrlAttributes == null) { - logger.warn("Configuration incomplete."); + LOGGER.warn("Configuration incomplete."); return EventService.NO_CHANGE; } Map sessionProperties = session.getProperties(); if (!sessionProperties.containsKey(LOCATION)) { - logger.warn("No location info found in the session."); + LOGGER.warn("No location info found in the session."); return EventService.NO_CHANGE; } Map location = (Map) session.getProperty(LOCATION); JsonNode currentWeatherData = getWeather(location); if (currentWeatherData == null) { - logger.error("No response from the request"); + LOGGER.error("No response from the request"); return EventService.NO_CHANGE; } @@ -96,15 +97,15 @@ public int execute(Action action, Event event) { return EventService.SESSION_UPDATED; } else { if (currentWeatherData.has(MESSAGE) && currentWeatherData.has(STATUS_CODE)) { - logger.error("Something went wrong, the status code was {} and the message response was {}", + LOGGER.error("Something went wrong, the status code was {} and the message response was {}", currentWeatherData.get(STATUS_CODE), currentWeatherData.get(MESSAGE)); } else { - logger.error("Something went wrong, the response was {}", currentWeatherData); + LOGGER.error("Something went wrong, the response was {}", currentWeatherData); } } - logger.info("No update made"); + LOGGER.info("No update made"); return EventService.NO_CHANGE; } @@ -131,12 +132,12 @@ private JsonNode getWeather(Map location) { ObjectMapper objectMapper = new ObjectMapper(); currentWeatherData = objectMapper.readTree(responseString); } catch (IOException e) { - logger.error("Error with the API json response.", e); + LOGGER.error("Error with the API json response.", e); } } } } catch (IOException e) { - logger.error("Error with the Http Request execution. Wrong parameters given", e); + LOGGER.error("Error with the Http Request execution. Wrong parameters given", e); } finally { if (response != null) { EntityUtils.consumeQuietly(response.getEntity()); @@ -186,10 +187,10 @@ private String extractTemperature(JsonNode currentWeatherData) { if (temperature - temperatureTreated > ROUND_TO_THE_TENTH) { temperatureTreated++; } - logger.debug("Temperature: {}", temperatureTreated); + LOGGER.debug("Temperature: {}", temperatureTreated); return String.valueOf(temperatureTreated); } - logger.info("API Response doesn't contains the temperature"); + LOGGER.info("API Response doesn't contains the temperature"); return null; } @@ -206,10 +207,10 @@ private String extractWindSpeed(JsonNode currentWeatherData) { float speed = Float.parseFloat(WindInfoSpeed.toString()); speed *= SECOND_TO_HOUR; int speedTreated = (int) speed; - logger.debug("Wind speed: {}", speedTreated); + LOGGER.debug("Wind speed: {}", speedTreated); return String.valueOf(speedTreated); } - logger.info("API Response doesn't contains the wind speed"); + LOGGER.info("API Response doesn't contains the wind speed"); return null; } @@ -245,12 +246,12 @@ private String extractWindDirection(JsonNode currentWeatherData) { } else if (290 < deg && deg < 340) { direction = ("NW"); } - logger.debug("Wind direction: {} ", direction); + LOGGER.debug("Wind direction: {} ", direction); return direction; } } } - logger.warn("API Response doesn't contains the wind direction"); + LOGGER.warn("API Response doesn't contains the wind direction"); return null; } @@ -264,13 +265,13 @@ private String extractWeatherLike(JsonNode currentWeatherData) { JsonNode weatherLike; if (currentWeatherData.has(WEATHER_LIKE_INFO)) { weatherLike = currentWeatherData.get(WEATHER_LIKE_INFO); - if (weatherLike.size() > 0) { + if (!weatherLike.isEmpty()) { weatherLike = weatherLike.get(0).get(MAIN_INFO_WEATHER); - logger.debug("Weather like: {}", weatherLike); + LOGGER.debug("Weather like: {}", weatherLike); return weatherLike.asText(); } } - logger.warn("API Response doesn't contains the weather description"); + LOGGER.warn("API Response doesn't contains the weather description"); return null; } diff --git a/extensions/web-tracker/wab/yarn.lock b/extensions/web-tracker/wab/yarn.lock index 879c19dd7..1ba5f474a 100644 --- a/extensions/web-tracker/wab/yarn.lock +++ b/extensions/web-tracker/wab/yarn.lock @@ -4,7 +4,7 @@ "@ampproject/remapping@^2.1.0": version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: "@jridgewell/gen-mapping" "^0.1.0" @@ -12,19 +12,19 @@ "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz" integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg== "@babel/core@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz" integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw== dependencies: "@ampproject/remapping" "^2.1.0" @@ -45,7 +45,7 @@ "@babel/generator@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz" integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== dependencies: "@babel/types" "^7.19.0" @@ -54,14 +54,14 @@ "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz" integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== dependencies: "@babel/helper-explode-assignable-expression" "^7.18.6" @@ -69,7 +69,7 @@ "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz" integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg== dependencies: "@babel/compat-data" "^7.19.1" @@ -79,7 +79,7 @@ "@babel/helper-create-class-features-plugin@^7.18.6": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz" integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -92,7 +92,7 @@ "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz" integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -100,7 +100,7 @@ "@babel/helper-define-polyfill-provider@^0.3.3": version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz" integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== dependencies: "@babel/helper-compilation-targets" "^7.17.7" @@ -112,19 +112,19 @@ "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== "@babel/helper-explode-assignable-expression@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz" integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== dependencies: "@babel/types" "^7.18.6" "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz" integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: "@babel/template" "^7.18.10" @@ -132,28 +132,28 @@ "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz" integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== dependencies: "@babel/types" "^7.18.9" "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz" integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -167,19 +167,19 @@ "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz" integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz" integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz" integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -189,7 +189,7 @@ "@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz" integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -200,43 +200,43 @@ "@babel/helper-simple-access@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz" integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== dependencies: "@babel/types" "^7.18.6" "@babel/helper-skip-transparent-expression-wrappers@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz" integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw== dependencies: "@babel/types" "^7.18.9" "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-string-parser@^7.18.10": version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz" integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== "@babel/helper-validator-identifier@^7.18.6": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== "@babel/helper-validator-option@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== "@babel/helper-wrap-function@^7.18.9": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz" integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== dependencies: "@babel/helper-function-name" "^7.19.0" @@ -246,7 +246,7 @@ "@babel/helpers@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz" integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== dependencies: "@babel/template" "^7.18.10" @@ -255,7 +255,7 @@ "@babel/highlight@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== dependencies: "@babel/helper-validator-identifier" "^7.18.6" @@ -264,19 +264,19 @@ "@babel/parser@^7.18.10", "@babel/parser@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz" integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz" integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -285,7 +285,7 @@ "@babel/plugin-proposal-async-generator-functions@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz" integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -295,7 +295,7 @@ "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -303,7 +303,7 @@ "@babel/plugin-proposal-class-static-block@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz" integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -312,7 +312,7 @@ "@babel/plugin-proposal-dynamic-import@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz" integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -320,7 +320,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz" integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -328,7 +328,7 @@ "@babel/plugin-proposal-json-strings@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz" integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -336,7 +336,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz" integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -344,7 +344,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -352,7 +352,7 @@ "@babel/plugin-proposal-numeric-separator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -360,7 +360,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz" integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q== dependencies: "@babel/compat-data" "^7.18.8" @@ -371,7 +371,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -379,7 +379,7 @@ "@babel/plugin-proposal-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz" integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -388,7 +388,7 @@ "@babel/plugin-proposal-private-methods@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz" integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -396,7 +396,7 @@ "@babel/plugin-proposal-private-property-in-object@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz" integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -406,7 +406,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz" integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -414,119 +414,119 @@ "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz" integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz" integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-async-to-generator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz" integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: "@babel/helper-module-imports" "^7.18.6" @@ -535,21 +535,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz" integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-block-scoping@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz" integrity sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-classes@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz" integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -564,21 +564,21 @@ "@babel/plugin-transform-computed-properties@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz" integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-destructuring@^7.18.13": version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz" integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz" integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -586,14 +586,14 @@ "@babel/plugin-transform-duplicate-keys@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz" integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-exponentiation-operator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz" integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" @@ -601,14 +601,14 @@ "@babel/plugin-transform-for-of@^7.18.8": version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz" integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-function-name@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz" integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== dependencies: "@babel/helper-compilation-targets" "^7.18.9" @@ -617,21 +617,21 @@ "@babel/plugin-transform-literals@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz" integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-member-expression-literals@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz" integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-modules-amd@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz" integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -640,7 +640,7 @@ "@babel/plugin-transform-modules-commonjs@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz" integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -650,7 +650,7 @@ "@babel/plugin-transform-modules-systemjs@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz" integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A== dependencies: "@babel/helper-hoist-variables" "^7.18.6" @@ -661,7 +661,7 @@ "@babel/plugin-transform-modules-umd@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz" integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -669,7 +669,7 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz" integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.19.0" @@ -677,14 +677,14 @@ "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz" integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-object-super@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz" integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -692,21 +692,21 @@ "@babel/plugin-transform-parameters@^7.18.8": version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz" integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz" integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-regenerator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz" integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -714,21 +714,21 @@ "@babel/plugin-transform-reserved-words@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz" integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-shorthand-properties@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz" integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-spread@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz" integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== dependencies: "@babel/helper-plugin-utils" "^7.19.0" @@ -736,35 +736,35 @@ "@babel/plugin-transform-sticky-regex@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz" integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-template-literals@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz" integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-typeof-symbol@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz" integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-escapes@^7.18.10": version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz" integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-regex@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz" integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -772,7 +772,7 @@ "@babel/preset-env@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.1.tgz#9f04c916f9c0205a48ebe5cc1be7768eb1983f67" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.1.tgz" integrity sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA== dependencies: "@babel/compat-data" "^7.19.1" @@ -853,7 +853,7 @@ "@babel/preset-modules@^0.1.5": version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -864,21 +864,21 @@ "@babel/runtime@^7.18.9": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" "@babel/runtime@^7.8.4": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz" integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== dependencies: regenerator-runtime "^0.13.4" "@babel/template@^7.18.10": version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz" integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== dependencies: "@babel/code-frame" "^7.18.6" @@ -887,7 +887,7 @@ "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz" integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA== dependencies: "@babel/code-frame" "^7.18.6" @@ -903,7 +903,7 @@ "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz" integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== dependencies: "@babel/helper-string-parser" "^7.18.10" @@ -912,7 +912,7 @@ "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== dependencies: "@jridgewell/set-array" "^1.0.0" @@ -920,7 +920,7 @@ "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -929,17 +929,17 @@ "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.2": version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== dependencies: "@jridgewell/gen-mapping" "^0.3.0" @@ -947,12 +947,12 @@ "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz" integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== dependencies: "@jridgewell/resolve-uri" "^3.0.3" @@ -960,7 +960,7 @@ "@rollup/plugin-babel@^5.3.1": version "5.3.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" + resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz" integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q== dependencies: "@babel/helper-module-imports" "^7.10.4" @@ -968,7 +968,7 @@ "@rollup/plugin-commonjs@^22.0.2": version "22.0.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz#ee8ca8415cda30d383b4096aad5222435b4b69b6" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz" integrity sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -981,7 +981,7 @@ "@rollup/plugin-inject@^4.0.0": version "4.0.4" - resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-4.0.4.tgz#fbeee66e9a700782c4f65c8b0edbafe58678fbc2" + resolved "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-4.0.4.tgz" integrity sha512-4pbcU4J/nS+zuHk+c+OL3WtmEQhqxlZ9uqfjQMQDOHOPld7PsCd8k5LWs8h5wjwJN7MgnAn768F2sDxEP4eNFQ== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -990,7 +990,7 @@ "@rollup/plugin-node-resolve@^14.1.0": version "14.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz#f2fa475405cd7fed6420bf438fe393f988a9bc96" + resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz" integrity sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -1002,7 +1002,7 @@ "@rollup/pluginutils@^3.0.9", "@rollup/pluginutils@^3.1.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz" integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== dependencies: "@types/estree" "0.0.39" @@ -1011,41 +1011,41 @@ "@types/estree@*": version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== "@types/estree@0.0.39": version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/node@*": version "18.7.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.18.tgz#633184f55c322e4fb08612307c274ee6d5ed3154" + resolved "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz" integrity sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg== "@types/resolve@1.17.1": version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz" integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== dependencies: "@types/node" "*" acorn@^8.5.0: version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" apache-unomi-tracker@^1.1.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/apache-unomi-tracker/-/apache-unomi-tracker-1.4.0.tgz#50707986531fc4f5dec28cdf06a18e48610bcb78" + resolved "https://registry.npmjs.org/apache-unomi-tracker/-/apache-unomi-tracker-1.4.0.tgz" integrity sha512-5mYm1GQDrzUNxYcQymmGYYkk7AKjGakI5T3wUH4apjiRzKwPMiMyRvc45HvYNmcCGZoPlP1AEcimVu+2t0M7PA== dependencies: "@babel/runtime" "^7.18.9" @@ -1053,19 +1053,19 @@ apache-unomi-tracker@^1.1.0: atob@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" babel-plugin-polyfill-corejs2@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz" integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== dependencies: "@babel/compat-data" "^7.17.7" @@ -1074,7 +1074,7 @@ babel-plugin-polyfill-corejs2@^0.3.3: babel-plugin-polyfill-corejs3@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz" integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" @@ -1082,19 +1082,19 @@ babel-plugin-polyfill-corejs3@^0.6.0: babel-plugin-polyfill-regenerator@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz" integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1102,7 +1102,7 @@ brace-expansion@^1.1.7: browserslist@^4.21.3, browserslist@^4.21.4: version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz" integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== dependencies: caniuse-lite "^1.0.30001400" @@ -1112,17 +1112,17 @@ browserslist@^4.21.3, browserslist@^4.21.4: buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== builtin-modules@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1130,12 +1130,12 @@ call-bind@^1.0.2: caniuse-lite@^1.0.30001400: version "1.0.30001407" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz#92281a6ee67cb90bfd8a6a1201fcc2dc19b60a15" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz" integrity sha512-4ydV+t4P7X3zH83fQWNDX/mQEzYomossfpViCOx9zHBSMV+rIe3LFqglHHtVyvNl1FhTNxPxs3jei82iqOW04w== chalk@^2.0.0: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1144,65 +1144,65 @@ chalk@^2.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== commander@^2.20.0: version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^1.7.0: version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" core-js-compat@^3.25.1: version "3.25.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.2.tgz#7875573586809909c69e03ef310810c1969ee138" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.2.tgz" integrity sha512-TxfyECD4smdn3/CjWxczVtJqVLEEC2up7/82t7vC0AzNogr+4nQ8vyF7abxAuTXWvjTClSbvGhU0RgqA4ToQaQ== dependencies: browserslist "^4.21.4" debug@^4.1.0, debug@^4.1.1: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== deepmerge@^4.2.2: version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== define-properties@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz" integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: has-property-descriptors "^1.0.0" @@ -1210,62 +1210,62 @@ define-properties@^1.1.4: electron-to-chromium@^1.4.251: version "1.4.255" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz#dc52d1095b876ed8acf25865db10265b02b1d6e1" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz" integrity sha512-H+mFNKow6gi2P5Gi2d1Fvd3TUEJlB9CF7zYaIV9T83BE3wP1xZ0mRPbNTm0KUjyd1QiVy7iKXuIcjlDtBQMiAQ== es6-crawler-detect@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/es6-crawler-detect/-/es6-crawler-detect-3.3.0.tgz#3a05cd3f2739099145bf40b012a6ad472cbbfb49" + resolved "https://registry.npmjs.org/es6-crawler-detect/-/es6-crawler-detect-3.3.0.tgz" integrity sha512-ptGU13H76+HNr5n0kvi5aO+RuqRHaIET/60Srv4+BgVWsuVVf3x9seDhz/IEcmuQMXJvrU2g+DbrKVrliUkTJQ== escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== estree-walker@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== estree-walker@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz" integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== dependencies: function-bind "^1.1.1" @@ -1274,7 +1274,7 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: glob@^7.1.6: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1286,41 +1286,41 @@ glob@^7.1.6: globals@^11.1.0: version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: get-intrinsic "^1.1.1" has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -1328,38 +1328,38 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== is-builtin-module@^3.1.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0" + resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz" integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw== dependencies: builtin-modules "^3.3.0" is-core-module@^2.9.0: version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz" integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== dependencies: has "^1.0.3" is-module@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== is-reference@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz" integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== dependencies: "@types/estree" "*" jest-worker@^26.2.1: version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: "@types/node" "*" @@ -1368,66 +1368,66 @@ jest-worker@^26.2.1: js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== json5@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== magic-string@^0.25.7: version "0.25.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz" integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== dependencies: sourcemap-codec "^1.4.8" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== minimatch@^3.1.1: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== node-releases@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.0: version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -1437,70 +1437,70 @@ object.assign@^4.1.0: once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== picocolors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.2.2: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" regenerate-unicode-properties@^10.1.0: version "10.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz" integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== dependencies: regenerate "^1.4.2" regenerate@^1.4.2: version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regenerator-runtime@^0.14.0: version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regenerator-transform@^0.15.0: version "0.15.0" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz" integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== dependencies: "@babel/runtime" "^7.8.4" regexpu-core@^5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz" integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ== dependencies: regenerate "^1.4.2" @@ -1512,19 +1512,19 @@ regexpu-core@^5.1.0: regjsgen@^0.7.1: version "0.7.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz" integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== regjsparser@^0.9.1: version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0: version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: is-core-module "^2.9.0" @@ -1533,14 +1533,14 @@ resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0: rollup-plugin-polyfill-node@^0.10.2: version "0.10.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.10.2.tgz#b2128646851fcb9475ddfd5bc22ca1a8c568738d" + resolved "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.10.2.tgz" integrity sha512-5GMywXiLiuQP6ZzED/LO/Q0HyDi2W6b8VN+Zd3oB0opIjyRs494Me2ZMaqKWDNbGiW4jvvzl6L2n4zRgxS9cSQ== dependencies: "@rollup/plugin-inject" "^4.0.0" rollup-plugin-sourcemaps@^0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz#bf93913ffe056e414419607f1d02780d7ece84ed" + resolved "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz" integrity sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw== dependencies: "@rollup/pluginutils" "^3.0.9" @@ -1548,7 +1548,7 @@ rollup-plugin-sourcemaps@^0.6.3: rollup-plugin-terser@^7.0.2: version "7.0.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" + resolved "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz" integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== dependencies: "@babel/code-frame" "^7.10.4" @@ -1558,36 +1558,36 @@ rollup-plugin-terser@^7.0.2: rollup@^2.79.0: version "2.79.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.0.tgz#9177992c9f09eb58c5e56cbfa641607a12b57ce2" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz" integrity sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA== optionalDependencies: fsevents "~2.3.2" safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== serialize-javascript@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz" integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: randombytes "^2.1.0" source-map-resolve@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz" integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== dependencies: atob "^2.1.2" @@ -1595,7 +1595,7 @@ source-map-resolve@^0.6.0: source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -1603,36 +1603,36 @@ source-map-support@~0.5.20: source-map@^0.6.0: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sourcemap-codec@^1.4.8: version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.0.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== terser@^5.0.0: version "5.15.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" + resolved "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz" integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== dependencies: "@jridgewell/source-map" "^0.3.2" @@ -1642,17 +1642,17 @@ terser@^5.0.0: to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: unicode-canonical-property-names-ecmascript "^2.0.0" @@ -1660,17 +1660,17 @@ unicode-match-property-ecmascript@^2.0.0: unicode-match-property-value-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== update-browserslist-db@^1.0.9: version "1.0.9" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz" integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg== dependencies: escalade "^3.1.1" @@ -1678,5 +1678,5 @@ update-browserslist-db@^1.0.9: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/DeleteProfilePropertiesCommand.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/DeleteProfilePropertiesCommand.java index ec63f6568..8234e3470 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/DeleteProfilePropertiesCommand.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/DeleteProfilePropertiesCommand.java @@ -29,7 +29,7 @@ public class DeleteProfilePropertiesCommand extends BaseCommand { - private static final Logger LOG = LoggerFactory.getLogger(DeleteProfilePropertiesCommand.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DeleteProfilePropertiesCommand.class); private final List propertyNames; @@ -58,12 +58,12 @@ public Boolean execute() { boolean deleted = profileService.deletePropertyType(propertyName); if (deleted) { - LOG.info("The property \"{}\" of profile was deleted successfully", propertyName); + LOGGER.info("The property \"{}\" of profile was deleted successfully", propertyName); } else { - LOG.info("The property \"{}\" of profile was not deleted", propertyName); + LOGGER.info("The property \"{}\" of profile was not deleted", propertyName); } } catch (Exception e) { - LOG.error("The delete property \"{}\" is failed", propertyName, e); + LOGGER.error("The delete property \"{}\" is failed", propertyName, e); } } diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java index fbd9208b1..e1a72ebb5 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/commands/ProcessEventsCommand.java @@ -40,7 +40,7 @@ public class ProcessEventsCommand extends BaseCommand { - private static final Logger LOG = LoggerFactory.getLogger(ProcessEventsCommand.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProcessEventsCommand.class.getName()); private static final List STATIC_FIELDS = new ArrayList<>(); @@ -104,10 +104,8 @@ private void processStaticFields( } } catch (Exception e) { - LOG.warn("Process field {} is failed. enable debug log to see the full stack trace", eventProcessor.getFieldName()); - if (LOG.isDebugEnabled()) { - LOG.debug("Process field failed", e); - } + LOGGER.warn("Process field {} is failed. enable debug log to see the full stack trace", eventProcessor.getFieldName()); + LOGGER.debug("Process field failed", e); } }); } @@ -118,10 +116,8 @@ private void processDynamicFields(final LinkedHashMap eventInput try { processField(fieldDefinition, eventInputAsMap); } catch (Exception e) { - LOG.warn("Process field {} is failed. enable debug log to see the full stack trace", fieldDefinition); - if (LOG.isDebugEnabled()) { - LOG.debug("Process field failed", e); - } + LOGGER.warn("Process field {} is failed. enable debug log to see the full stack trace", fieldDefinition); + LOGGER.debug("Process field failed", e); } } }); diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/BaseDataFetcher.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/BaseDataFetcher.java index c6c30bf5d..b9d70e4da 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/BaseDataFetcher.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/fetchers/BaseDataFetcher.java @@ -31,7 +31,7 @@ public abstract class BaseDataFetcher implements DataFetcher { - private static final Logger logger = LoggerFactory.getLogger(BaseDataFetcher.class); + private static final Logger LOGGER = LoggerFactory.getLogger(BaseDataFetcher.class); protected E parseObjectParam(String name, Class clazz, DataFetchingEnvironment environment) { final Object param = environment.getArgument(name); @@ -52,7 +52,7 @@ protected Date parseDateParam(final String name, final DataFetchingEnvironment e try { param = DateFormat.getInstance().parse(paramValue); } catch (ParseException e) { - logger.warn(String.format("Invalid date format for field '%s': %s", name, paramValue)); + LOGGER.warn("Invalid date format for field '{}': {}", name, paramValue); } } return param; diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java index a4b082d7d..f9d7a2d09 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/GraphQLSchemaProvider.java @@ -17,7 +17,6 @@ package org.apache.unomi.graphql.schema; import com.fasterxml.jackson.core.JsonProcessingException; -import com.networknt.schema.JsonSchema; import graphql.annotations.AnnotationsSchemaCreator; import graphql.annotations.processor.GraphQLAnnotations; import graphql.annotations.processor.ProcessingElementsContainer; @@ -89,7 +88,7 @@ public class GraphQLSchemaProvider { - private static final Logger logger = LoggerFactory.getLogger(GraphQLSchemaProvider.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GraphQLSchemaProvider.class.getName()); private final ProfileService profileService; @@ -165,7 +164,7 @@ public JSONTypeDefinitionType(String name, List jsonTypes) { if (firstNonNullType.isPresent()) { this.firstNonNullType = firstNonNullType.get(); } else { - logger.warn("Couldn't find non null type for {} and types {}", name, jsonTypes); + LOGGER.warn("Couldn't find non null type for {} and types {}", name, jsonTypes); } } @@ -543,7 +542,7 @@ private GraphQLInputObjectType createDynamicInputType(final String name, final boolean isEvent, Deque typeStack) { if (typeStack.contains(name)) { - logger.error("Loop detected when creating dynamic input types {} !" , typeStack); + LOGGER.error("Loop detected when creating dynamic input types {} !" , typeStack); return null; } typeStack.push(name); @@ -678,7 +677,7 @@ private void registerDynamicEventInputFields() { final String typeName = UnomiToGraphQLConverter.convertEventType(eventType.getName()); final GraphQLInputType eventInputType = (GraphQLInputType) getFromTypeRegistry(typeName + "Input"); if (eventInputType == null) { - logger.warn("Couldn't find event input type {}", typeName + "Input, will not add it as a field."); + LOGGER.warn("Couldn't find event input type {}Input, will not add it as a field.", typeName); return; } @@ -696,7 +695,7 @@ public static JSONSchema buildJSONSchema(JsonSchemaWrapper jsonSchemaWrapper, Sc try { schemaMap = GraphQLObjectMapper.getInstance().readValue(jsonSchemaWrapper.getSchema(), Map.class); } catch (JsonProcessingException e) { - logger.error("Failed to process Json object, e"); + LOGGER.error("Failed to process Json object", e); schemaMap = Collections.emptyMap(); } return new JSONSchema(schemaMap, new JSONTypeFactory(schemaService)); diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java index ca5770454..9a07165e4 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONObjectType.java @@ -25,7 +25,7 @@ public class JSONObjectType extends JSONType { - private static final Logger logger = LoggerFactory.getLogger(JSONTypeFactory.class); + private static final Logger LOGGER = LoggerFactory.getLogger(JSONTypeFactory.class); Map> properties = new HashMap<>(); JSONType additionalProperties; @@ -43,7 +43,7 @@ public JSONObjectType(Map schemaTree, JSONTypeFactory jsonTypeFa if (entry.getValue() instanceof Map) { properties.put(entry.getKey(), jsonTypeFactory.getTypes((Map) entry.getValue())); } else { - logger.error("Expected map type for property {}, instead found {}", entry.getKey(), entry.getValue().getClass()); + LOGGER.error("Expected map type for property {}, instead found {}", entry.getKey(), entry.getValue().getClass()); } }); } diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java index 04c5bb255..ff6bda733 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/schema/json/JSONTypeFactory.java @@ -31,7 +31,7 @@ public class JSONTypeFactory { - private static final Logger logger = LoggerFactory.getLogger(JSONTypeFactory.class); + private static final Logger LOGGER = LoggerFactory.getLogger(JSONTypeFactory.class); Map> jsonTypes = new HashMap<>(); @@ -96,7 +96,7 @@ List getTypes(Map schemaTree) { constructor = typeClass.getConstructor(Map.class, JSONTypeFactory.class); resultJsonTypes.add(constructor.newInstance(schemaTree, this)); } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException e) { - logger.error("Error while building object type", e); + LOGGER.error("Error while building object type", e); } } return resultJsonTypes; diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/ExecutionResultSubscriber.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/ExecutionResultSubscriber.java index 763453d24..426bc041e 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/ExecutionResultSubscriber.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/ExecutionResultSubscriber.java @@ -27,7 +27,7 @@ public class ExecutionResultSubscriber extends io.reactivex.subscribers.DefaultSubscriber { - private static final Logger logger = LoggerFactory.getLogger(ExecutionResultSubscriber.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionResultSubscriber.class); private final RemoteEndpoint remote; @@ -40,7 +40,7 @@ public ExecutionResultSubscriber(String id, RemoteEndpoint remote) { @Override public void onNext(ExecutionResult result) { - logger.debug("Subscriber sending data", result); + LOGGER.debug("Subscriber sending data {}", result); final GraphQLMessage message = GraphQLMessage.create(id) .data(result.getData()) @@ -56,13 +56,13 @@ private void sendMessage(GraphQLMessage message) { try { this.remote.sendString(message.toString()); } catch (IOException e) { - logger.warn("Subscriber failed to send data", e); + LOGGER.warn("Subscriber failed to send data", e); } } @Override public void onError(Throwable t) { - logger.error("Subscriber exception", t); + LOGGER.error("Subscriber exception", t); sendMessage(GraphQLMessage.create(id).errors(Collections.singletonList(t.getMessage())).build()); cancel(); @@ -70,7 +70,7 @@ public void onError(Throwable t) { @Override public void onComplete() { - logger.info("Subscriber complete"); + LOGGER.info("Subscriber complete"); sendMessage(GraphQLMessage.complete(id)); cancel(); diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/SubscriptionWebSocket.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/SubscriptionWebSocket.java index d99c16b28..5e20d0305 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/SubscriptionWebSocket.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/servlet/websocket/SubscriptionWebSocket.java @@ -33,7 +33,7 @@ import java.util.Map; public class SubscriptionWebSocket extends WebSocketAdapter { - private static final Logger logger = LoggerFactory.getLogger(SubscriptionWebSocket.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SubscriptionWebSocket.class); private GraphQL graphQL; @@ -48,19 +48,19 @@ public SubscriptionWebSocket(GraphQL graphQL, ServiceManager serviceManager) { @Override public void onWebSocketConnect(Session sess) { - logger.info("Opening web socket"); + LOGGER.info("Opening web socket"); super.onWebSocketConnect(sess); } @Override public void onWebSocketClose(int statusCode, String reason) { - logger.info("Closing web socket"); + LOGGER.info("Closing web socket"); super.onWebSocketClose(statusCode, reason); } @Override public void onWebSocketText(String textMessage) { - logger.info("Got web socket messages {}", textMessage); + LOGGER.info("Got web socket messages {}", textMessage); final GraphQLMessage message = GraphQLMessage.fromJson(textMessage); if (message == null) { return; @@ -91,7 +91,7 @@ private void sendMessage(GraphQLMessage message) { try { getRemote().sendString(message.toString()); } catch (IOException e) { - logger.error("Web socket error when sending a message", e); + LOGGER.error("Web socket error when sending a message", e); } } diff --git a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json deleted file mode 100644 index 01ea63303..000000000 --- a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "metadata": { - "id": "updateConsent", - "name": "Update profile/persona consents", - "description": "Update profile/persona consents", - "readOnly": true - }, - "condition": { - "type": "updateConsentEventCondition", - "parameterValues": { - } - }, - "actions": [ - { - "type": "updateConsentEventAction", - "parameterValues": { - } - } - ] -} diff --git a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json deleted file mode 100644 index b25d7d7c9..000000000 --- a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "metadata" : { - "id": "updateLists", - "name": "Update profile/persona lists", - "description" : "Update profile/persona lists", - "readOnly":true - }, - - "condition" : { - "type": "updateListsEventCondition", - "parameterValues": { - } - }, - - "actions" : [ - { - "type": "updateListsEventAction", - "parameterValues": { - - } - } - ] - -} diff --git a/graphql/graphql-playground/yarn.lock b/graphql/graphql-playground/yarn.lock index 51fc47ef4..88e26e3c6 100644 --- a/graphql/graphql-playground/yarn.lock +++ b/graphql/graphql-playground/yarn.lock @@ -4,19 +4,19 @@ "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== "@babel/core@^7.10.4": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz" integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" @@ -37,7 +37,7 @@ "@babel/generator@^7.12.10", "@babel/generator@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz" integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: "@babel/types" "^7.12.11" @@ -46,14 +46,14 @@ "@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz" integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== dependencies: "@babel/types" "^7.12.10" "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz" integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: "@babel/helper-explode-assignable-expression" "^7.10.4" @@ -61,7 +61,7 @@ "@babel/helper-compilation-targets@^7.12.5": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz" integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== dependencies: "@babel/compat-data" "^7.12.5" @@ -71,7 +71,7 @@ "@babel/helper-create-class-features-plugin@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz" integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -82,7 +82,7 @@ "@babel/helper-create-regexp-features-plugin@^7.12.1": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz" integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -90,7 +90,7 @@ "@babel/helper-define-map@^7.10.4": version "7.10.5" - resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz" integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -99,14 +99,14 @@ "@babel/helper-explode-assignable-expression@^7.10.4": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz" integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz" integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: "@babel/helper-get-function-arity" "^7.12.10" @@ -115,35 +115,35 @@ "@babel/helper-get-function-arity@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz" integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== dependencies: "@babel/types" "^7.12.10" "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz" integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== dependencies: "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz" integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== dependencies: "@babel/types" "^7.12.7" "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz" integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== dependencies: "@babel/types" "^7.12.5" "@babel/helper-module-transforms@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz" integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -158,19 +158,19 @@ "@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz" integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== dependencies: "@babel/types" "^7.12.10" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz" integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -179,7 +179,7 @@ "@babel/helper-replace-supers@^7.12.1": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz" integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== dependencies: "@babel/helper-member-expression-to-functions" "^7.12.7" @@ -189,38 +189,38 @@ "@babel/helper-simple-access@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz" integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-skip-transparent-expression-wrappers@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz" integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz" integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: "@babel/types" "^7.12.11" "@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz" integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== "@babel/helper-wrap-function@^7.10.4": version "7.12.3" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz" integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -230,7 +230,7 @@ "@babel/helpers@^7.12.5": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz" integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== dependencies: "@babel/template" "^7.10.4" @@ -239,7 +239,7 @@ "@babel/highlight@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" @@ -248,12 +248,12 @@ "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz" integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz" integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -262,7 +262,7 @@ "@babel/plugin-proposal-class-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz" integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" @@ -270,7 +270,7 @@ "@babel/plugin-proposal-dynamic-import@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz" integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -278,7 +278,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz" integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -286,7 +286,7 @@ "@babel/plugin-proposal-json-strings@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz" integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -294,7 +294,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz" integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -302,7 +302,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz" integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -310,7 +310,7 @@ "@babel/plugin-proposal-numeric-separator@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz" integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -318,7 +318,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -327,7 +327,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz" integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -335,7 +335,7 @@ "@babel/plugin-proposal-optional-chaining@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz" integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -344,7 +344,7 @@ "@babel/plugin-proposal-private-methods@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz" integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" @@ -352,7 +352,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz" integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -360,105 +360,105 @@ "@babel/plugin-syntax-async-generators@^7.8.0": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz" integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz" integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-arrow-functions@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz" integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-async-to-generator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz" integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -467,21 +467,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz" integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoping@^7.12.11": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz" integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-classes@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz" integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -495,21 +495,21 @@ "@babel/plugin-transform-computed-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz" integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-destructuring@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz" integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz" integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -517,14 +517,14 @@ "@babel/plugin-transform-duplicate-keys@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz" integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-exponentiation-operator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz" integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" @@ -532,14 +532,14 @@ "@babel/plugin-transform-for-of@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz" integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-function-name@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz" integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -547,21 +547,21 @@ "@babel/plugin-transform-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz" integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-member-expression-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz" integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-modules-amd@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz" integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -570,7 +570,7 @@ "@babel/plugin-transform-modules-commonjs@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz" integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -580,7 +580,7 @@ "@babel/plugin-transform-modules-systemjs@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz" integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== dependencies: "@babel/helper-hoist-variables" "^7.10.4" @@ -591,7 +591,7 @@ "@babel/plugin-transform-modules-umd@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz" integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -599,21 +599,21 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz" integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/plugin-transform-new-target@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz" integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-object-super@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz" integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -621,35 +621,35 @@ "@babel/plugin-transform-parameters@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz" integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-property-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz" integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-display-name@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz" integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-jsx-development@^7.12.7": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz" integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== dependencies: "@babel/plugin-transform-react-jsx" "^7.12.12" "@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz" integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== dependencies: "@babel/helper-annotate-as-pure" "^7.12.10" @@ -660,7 +660,7 @@ "@babel/plugin-transform-react-pure-annotations@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz" integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -668,28 +668,28 @@ "@babel/plugin-transform-regenerator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz" integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== dependencies: regenerator-transform "^0.14.2" "@babel/plugin-transform-reserved-words@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz" integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-shorthand-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz" integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-spread@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz" integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -697,35 +697,35 @@ "@babel/plugin-transform-sticky-regex@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz" integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-template-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz" integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typeof-symbol@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz" integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-escapes@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz" integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-regex@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz" integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -733,7 +733,7 @@ "@babel/preset-env@^7.10.4": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz" integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== dependencies: "@babel/compat-data" "^7.12.7" @@ -805,7 +805,7 @@ "@babel/preset-modules@^0.1.3": version "0.1.4" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz" integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -816,7 +816,7 @@ "@babel/preset-react@^7.10.4": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz" integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -827,14 +827,14 @@ "@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" "@babel/template@^7.10.4", "@babel/template@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz" integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" @@ -843,7 +843,7 @@ "@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz" integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== dependencies: "@babel/code-frame" "^7.12.11" @@ -858,7 +858,7 @@ "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz" integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: "@babel/helper-validator-identifier" "^7.12.11" @@ -867,24 +867,24 @@ "@emotion/is-prop-valid@^0.8.1": version "0.8.8" - resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz" integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== dependencies: "@emotion/memoize" "0.7.4" "@emotion/memoize@0.7.4": version "0.7.4" - resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== "@emotion/unitless@^0.7.0": version "0.7.5" - resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + resolved "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz" integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== "@redux-saga/core@^1.1.3": version "1.1.3" - resolved "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz#3085097b57a4ea8db5528d58673f20ce0950f6a4" + resolved "https://registry.npmjs.org/@redux-saga/core/-/core-1.1.3.tgz" integrity sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg== dependencies: "@babel/runtime" "^7.6.3" @@ -898,19 +898,19 @@ "@redux-saga/deferred@^1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz#59937a0eba71fff289f1310233bc518117a71888" + resolved "https://registry.npmjs.org/@redux-saga/deferred/-/deferred-1.1.2.tgz" integrity sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ== "@redux-saga/delay-p@^1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz#8f515f4b009b05b02a37a7c3d0ca9ddc157bb355" + resolved "https://registry.npmjs.org/@redux-saga/delay-p/-/delay-p-1.1.2.tgz" integrity sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g== dependencies: "@redux-saga/symbols" "^1.1.2" "@redux-saga/is@^1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz#ae6c8421f58fcba80faf7cadb7d65b303b97e58e" + resolved "https://registry.npmjs.org/@redux-saga/is/-/is-1.1.2.tgz" integrity sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w== dependencies: "@redux-saga/symbols" "^1.1.2" @@ -918,27 +918,27 @@ "@redux-saga/symbols@^1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz#216a672a487fc256872b8034835afc22a2d0595d" + resolved "https://registry.npmjs.org/@redux-saga/symbols/-/symbols-1.1.2.tgz" integrity sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ== "@redux-saga/types@^1.1.0": version "1.1.0" - resolved "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz#0e81ce56b4883b4b2a3001ebe1ab298b84237204" + resolved "https://registry.npmjs.org/@redux-saga/types/-/types-1.1.0.tgz" integrity sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg== "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.7" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== "@types/lru-cache@^4.1.1": version "4.1.2" - resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.2.tgz#528ba392658055dba78fc3be906ca338a1a2d1c5" + resolved "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-4.1.2.tgz" integrity sha512-ve2IoUJClE+4S/sG2zoLGEHP6DCvqgyz7UkHZdiICdQaAYRaCXsRWfJlbL8B0KvUyo9lgzD+oR0YSy4YikFyFQ== "@webassemblyjs/ast@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz" integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== dependencies: "@webassemblyjs/helper-module-context" "1.9.0" @@ -947,46 +947,46 @@ "@webassemblyjs/floating-point-hex-parser@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz" integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== "@webassemblyjs/helper-api-error@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz" integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== "@webassemblyjs/helper-buffer@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz" integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== "@webassemblyjs/helper-code-frame@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz" integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== dependencies: "@webassemblyjs/wast-printer" "1.9.0" "@webassemblyjs/helper-fsm@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz" integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== "@webassemblyjs/helper-module-context@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz" integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== dependencies: "@webassemblyjs/ast" "1.9.0" "@webassemblyjs/helper-wasm-bytecode@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz" integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== "@webassemblyjs/helper-wasm-section@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz" integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -996,26 +996,26 @@ "@webassemblyjs/ieee754@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz" integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz" integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz" integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== "@webassemblyjs/wasm-edit@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz" integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -1029,7 +1029,7 @@ "@webassemblyjs/wasm-gen@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz" integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -1040,7 +1040,7 @@ "@webassemblyjs/wasm-opt@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz" integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -1050,7 +1050,7 @@ "@webassemblyjs/wasm-parser@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz" integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -1062,7 +1062,7 @@ "@webassemblyjs/wast-parser@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz" integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -1074,7 +1074,7 @@ "@webassemblyjs/wast-printer@1.9.0": version "1.9.0" - resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz" integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -1083,24 +1083,24 @@ "@wry/equality@^0.1.2": version "0.1.11" - resolved "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz#35cb156e4a96695aa81a9ecc4d03787bc17f1790" + resolved "https://registry.npmjs.org/@wry/equality/-/equality-0.1.11.tgz" integrity sha512-mwEVBDUVODlsQQ5dfuLUS5/Tf7jqUKyhKYHmVi4fPB6bDMOfWvUPJmKgS1Z7Za/sOI3vzWt4+O7yCiL/70MogA== dependencies: tslib "^1.9.3" "@xtuc/ieee754@^1.2.0": version "1.2.0" - resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.2": version "4.2.2" - resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== accepts@~1.3.7: version "1.3.7" - resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + resolved "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== dependencies: mime-types "~2.1.24" @@ -1108,32 +1108,32 @@ accepts@~1.3.7: acorn-walk@^7.1.1: version "7.2.0" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== acorn@^6.4.1: version "6.4.2" - resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" + resolved "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== acorn@^7.1.1: version "7.4.1" - resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + resolved "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== ajv-errors@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + resolved "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz" integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -1148,14 +1148,14 @@ ansi-regex@4.1.1, ansi-regex@^4.1.0: ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" anymatch@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz" integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" @@ -1163,7 +1163,7 @@ anymatch@^2.0.0: anymatch@~3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz" integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== dependencies: normalize-path "^3.0.0" @@ -1171,7 +1171,7 @@ anymatch@~3.1.1: apollo-link-http-common@^0.2.16: version "0.2.16" - resolved "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz#756749dafc732792c8ca0923f9a40564b7c59ecc" + resolved "https://registry.npmjs.org/apollo-link-http-common/-/apollo-link-http-common-0.2.16.tgz" integrity sha512-2tIhOIrnaF4UbQHf7kjeQA/EmSorB7+HyJIIrUjJOKBgnXwuexi8aMecRlqTIDWcyVXCeqLhUnztMa6bOH/jTg== dependencies: apollo-link "^1.2.14" @@ -1180,7 +1180,7 @@ apollo-link-http-common@^0.2.16: apollo-link-http@^1.5.16: version "1.5.17" - resolved "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.17.tgz#499e9f1711bf694497f02c51af12d82de5d8d8ba" + resolved "https://registry.npmjs.org/apollo-link-http/-/apollo-link-http-1.5.17.tgz" integrity sha512-uWcqAotbwDEU/9+Dm9e1/clO7hTB2kQ/94JYcGouBVLjoKmTeJTUPQKcJGpPwUjZcSqgYicbFqQSoJIW0yrFvg== dependencies: apollo-link "^1.2.14" @@ -1189,7 +1189,7 @@ apollo-link-http@^1.5.16: apollo-link-ws@^1.0.19: version "1.0.20" - resolved "https://registry.npmjs.org/apollo-link-ws/-/apollo-link-ws-1.0.20.tgz#dfad44121f8445c6d7b7f8101a1b24813ba008ed" + resolved "https://registry.npmjs.org/apollo-link-ws/-/apollo-link-ws-1.0.20.tgz" integrity sha512-mjSFPlQxmoLArpHBeUb2Xj+2HDYeTaJqFGOqQ+I8NVJxgL9lJe84PDWcPah/yMLv3rB7QgBDSuZ0xoRFBPlySw== dependencies: apollo-link "^1.2.14" @@ -1197,7 +1197,7 @@ apollo-link-ws@^1.0.19: apollo-link@^1.2.13, apollo-link@^1.2.14: version "1.2.14" - resolved "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz#3feda4b47f9ebba7f4160bef8b977ba725b684d9" + resolved "https://registry.npmjs.org/apollo-link/-/apollo-link-1.2.14.tgz" integrity sha512-p67CMEFP7kOG1JZ0ZkYZwRDa369w5PIjtMjvrQd/HnIV8FRsHRqLqK+oAZQnFa1DDdZtOtHTi+aMIW6EatC2jg== dependencies: apollo-utilities "^1.3.0" @@ -1207,7 +1207,7 @@ apollo-link@^1.2.13, apollo-link@^1.2.14: apollo-utilities@^1.3.0: version "1.3.4" - resolved "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz#6129e438e8be201b6c55b0f13ce49d2c7175c9cf" + resolved "https://registry.npmjs.org/apollo-utilities/-/apollo-utilities-1.3.4.tgz" integrity sha512-pk2hiWrCXMAy2fRPwEyhvka+mqwzeP60Jr1tRYi5xru+3ko94HI9o6lK0CT33/w4RDlxWchmdhDCrvdr+pHCig== dependencies: "@wry/equality" "^0.1.2" @@ -1217,44 +1217,44 @@ apollo-utilities@^1.3.0: aproba@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + resolved "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== argparse@^1.0.7: version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" arr-diff@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + resolved "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz" integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + resolved "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== arr-union@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + resolved "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-flatten@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + resolved "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= array-unique@^0.3.2: version "0.3.2" - resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + resolved "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= asn1.js@^5.2.0: version "5.4.1" - resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + resolved "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz" integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" @@ -1264,7 +1264,7 @@ asn1.js@^5.2.0: assert@^1.1.1: version "1.5.0" - resolved "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + resolved "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz" integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== dependencies: object-assign "^4.1.1" @@ -1272,27 +1272,27 @@ assert@^1.1.1: assign-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + resolved "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= async-each@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + resolved "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== async-limiter@~1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + resolved "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== atob@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== babel-loader@^8.1.0: version "8.2.2" - resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz" integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== dependencies: find-cache-dir "^3.3.1" @@ -1302,14 +1302,14 @@ babel-loader@^8.1.0: babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" "babel-plugin-styled-components@>= 1": version "1.12.0" - resolved "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz#1dec1676512177de6b827211e9eda5a30db4f9b9" + resolved "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz" integrity sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA== dependencies: "@babel/helper-annotate-as-pure" "^7.0.0" @@ -1319,12 +1319,12 @@ babel-plugin-dynamic-import-node@^2.3.3: babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" - resolved "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + resolved "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz" integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= babel-runtime@^6.11.6: version "6.26.0" - resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz" integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= dependencies: core-js "^2.4.0" @@ -1332,22 +1332,22 @@ babel-runtime@^6.11.6: backo2@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + resolved "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz" integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= balanced-match@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base64-js@^1.0.2: version "1.5.1" - resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== base@^0.11.1: version "0.11.2" - resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + resolved "https://registry.npmjs.org/base/-/base-0.11.2.tgz" integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" @@ -1360,7 +1360,7 @@ base@^0.11.1: bfj@^6.1.1: version "6.1.2" - resolved "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" + resolved "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz" integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== dependencies: bluebird "^3.5.5" @@ -1370,44 +1370,44 @@ bfj@^6.1.1: big.js@^5.2.2: version "5.2.2" - resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^1.0.0: version "1.13.1" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== bindings@^1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + resolved "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== dependencies: file-uri-to-path "1.0.0" bluebird@^3.5.5: version "3.7.2" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: version "4.11.9" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== bn.js@^5.0.0, bn.js@^5.1.1: version "5.1.3" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" + resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== body-parser@1.19.0: version "1.19.0" - resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + resolved "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz" integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== dependencies: bytes "3.1.0" @@ -1423,14 +1423,14 @@ body-parser@1.19.0: boom@7.x.x: version "7.3.0" - resolved "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz#733a6d956d33b0b1999da3fe6c12996950d017b9" + resolved "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz" integrity sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A== dependencies: hoek "6.x.x" brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1438,7 +1438,7 @@ brace-expansion@^1.1.7: braces@^2.3.1, braces@^2.3.2: version "2.3.2" - resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + resolved "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" @@ -1454,24 +1454,24 @@ braces@^2.3.1, braces@^2.3.2: braces@~3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" brorand@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-fingerprint@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/browser-fingerprint/-/browser-fingerprint-0.0.1.tgz#8df3cdca25bf7d5b3542d61545d730053fce604a" + resolved "https://registry.npmjs.org/browser-fingerprint/-/browser-fingerprint-0.0.1.tgz" integrity sha1-jfPNyiW/fVs1QtYVRdcwBT/OYEo= browserify-aes@^1.0.0, browserify-aes@^1.0.4: version "1.2.0" - resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + resolved "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== dependencies: buffer-xor "^1.0.3" @@ -1483,7 +1483,7 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: browserify-cipher@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + resolved "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz" integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== dependencies: browserify-aes "^1.0.4" @@ -1492,7 +1492,7 @@ browserify-cipher@^1.0.0: browserify-des@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + resolved "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz" integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== dependencies: cipher-base "^1.0.1" @@ -1502,7 +1502,7 @@ browserify-des@^1.0.0: browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: version "4.1.0" - resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + resolved "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz" integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== dependencies: bn.js "^5.0.0" @@ -1510,7 +1510,7 @@ browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: browserify-sign@^4.0.0: version "4.2.1" - resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + resolved "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz" integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== dependencies: bn.js "^5.1.1" @@ -1525,14 +1525,14 @@ browserify-sign@^4.0.0: browserify-zlib@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + resolved "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz" integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== dependencies: pako "~1.0.5" browserslist@^4.14.5, browserslist@^4.16.1: version "4.16.3" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz" integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== dependencies: caniuse-lite "^1.0.30001181" @@ -1543,17 +1543,17 @@ browserslist@^4.14.5, browserslist@^4.16.1: buffer-from@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-xor@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + resolved "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= buffer@^4.3.0: version "4.9.2" - resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + resolved "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz" integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== dependencies: base64-js "^1.0.2" @@ -1562,17 +1562,17 @@ buffer@^4.3.0: builtin-status-codes@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + resolved "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= bytes@3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== cacache@^12.0.2: version "12.0.4" - resolved "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + resolved "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz" integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== dependencies: bluebird "^3.5.5" @@ -1593,7 +1593,7 @@ cacache@^12.0.2: cache-base@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + resolved "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz" integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" @@ -1608,12 +1608,12 @@ cache-base@^1.0.1: calculate-size@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/calculate-size/-/calculate-size-1.1.1.tgz#ae7caa1c7795f82c4f035dc7be270e3581dae3ee" + resolved "https://registry.npmjs.org/calculate-size/-/calculate-size-1.1.1.tgz" integrity sha1-rnyqHHeV+CxPA13HvicONYHa4+4= call-bind@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1621,22 +1621,22 @@ call-bind@^1.0.0: camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== camelize@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" + resolved "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= caniuse-lite@^1.0.30001181: version "1.0.30001183" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz#7a57ba9d6584119bb5f2bc76d3cc47ba9356b3e2" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz" integrity sha512-7JkwTEE1hlRKETbCFd8HDZeLiQIUcl8rC6JgNjvHCNaxOeNmQ9V4LvQXRUsKIV2CC73qKxljwVhToaA3kLRqTw== chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1645,12 +1645,12 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: check-types@^8.0.3: version "8.0.3" - resolved "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" + resolved "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz" integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== chokidar@^2.1.8: version "2.1.8" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz" integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== dependencies: anymatch "^2.0.0" @@ -1669,7 +1669,7 @@ chokidar@^2.1.8: chokidar@^3.4.1: version "3.5.1" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== dependencies: anymatch "~3.1.1" @@ -1684,19 +1684,19 @@ chokidar@^3.4.1: chownr@^1.1.1: version "1.1.4" - resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + resolved "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chrome-trace-event@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz" integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== dependencies: tslib "^1.9.0" cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + resolved "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz" integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== dependencies: inherits "^2.0.1" @@ -1704,7 +1704,7 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: class-utils@^0.3.5: version "0.3.6" - resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + resolved "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz" integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" @@ -1714,12 +1714,12 @@ class-utils@^0.3.5: classnames@^2.2.5: version "2.2.6" - resolved "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + resolved "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== cliui@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + resolved "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz" integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: string-width "^3.1.0" @@ -1728,12 +1728,12 @@ cliui@^5.0.0: clsx@^1.0.4: version "1.1.1" - resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" + resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz" integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== codemirror-graphql@^0.11.6: version "0.11.6" - resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-0.11.6.tgz#885e34afb5b7aacf0e328d4d5949e73ad21d5a4e" + resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-0.11.6.tgz" integrity sha512-/zVKgOVS2/hfjAY0yoBkLz9ESHnWKBWpBNXQSoFF4Hl5q5AS2DmM22coonWKJcCvNry6TLak2F+QkzPeKVv3Eg== dependencies: graphql-language-service-interface "^2.3.3" @@ -1741,7 +1741,7 @@ codemirror-graphql@^0.11.6: codemirror-graphql@^0.12.3: version "0.12.4" - resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-0.12.4.tgz#607e113035856a179ee019e8451210cd1a8ca340" + resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-0.12.4.tgz" integrity sha512-gWxmLk2OzPVzvwAXO0K52MtU1n6ylMNbKp0LtZHioK0NEUwLnSL5iPKVXn8MgvYqS8Yos/CG5WrP9Y7RWTO4mg== dependencies: graphql-language-service-interface "^2.4.3" @@ -1749,12 +1749,12 @@ codemirror-graphql@^0.12.3: codemirror@^5.18.2, codemirror@^5.47.0, codemirror@^5.58.1: version "5.59.2" - resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.59.2.tgz#ee674d3a4a8d241af38d52afc482625ba7393922" + resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.59.2.tgz" integrity sha512-/D5PcsKyzthtSy2NNKCyJi3b+htRkoKv3idswR/tR6UAvMNKA7SrmyZy6fOONJxSRs1JlUWEDAbxqfdArbK8iA== collection-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + resolved "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz" integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" @@ -1762,44 +1762,44 @@ collection-visit@^1.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colorette@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz" integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== commander@^2.18.0, commander@^2.20.0: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= component-emitter@^1.2.1: version "1.3.0" - resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + resolved "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@^1.5.0: version "1.6.2" - resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" @@ -1809,46 +1809,46 @@ concat-stream@^1.5.0: console-browserify@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + resolved "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== constants-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + resolved "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz" integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= content-disposition@0.5.3: version "0.5.3" - resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + resolved "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== dependencies: safe-buffer "5.1.2" content-type@~1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + resolved "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" cookie-signature@1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= cookie@0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz" integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== copy-concurrently@^1.0.0: version "1.0.5" - resolved "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + resolved "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz" integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== dependencies: aproba "^1.1.1" @@ -1860,19 +1860,19 @@ copy-concurrently@^1.0.0: copy-descriptor@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + resolved "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-to-clipboard@^3, copy-to-clipboard@^3.0.8, copy-to-clipboard@^3.2.0: version "3.3.1" - resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" + resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz" integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== dependencies: toggle-selection "^1.0.6" core-js-compat@^3.8.0: version "3.8.3" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz" integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== dependencies: browserslist "^4.16.1" @@ -1880,22 +1880,22 @@ core-js-compat@^3.8.0: core-js@^1.1.1: version "1.2.7" - resolved "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + resolved "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= core-js@^2.4.0: version "2.6.12" - resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" + resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-util-is@~1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= create-ecdh@^4.0.0: version "4.0.4" - resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + resolved "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz" integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== dependencies: bn.js "^4.1.0" @@ -1903,7 +1903,7 @@ create-ecdh@^4.0.0: create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz" integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== dependencies: cipher-base "^1.0.1" @@ -1914,7 +1914,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" - resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + resolved "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== dependencies: cipher-base "^1.0.3" @@ -1926,7 +1926,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: create-react-class@^15.5.1: version "15.7.0" - resolved "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e" + resolved "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz" integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng== dependencies: loose-envify "^1.3.1" @@ -1934,7 +1934,7 @@ create-react-class@^15.5.1: cross-spawn@^6.0.5: version "6.0.5" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" @@ -1945,14 +1945,14 @@ cross-spawn@^6.0.5: cryptiles@4.1.2: version "4.1.2" - resolved "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.2.tgz#363c9ab5c859da9d2d6fb901b64d980966181184" + resolved "https://registry.npmjs.org/cryptiles/-/cryptiles-4.1.2.tgz" integrity sha512-U2ALcoAHvA1oO2xOreyHvtkQ+IELqDG2WVWRI1GH/XEmmfGIOalnM5MU5Dd2ITyWfr3m6kNqXiy8XuYyd4wKJw== dependencies: boom "7.x.x" crypto-browserify@^3.11.0: version "3.12.0" - resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + resolved "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz" integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== dependencies: browserify-cipher "^1.0.0" @@ -1969,12 +1969,12 @@ crypto-browserify@^3.11.0: css-color-keywords@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + resolved "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz" integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU= css-loader@^3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz" integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== dependencies: camelcase "^5.3.1" @@ -1993,7 +1993,7 @@ css-loader@^3.6.0: css-to-react-native@^2.2.2: version "2.3.2" - resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz#e75e2f8f7aa385b4c3611c52b074b70a002f2e7d" + resolved "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.2.tgz" integrity sha512-VOFaeZA053BqvvvqIA8c9n0+9vFppVBAHCp6JgFTtTMU3Mzi+XnelJ9XC9ul3BqFzZyQ5N+H0SnwsWT2Ebchxw== dependencies: camelize "^1.0.0" @@ -2002,17 +2002,17 @@ css-to-react-native@^2.2.2: cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== csstype@^3.0.2: version "3.0.6" - resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz#865d0b5833d7d8d40f4e5b8a6d76aea3de4725ef" + resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz" integrity sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw== cuid@^1.3.8: version "1.3.8" - resolved "https://registry.npmjs.org/cuid/-/cuid-1.3.8.tgz#4b875e0969bad764f7ec0706cf44f5fb0831f6b7" + resolved "https://registry.npmjs.org/cuid/-/cuid-1.3.8.tgz" integrity sha1-S4deCWm612T37AcGz0T1+wgx9rc= dependencies: browser-fingerprint "0.0.1" @@ -2021,57 +2021,57 @@ cuid@^1.3.8: cyclist@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" debug@^4.1.0: version "4.3.1" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" decamelize@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= define-properties@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" define-property@^0.2.5: version "0.2.5" - resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + resolved "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz" integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + resolved "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz" integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + resolved "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz" integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" @@ -2079,12 +2079,12 @@ define-property@^2.0.2: depd@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= des.js@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + resolved "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz" integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== dependencies: inherits "^2.0.1" @@ -2092,17 +2092,17 @@ des.js@^1.0.0: destroy@~1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + resolved "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= detect-file@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + resolved "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= diffie-hellman@^5.0.0: version "5.0.3" - resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + resolved "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz" integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== dependencies: bn.js "^4.1.0" @@ -2111,14 +2111,14 @@ diffie-hellman@^5.0.0: dom-helpers@^3.4.0: version "3.4.0" - resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" + resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz" integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== dependencies: "@babel/runtime" "^7.1.2" dom-helpers@^5.1.3: version "5.2.0" - resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" + resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz" integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== dependencies: "@babel/runtime" "^7.8.7" @@ -2126,17 +2126,17 @@ dom-helpers@^5.1.3: domain-browser@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + resolved "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz" integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== duplexer@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + resolved "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" - resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + resolved "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz" integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== dependencies: end-of-stream "^1.0.0" @@ -2146,22 +2146,22 @@ duplexify@^3.4.2, duplexify@^3.6.0: ee-first@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + resolved "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= ejs@^2.6.1: version "2.7.4" - resolved "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + resolved "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== electron-to-chromium@^1.3.649: version "1.3.650" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.650.tgz#24e821fff2ed61fd71fee092f2a0631b3c0c22a6" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.650.tgz" integrity sha512-j6pRuNylFBbroG6NB8Lw/Im9oDY74s2zWHBP5TmdYg73cBuL6cz//SMgolVa0gIJk/DSL+kO7baJ1DSXW1FUZg== elliptic@^6.5.3: version "6.5.3" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" + resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz" integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== dependencies: bn.js "^4.4.0" @@ -2174,36 +2174,36 @@ elliptic@^6.5.3: emoji-regex@^7.0.1: version "7.0.3" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== emojis-list@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== encodeurl@~1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + resolved "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= encoding@^0.1.11: version "0.1.13" - resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + resolved "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: iconv-lite "^0.6.2" end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" - resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + resolved "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz" integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== dependencies: once "^1.4.0" enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz#2f3cfd84dbe3b487f18f2db2ef1e064a571ca5ec" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz" integrity sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg== dependencies: graceful-fs "^4.1.2" @@ -2212,44 +2212,44 @@ enhanced-resolve@^4.1.1, enhanced-resolve@^4.5.0: entities@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" + resolved "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== entities@~1.1.1: version "1.1.2" - resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + resolved "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== entities@~2.0.0: version "2.0.3" - resolved "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" + resolved "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz" integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== errno@^0.1.3, errno@~0.1.7: version "0.1.8" - resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-html@~1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= eslint-scope@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz" integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" @@ -2257,49 +2257,49 @@ eslint-scope@^4.0.3: esprima@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esrecurse@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== etag@~1.8.1: version "1.8.1" - resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= eventemitter3@^3.1.0: version "3.1.2" - resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + resolved "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz" integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== events@^3.0.0: version "3.2.0" - resolved "https://registry.npmjs.org/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" + resolved "https://registry.npmjs.org/events/-/events-3.2.0.tgz" integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz" integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== dependencies: md5.js "^1.3.4" @@ -2307,12 +2307,12 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: exenv@^1.2.0: version "1.2.2" - resolved "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" + resolved "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz" integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50= expand-brackets@^2.1.4: version "2.1.4" - resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + resolved "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz" integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" @@ -2325,14 +2325,14 @@ expand-brackets@^2.1.4: expand-tilde@^2.0.0, expand-tilde@^2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + resolved "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz" integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= dependencies: homedir-polyfill "^1.0.1" express@^4.16.3: version "4.17.1" - resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + resolved "https://registry.npmjs.org/express/-/express-4.17.1.tgz" integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== dependencies: accepts "~1.3.7" @@ -2368,14 +2368,14 @@ express@^4.16.3: extend-shallow@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz" integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + resolved "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz" integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" @@ -2383,7 +2383,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: extglob@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + resolved "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" @@ -2397,22 +2397,22 @@ extglob@^2.0.4: fast-deep-equal@^3.1.1: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== figgy-pudding@^3.5.1: version "3.5.2" - resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + resolved "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz" integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== file-loader@^6.0.0: version "6.2.0" - resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== dependencies: loader-utils "^2.0.0" @@ -2420,17 +2420,17 @@ file-loader@^6.0.0: file-uri-to-path@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + resolved "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== filesize@^3.6.1: version "3.6.1" - resolved "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + resolved "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz" integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== fill-range@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz" integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" @@ -2440,14 +2440,14 @@ fill-range@^4.0.0: fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" finalhandler@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + resolved "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz" integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== dependencies: debug "2.6.9" @@ -2460,7 +2460,7 @@ finalhandler@~1.1.2: find-cache-dir@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz" integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== dependencies: commondir "^1.0.1" @@ -2469,7 +2469,7 @@ find-cache-dir@^2.1.0: find-cache-dir@^3.3.1: version "3.3.1" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" @@ -2478,14 +2478,14 @@ find-cache-dir@^3.3.1: find-up@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" find-up@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -2493,7 +2493,7 @@ find-up@^4.0.0: findup-sync@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + resolved "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz" integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== dependencies: detect-file "^1.0.0" @@ -2503,7 +2503,7 @@ findup-sync@^3.0.0: flush-write-stream@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + resolved "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz" integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== dependencies: inherits "^2.0.3" @@ -2511,29 +2511,29 @@ flush-write-stream@^1.0.0: for-in@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + resolved "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= forwarded@~0.1.2: version "0.1.2" - resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + resolved "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz" integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= fragment-cache@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + resolved "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz" integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" fresh@0.5.2: version "0.5.2" - resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + resolved "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= from2@^2.1.0: version "2.3.0" - resolved "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + resolved "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz" integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= dependencies: inherits "^2.0.1" @@ -2541,7 +2541,7 @@ from2@^2.1.0: fs-write-stream-atomic@^1.0.8: version "1.0.10" - resolved "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + resolved "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz" integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= dependencies: graceful-fs "^4.1.2" @@ -2551,12 +2551,12 @@ fs-write-stream-atomic@^1.0.8: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.7: version "1.2.13" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz" integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== dependencies: bindings "^1.5.0" @@ -2564,27 +2564,27 @@ fsevents@^1.2.7: fsevents@~2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz#b209ab14c61012636c8863507edf7fb68cc54e9f" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz" integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== gensync@^1.0.0-beta.1: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^2.0.1: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-intrinsic@^1.0.2: version "1.1.0" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz#892e62931e6938c8a23ea5aaebcfb67bd97da97e" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz" integrity sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg== dependencies: function-bind "^1.1.1" @@ -2593,12 +2593,12 @@ get-intrinsic@^1.0.2: get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + resolved "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= glob-parent@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz" integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" @@ -2606,14 +2606,14 @@ glob-parent@^3.1.0: glob-parent@~5.1.0: version "5.1.1" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" glob@^7.1.3, glob@^7.1.4: version "7.1.6" - resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" @@ -2625,7 +2625,7 @@ glob@^7.1.3, glob@^7.1.4: global-modules@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + resolved "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz" integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== dependencies: global-prefix "^1.0.1" @@ -2634,14 +2634,14 @@ global-modules@^1.0.0: global-modules@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + resolved "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz" integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== dependencies: global-prefix "^3.0.0" global-prefix@^1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz" integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= dependencies: expand-tilde "^2.0.2" @@ -2652,7 +2652,7 @@ global-prefix@^1.0.1: global-prefix@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + resolved "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz" integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== dependencies: ini "^1.3.5" @@ -2661,17 +2661,17 @@ global-prefix@^3.0.0: globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2: version "4.2.4" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== graphiql@^0.17.5: version "0.17.5" - resolved "https://registry.npmjs.org/graphiql/-/graphiql-0.17.5.tgz#76c553fc0d8936f77e33114ac3374f1807a718ff" + resolved "https://registry.npmjs.org/graphiql/-/graphiql-0.17.5.tgz" integrity sha512-ogNsrg9qM1py9PzcIUn+C29JukOADbjIfB6zwtfui4BrpOEpDb5UZ6TjAmSL/F/8tCt4TbgwKtkSrBeLNNUrqA== dependencies: codemirror "^5.47.0" @@ -2683,7 +2683,7 @@ graphiql@^0.17.5: graphql-language-service-interface@^2.3.3, graphql-language-service-interface@^2.4.3: version "2.8.2" - resolved "https://registry.npmjs.org/graphql-language-service-interface/-/graphql-language-service-interface-2.8.2.tgz#b3bb2aef7eaf0dff0b4ea419fa412c5f66fa268b" + resolved "https://registry.npmjs.org/graphql-language-service-interface/-/graphql-language-service-interface-2.8.2.tgz" integrity sha512-otbOQmhgkAJU1QJgQkMztNku6SbJLu/uodoFOYOOtJsizTjrMs93vkYaHCcYnLA3oi1Goj27XcHjMnRCYQOZXQ== dependencies: graphql-language-service-parser "^1.9.0" @@ -2693,19 +2693,19 @@ graphql-language-service-interface@^2.3.3, graphql-language-service-interface@^2 graphql-language-service-parser@^1.5.2, graphql-language-service-parser@^1.6.5, graphql-language-service-parser@^1.9.0: version "1.9.0" - resolved "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.0.tgz#79af21294119a0a7e81b6b994a1af36833bab724" + resolved "https://registry.npmjs.org/graphql-language-service-parser/-/graphql-language-service-parser-1.9.0.tgz" integrity sha512-B5xPZLbBmIp0kHvpY1Z35I5DtPoDK9wGxQVRDIzcBaiIvAmlTrDvjo3bu7vKREdjFbYKvWNgrEWENuprMbF17Q== dependencies: graphql-language-service-types "^1.8.0" graphql-language-service-types@^1.8.0: version "1.8.1" - resolved "https://registry.npmjs.org/graphql-language-service-types/-/graphql-language-service-types-1.8.1.tgz#963810010924f2b5eaea415d5b8eb0b7d42c479b" + resolved "https://registry.npmjs.org/graphql-language-service-types/-/graphql-language-service-types-1.8.1.tgz" integrity sha512-IpYS0mEHEmRsFlq+loWCpSYYYizAID7Alri6GoFN1QqUdux+8rp1Tkp2NGsGDpDmm3Dbz5ojmJWzNWQGpuwveA== graphql-language-service-utils@^2.5.1: version "2.5.1" - resolved "https://registry.npmjs.org/graphql-language-service-utils/-/graphql-language-service-utils-2.5.1.tgz#832ad4b0a9da03fdded756932c27e057ccf71302" + resolved "https://registry.npmjs.org/graphql-language-service-utils/-/graphql-language-service-utils-2.5.1.tgz" integrity sha512-Lzz723cYrYlVN4WVzIyFGg3ogoe+QYAIBfdtDboiIILoy0FTmqbyC2TOErqbmWKqO4NK9xDA95cSRFbWiHYj0g== dependencies: graphql-language-service-types "^1.8.0" @@ -2713,7 +2713,7 @@ graphql-language-service-utils@^2.5.1: graphql-playground-react@^1.7.27: version "1.7.27" - resolved "https://registry.npmjs.org/graphql-playground-react/-/graphql-playground-react-1.7.27.tgz#0d0e2c14a9a1fe3583917c9eb2cecc22b9e342e4" + resolved "https://registry.npmjs.org/graphql-playground-react/-/graphql-playground-react-1.7.27.tgz" integrity sha512-LGSfAHzedAFFn36yYZzPdw58YAvE05qUEjWZUqqu4nvg4M019zhGIYPvZF612j43CU/Cuk2wjxxjzfbHqx8YVQ== dependencies: "@types/lru-cache" "^4.1.1" @@ -2771,12 +2771,12 @@ graphql-playground-react@^1.7.27: graphql@^15.2.0, graphql@^15.3.0: version "15.5.0" - resolved "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5" + resolved "https://registry.npmjs.org/graphql/-/graphql-15.5.0.tgz" integrity sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA== gzip-size@^5.0.0: version "5.1.1" - resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + resolved "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz" integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== dependencies: duplexer "^0.1.1" @@ -2784,17 +2784,17 @@ gzip-size@^5.0.0: has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbols@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has-value@^0.3.1: version "0.3.1" - resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + resolved "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz" integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" @@ -2803,7 +2803,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + resolved "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz" integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" @@ -2812,12 +2812,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + resolved "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz" integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + resolved "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz" integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" @@ -2825,14 +2825,14 @@ has-values@^1.0.0: has@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hash-base@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + resolved "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz" integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== dependencies: inherits "^2.0.4" @@ -2841,7 +2841,7 @@ hash-base@^3.0.0: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" @@ -2849,7 +2849,7 @@ hash.js@^1.0.0, hash.js@^1.0.3: history@^4.7.2: version "4.10.1" - resolved "https://registry.npmjs.org/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + resolved "https://registry.npmjs.org/history/-/history-4.10.1.tgz" integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== dependencies: "@babel/runtime" "^7.1.2" @@ -2861,7 +2861,7 @@ history@^4.7.2: hmac-drbg@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" @@ -2870,36 +2870,36 @@ hmac-drbg@^1.0.0: hoek@6.x.x: version "6.1.3" - resolved "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c" + resolved "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz" integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ== hoist-non-react-statics@^2.5.0: version "2.5.5" - resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" + resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== hoist-non-react-statics@^3.3.2: version "3.3.2" - resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + resolved "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== dependencies: react-is "^16.7.0" homedir-polyfill@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + resolved "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz" integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== dependencies: parse-passwd "^1.0.0" hoopy@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + resolved "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz" integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== http-errors@1.7.2: version "1.7.2" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz" integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== dependencies: depd "~1.1.2" @@ -2910,7 +2910,7 @@ http-errors@1.7.2: http-errors@~1.7.2: version "1.7.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz" integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== dependencies: depd "~1.1.2" @@ -2921,48 +2921,48 @@ http-errors@~1.7.2: https-browserify@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + resolved "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= iconv-lite@0.4.24: version "0.4.24" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" iconv-lite@^0.6.2: version "0.6.2" - resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz" integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz" integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== dependencies: postcss "^7.0.14" ieee754@^1.1.4: version "1.2.1" - resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== iferr@^0.1.5: version "0.1.5" - resolved "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + resolved "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz" integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= immutable@^4.0.0-rc.9: version "4.0.0-rc.12" - resolved "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" + resolved "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz" integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== import-local@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + resolved "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz" integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== dependencies: pkg-dir "^3.0.0" @@ -2970,22 +2970,22 @@ import-local@^2.0.0: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= indexes-of@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= infer-owner@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + resolved "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz" integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -2993,91 +2993,91 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= inherits@2.0.3: version "2.0.3" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= ini@^1.3.4, ini@^1.3.5: version "1.3.8" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== interpret@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" + resolved "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== invariant@^2.2.1, invariant@^2.2.4: version "2.2.4" - resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" ipaddr.js@1.9.1: version "1.9.1" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== is-accessor-descriptor@^0.1.6: version "0.1.6" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz" integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + resolved "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz" integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" is-binary-path@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz" integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" is-buffer@^1.1.5: version "1.1.6" - resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== is-data-descriptor@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz" integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + resolved "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz" integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" is-descriptor@^0.1.0: version "0.1.6" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz" integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" @@ -3086,7 +3086,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + resolved "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz" integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" @@ -3095,109 +3095,109 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz" integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + resolved "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz" integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-glob@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz" integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" is-number@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + resolved "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz" integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-stream@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + resolved "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-what@^3.3.1: version "3.12.0" - resolved "https://registry.npmjs.org/is-what/-/is-what-3.12.0.tgz#f4405ce4bd6dd420d3ced51a026fb90e03705e55" + resolved "https://registry.npmjs.org/is-what/-/is-what-3.12.0.tgz" integrity sha512-2ilQz5/f/o9V7WRWJQmpFYNmQFZ9iM+OXRonZKcYgTkCzjb949Vi4h282PD1UfmgHk666rcWonbRJ++KI41VGw== is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== is-wsl@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz" integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= isarray@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + resolved "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz" integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + resolved "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz" integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= dependencies: node-fetch "^1.0.1" @@ -3205,17 +3205,17 @@ isomorphic-fetch@^2.2.1: iterall@^1.2.1: version "1.3.0" - resolved "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz#afcb08492e2915cbd8a0884eb93a8c94d0d72fea" + resolved "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz" integrity sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^3.10.0: version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== dependencies: argparse "^1.0.7" @@ -3223,99 +3223,99 @@ js-yaml@^3.10.0: jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-parse-better-errors@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + resolved "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz" integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= dependencies: jsonify "~0.0.0" json5@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" json5@^2.1.2: version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" jsonify@~0.0.0: version "0.0.0" - resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + resolved "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz" integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= just-curry-it@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.1.0.tgz#ab59daed308a58b847ada166edd0a2d40766fbc5" + resolved "https://registry.npmjs.org/just-curry-it/-/just-curry-it-3.1.0.tgz" integrity sha512-mjzgSOFzlrurlURaHVjnQodyPNvrHrf1TbQP2XU9NSqBtHQPuHZ+Eb6TAJP7ASeJN9h9K0KXoRTs8u6ouHBKvg== keycode@^2.1.9: version "2.2.0" - resolved "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04" + resolved "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz" integrity sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ= kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz" integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz" integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== linkify-it@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz" integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== dependencies: uc.micro "^1.0.1" loader-runner@^2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz" integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: big.js "^5.2.2" @@ -3324,7 +3324,7 @@ loader-utils@^1.2.3, loader-utils@^1.4.0: loader-utils@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz" integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== dependencies: big.js "^5.2.2" @@ -3333,7 +3333,7 @@ loader-utils@^2.0.0: locate-path@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz" integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" @@ -3341,55 +3341,55 @@ locate-path@^3.0.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" lodash._getnative@^3.0.0: version "3.9.1" - resolved "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + resolved "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz" integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= lodash.debounce@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz#812211c378a94cc29d5aa4e3346cf0bfce3a7df5" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-3.1.1.tgz" integrity sha1-gSIRw3ipTMKdWqTjNGzwv846ffU= dependencies: lodash._getnative "^3.0.0" lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.isequal@^4.5.0: version "4.5.0" - resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= lodash@^4.17.11, lodash@^4.17.19: version "4.17.20" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" lru-cache@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz" integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== dependencies: yallist "^3.0.2" make-dir@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: pify "^4.0.1" @@ -3397,26 +3397,26 @@ make-dir@^2.0.0: make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" map-cache@^0.2.2: version "0.2.2" - resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + resolved "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz" integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-visit@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + resolved "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz" integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" markdown-it@^10.0.0: version "10.0.0" - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz#abfc64f141b1722d663402044e43927f1f50a8dc" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz" integrity sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg== dependencies: argparse "^1.0.7" @@ -3427,7 +3427,7 @@ markdown-it@^10.0.0: markdown-it@^8.4.1: version "8.4.2" - resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz#386f98998dc15a37722aa7722084f4020bdd9b54" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz" integrity sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ== dependencies: argparse "^1.0.7" @@ -3438,12 +3438,12 @@ markdown-it@^8.4.1: marked@^0.8.2: version "0.8.2" - resolved "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz#4faad28d26ede351a7a1aaa5fec67915c869e355" + resolved "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz" integrity sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw== md5.js@^1.3.4: version "1.3.5" - resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz" integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== dependencies: hash-base "^3.0.0" @@ -3452,22 +3452,22 @@ md5.js@^1.3.4: mdurl@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz" integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= media-typer@0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= memoize-one@^5.0.0: version "5.1.1" - resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" + resolved "https://registry.npmjs.org/memoize-one/-/memoize-one-5.1.1.tgz" integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== memory-fs@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz" integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= dependencies: errno "^0.1.3" @@ -3475,7 +3475,7 @@ memory-fs@^0.4.1: memory-fs@^0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + resolved "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz" integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== dependencies: errno "^0.1.3" @@ -3483,24 +3483,24 @@ memory-fs@^0.5.0: merge-anything@^2.2.4: version "2.4.4" - resolved "https://registry.npmjs.org/merge-anything/-/merge-anything-2.4.4.tgz#6226b2ac3d3d3fc5fb9e8d23aa400df25f98fdf0" + resolved "https://registry.npmjs.org/merge-anything/-/merge-anything-2.4.4.tgz" integrity sha512-l5XlriUDJKQT12bH+rVhAHjwIuXWdAIecGwsYjv2LJo+dA1AeRTmeQS+3QBpO6lEthBMDi2IUMpLC1yyRvGlwQ== dependencies: is-what "^3.3.1" merge-descriptors@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= methods@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + resolved "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + resolved "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== dependencies: arr-diff "^4.0.0" @@ -3519,7 +3519,7 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: miller-rabin@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + resolved "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz" integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== dependencies: bn.js "^4.0.0" @@ -3527,34 +3527,34 @@ miller-rabin@^4.0.0: mime-db@1.45.0: version "1.45.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== mime-types@~2.1.24: version "2.1.28" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz" integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== dependencies: mime-db "1.45.0" mime@1.6.0: version "1.6.0" - resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= minimatch@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" @@ -3566,7 +3566,7 @@ minimist@1.2.6, minimist@^1.2.0, minimist@^1.2.5: mississippi@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + resolved "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz" integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== dependencies: concat-stream "^1.5.0" @@ -3582,7 +3582,7 @@ mississippi@^3.0.0: mixin-deep@^1.2.0: version "1.3.2" - resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + resolved "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== dependencies: for-in "^1.0.2" @@ -3590,14 +3590,14 @@ mixin-deep@^1.2.0: mkdirp@^0.5.1, mkdirp@^0.5.3: version "0.5.5" - resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" move-concurrently@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + resolved "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz" integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= dependencies: aproba "^1.1.1" @@ -3609,27 +3609,27 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== nan@^2.12.1: version "2.14.2" - resolved "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" + resolved "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== nanomatch@^1.2.9: version "1.2.13" - resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz" integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" @@ -3646,22 +3646,22 @@ nanomatch@^1.2.9: negotiator@0.6.2: version "0.6.2" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== neo-async@^2.5.0, neo-async@^2.6.1: version "2.6.2" - resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" - resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + resolved "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== node-fetch@^1.0.1: version "1.7.3" - resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz" integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== dependencies: encoding "^0.1.11" @@ -3669,12 +3669,12 @@ node-fetch@^1.0.1: node-fingerprint@0.0.2: version "0.0.2" - resolved "https://registry.npmjs.org/node-fingerprint/-/node-fingerprint-0.0.2.tgz#31cbabeb71a67ae7dd5a7dc042e51c3c75868501" + resolved "https://registry.npmjs.org/node-fingerprint/-/node-fingerprint-0.0.2.tgz" integrity sha1-Mcur63GmeufdWn3AQuUcPHWGhQE= node-libs-browser@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + resolved "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz" integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== dependencies: assert "^1.1.1" @@ -3703,34 +3703,34 @@ node-libs-browser@^2.2.1: node-releases@^1.1.70: version "1.1.70" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz" integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== normalize-path@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz" integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= dependencies: remove-trailing-separator "^1.0.1" normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== nullthrows@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= object-copy@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + resolved "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz" integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" @@ -3739,19 +3739,19 @@ object-copy@^0.1.0: object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-visit@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + resolved "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz" integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" object.assign@^4.1.0: version "4.1.2" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: call-bind "^1.0.0" @@ -3761,69 +3761,69 @@ object.assign@^4.1.0: object.pick@^1.3.0: version "1.3.0" - resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + resolved "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz" integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" on-finished@~2.3.0: version "2.3.0" - resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + resolved "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz" integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= dependencies: ee-first "1.1.1" once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" opener@^1.5.1: version "1.5.2" - resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" + resolved "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== os-browserify@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + resolved "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-locate@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz" integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== pako@~1.0.5: version "1.0.11" - resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + resolved "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== parallel-transform@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + resolved "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz" integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== dependencies: cyclist "^1.0.1" @@ -3832,7 +3832,7 @@ parallel-transform@^1.1.0: parse-asn1@^5.0.0, parse-asn1@^5.1.5: version "5.1.6" - resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + resolved "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz" integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: asn1.js "^5.2.0" @@ -3843,64 +3843,64 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.5: parse-passwd@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + resolved "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz" integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= parseurl@~1.3.3: version "1.3.3" - resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + resolved "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== pascalcase@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + resolved "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + resolved "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== path-dirname@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + resolved "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz" integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-key@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + resolved "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= path-to-regexp@0.1.7: version "0.1.7" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= path-to-regexp@^1.7.0: version "1.8.0" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz" integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== dependencies: isarray "0.0.1" pbkdf2@^3.0.3: version "3.1.1" - resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + resolved "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz" integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== dependencies: create-hash "^1.1.2" @@ -3911,48 +3911,48 @@ pbkdf2@^3.0.3: picocolors@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz" integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== pify@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pkg-dir@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz" integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== dependencies: find-up "^3.0.0" pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" posix-character-classes@^0.1.0: version "0.1.1" - resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-modules-extract-imports@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz" integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== dependencies: postcss "^7.0.5" postcss-modules-local-by-default@^3.0.2: version "3.0.3" - resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz" integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: icss-utils "^4.1.1" @@ -3962,7 +3962,7 @@ postcss-modules-local-by-default@^3.0.2: postcss-modules-scope@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz" integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: postcss "^7.0.6" @@ -3970,7 +3970,7 @@ postcss-modules-scope@^2.2.0: postcss-modules-values@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz" integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: icss-utils "^4.0.0" @@ -3978,7 +3978,7 @@ postcss-modules-values@^3.0.0: postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.4" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz" integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== dependencies: cssesc "^3.0.0" @@ -3988,12 +3988,12 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: postcss-value-parser@^3.3.0: version "3.3.1" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== postcss-value-parser@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@7.0.39, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: @@ -4006,27 +4006,27 @@ postcss@7.0.39, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6 prettier@2.0.2: version "2.0.2" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.0.2.tgz#1ba8f3eb92231e769b7fcd7cb73ae1b6b74ade08" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.0.2.tgz" integrity sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg== process-nextick-args@~2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== process@^0.11.10: version "0.11.10" - resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + resolved "https://registry.npmjs.org/process/-/process-0.11.10.tgz" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= promise-inflight@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + resolved "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz" integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" - resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== dependencies: loose-envify "^1.4.0" @@ -4035,7 +4035,7 @@ prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, proxy-addr@~2.0.5: version "2.0.6" - resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" + resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz" integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== dependencies: forwarded "~0.1.2" @@ -4043,12 +4043,12 @@ proxy-addr@~2.0.5: prr@~1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= public-encrypt@^4.0.0: version "4.0.3" - resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + resolved "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz" integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== dependencies: bn.js "^4.1.0" @@ -4060,7 +4060,7 @@ public-encrypt@^4.0.0: pump@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + resolved "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz" integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== dependencies: end-of-stream "^1.1.0" @@ -4068,7 +4068,7 @@ pump@^2.0.0: pump@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + resolved "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz" integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== dependencies: end-of-stream "^1.1.0" @@ -4076,7 +4076,7 @@ pump@^3.0.0: pumpify@^1.3.3: version "1.5.1" - resolved "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + resolved "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz" integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== dependencies: duplexify "^3.6.0" @@ -4085,27 +4085,27 @@ pumpify@^1.3.3: punycode@1.3.2: version "1.3.2" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= punycode@^1.2.4: version "1.4.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + resolved "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= punycode@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== qs@6.7.0: version "6.7.0" - resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + resolved "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== query-string@5: version "5.1.1" - resolved "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" + resolved "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz" integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== dependencies: decode-uri-component "^0.2.0" @@ -4114,24 +4114,24 @@ query-string@5: querystring-es3@^0.2.0: version "0.2.1" - resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + resolved "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz" integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= querystring@0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + resolved "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" randomfill@^1.0.3: version "1.0.4" - resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + resolved "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz" integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== dependencies: randombytes "^2.0.5" @@ -4139,12 +4139,12 @@ randomfill@^1.0.3: range-parser@~1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== raw-body@2.4.0: version "2.4.0" - resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz" integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== dependencies: bytes "3.1.0" @@ -4154,14 +4154,14 @@ raw-body@2.4.0: react-addons-shallow-compare@^15.6.2: version "15.6.3" - resolved "https://registry.npmjs.org/react-addons-shallow-compare/-/react-addons-shallow-compare-15.6.3.tgz#28a94b0dfee71530852c66a69053d59a1baf04cb" + resolved "https://registry.npmjs.org/react-addons-shallow-compare/-/react-addons-shallow-compare-15.6.3.tgz" integrity sha512-EDJbgKTtGRLhr3wiGDXK/+AEJ59yqGS+tKE6mue0aNXT6ZMR7VJbbzIiT6akotmHg1BLj46ElJSb+NBMp80XBg== dependencies: object-assign "^4.1.0" react-codemirror@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/react-codemirror/-/react-codemirror-1.0.0.tgz#91467b53b1f5d80d916a2fd0b4c7adb85a9001ba" + resolved "https://registry.npmjs.org/react-codemirror/-/react-codemirror-1.0.0.tgz" integrity sha1-kUZ7U7H12A2Rai/QtMetuFqQAbo= dependencies: classnames "^2.2.5" @@ -4173,7 +4173,7 @@ react-codemirror@^1.0.0: react-copy-to-clipboard@^5.0.1: version "5.0.3" - resolved "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.3.tgz#2a0623b1115a1d8c84144e9434d3342b5af41ab4" + resolved "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.3.tgz" integrity sha512-9S3j+m+UxDZOM0Qb8mhnT/rMR0NGSrj9A/073yz2DSxPMYhmYFBMYIdI2X4o8AjOjyFsSNxDRnCX6s/gRxpriw== dependencies: copy-to-clipboard "^3" @@ -4181,12 +4181,12 @@ react-copy-to-clipboard@^5.0.1: react-display-name@^0.2.3: version "0.2.5" - resolved "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz#304c7cbfb59ee40389d436e1a822c17fe27936c6" + resolved "https://registry.npmjs.org/react-display-name/-/react-display-name-0.2.5.tgz" integrity sha512-I+vcaK9t4+kypiSgaiVWAipqHRXYmZIuAiS8vzFvXHHXVigg/sMKwlRgLy6LH2i3rmP+0Vzfl5lFsFRwF1r3pg== react-dom@^16.13.1: version "16.14.0" - resolved "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz#7ad838ec29a777fb3c75c3a190f661cf92ab8b89" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz" integrity sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw== dependencies: loose-envify "^1.1.0" @@ -4196,12 +4196,12 @@ react-dom@^16.13.1: react-fast-compare@^2.0.2: version "2.0.4" - resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + resolved "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz" integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== react-helmet@^5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.1.tgz#16a7192fdd09951f8e0fe22ffccbf9bb3e591ffa" + resolved "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.1.tgz" integrity sha512-CnwD822LU8NDBnjCpZ4ySh8L6HYyngViTZLfBBb3NjtrpN8m49clH8hidHouq20I51Y6TpCTISCBbqiY5GamwA== dependencies: object-assign "^4.1.1" @@ -4211,24 +4211,24 @@ react-helmet@^5.2.0: react-input-autosize@^2.2.1: version "2.2.2" - resolved "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" + resolved "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz" integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== dependencies: prop-types "^15.5.8" react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" - resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" + resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== react-modal@^3.1.11: version "3.12.1" - resolved "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz#38c33f70d81c33d02ff1ed115530443a3dc2afd3" + resolved "https://registry.npmjs.org/react-modal/-/react-modal-3.12.1.tgz" integrity sha512-WGuXn7Fq31PbFJwtWmOk+jFtGC7E9tJVbFX0lts8ZoS5EPi9+WWylUJWLKKVm3H4GlQ7ZxY7R6tLlbSIBQ5oZA== dependencies: exenv "^1.2.0" @@ -4238,7 +4238,7 @@ react-modal@^3.1.11: react-redux@^7.2.0, react-redux@^7.2.2: version "7.2.2" - resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz#03862e803a30b6b9ef8582dadcc810947f74b736" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz" integrity sha512-8+CQ1EvIVFkYL/vu6Olo7JFLWop1qRUeb46sGtIMDCSpgwPQq8fPLpirIB0iTqFe9XYEFPHssdX8/UwN6pAkEA== dependencies: "@babel/runtime" "^7.12.1" @@ -4249,7 +4249,7 @@ react-redux@^7.2.0, react-redux@^7.2.2: react-router-dom@^4.2.2: version "4.3.1" - resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" + resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz" integrity sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA== dependencies: history "^4.7.2" @@ -4261,7 +4261,7 @@ react-router-dom@^4.2.2: react-router@^4.3.1: version "4.3.1" - resolved "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz#aada4aef14c809cb2e686b05cee4742234506c4e" + resolved "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz" integrity sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg== dependencies: history "^4.7.2" @@ -4274,14 +4274,14 @@ react-router@^4.3.1: react-side-effect@^1.1.0: version "1.2.0" - resolved "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.2.0.tgz#0e940c78faba0c73b9b0eba9cd3dda8dfb7e7dae" + resolved "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.2.0.tgz" integrity sha512-v1ht1aHg5k/thv56DRcjw+WtojuuDHFUgGfc+bFHOWsF4ZK6C2V57DO0Or0GPsg6+LSTE0M6Ry/gfzhzSwbc5w== dependencies: shallowequal "^1.0.1" react-sortable-hoc@^0.8.3: version "0.8.4" - resolved "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-0.8.4.tgz#11aa1f3e07ded79764a8bae9d107990ab9b3954b" + resolved "https://registry.npmjs.org/react-sortable-hoc/-/react-sortable-hoc-0.8.4.tgz" integrity sha512-J9AFEQAJ7u2YWdVzkU5E3ewrG82xQ4xF1ZPrZYKliDwlVBDkmjri+iKFAEt6NCDIRiBZ4hiN5vzI8pwy/dGPHw== dependencies: babel-runtime "^6.11.6" @@ -4290,7 +4290,7 @@ react-sortable-hoc@^0.8.3: react-transition-group@^2.2.1: version "2.9.0" - resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" + resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz" integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== dependencies: dom-helpers "^3.4.0" @@ -4300,7 +4300,7 @@ react-transition-group@^2.2.1: react-virtualized@^9.12.0: version "9.22.3" - resolved "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz#f430f16beb0a42db420dbd4d340403c0de334421" + resolved "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.3.tgz" integrity sha512-MKovKMxWTcwPSxE1kK1HcheQTWfuCxAuBoSTf2gwyMM21NdX/PXUhnoP8Uc5dRKd+nKm8v41R36OellhdCpkrw== dependencies: "@babel/runtime" "^7.7.2" @@ -4312,7 +4312,7 @@ react-virtualized@^9.12.0: react@16.13.1: version "16.13.1" - resolved "https://registry.npmjs.org/react/-/react-16.13.1.tgz#2e818822f1a9743122c063d6410d85c1e3afe48e" + resolved "https://registry.npmjs.org/react/-/react-16.13.1.tgz" integrity sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w== dependencies: loose-envify "^1.1.0" @@ -4321,7 +4321,7 @@ react@16.13.1: react@^16.13.1: version "16.14.0" - resolved "https://registry.npmjs.org/react/-/react-16.14.0.tgz#94d776ddd0aaa37da3eda8fc5b6b18a4c9a3114d" + resolved "https://registry.npmjs.org/react/-/react-16.14.0.tgz" integrity sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g== dependencies: loose-envify "^1.1.0" @@ -4330,7 +4330,7 @@ react@^16.13.1: "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" @@ -4343,7 +4343,7 @@ react@^16.13.1: readable-stream@^3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" @@ -4352,7 +4352,7 @@ readable-stream@^3.6.0: readdirp@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz" integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" @@ -4361,19 +4361,19 @@ readdirp@^2.2.1: readdirp@~3.5.0: version "3.5.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz" integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== dependencies: picomatch "^2.2.1" reduce-reducers@^0.4.3: version "0.4.3" - resolved "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz#8e052618801cd8fc2714b4915adaa8937eb6d66c" + resolved "https://registry.npmjs.org/reduce-reducers/-/reduce-reducers-0.4.3.tgz" integrity sha512-+CNMnI8QhgVMtAt54uQs3kUxC3Sybpa7Y63HR14uGLgI9/QR5ggHvpxwhGGe3wmx5V91YwqQIblN9k5lspAmGw== redux-actions@^2.6.5: version "2.6.5" - resolved "https://registry.npmjs.org/redux-actions/-/redux-actions-2.6.5.tgz#bdca548768ee99832a63910c276def85e821a27e" + resolved "https://registry.npmjs.org/redux-actions/-/redux-actions-2.6.5.tgz" integrity sha512-pFhEcWFTYNk7DhQgxMGnbsB1H2glqhQJRQrtPb96kD3hWiZRzXHwwmFPswg6V2MjraXRXWNmuP9P84tvdLAJmw== dependencies: invariant "^2.2.4" @@ -4384,36 +4384,36 @@ redux-actions@^2.6.5: redux-immutable@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz#3a1a32df66366462b63691f0e1dc35e472bbc9f3" + resolved "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz" integrity sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM= redux-localstorage-debounce@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/redux-localstorage-debounce/-/redux-localstorage-debounce-0.1.0.tgz#ce8f4c9c36a7b867550dca24a7ef4068fb5bc18b" + resolved "https://registry.npmjs.org/redux-localstorage-debounce/-/redux-localstorage-debounce-0.1.0.tgz" integrity sha1-zo9MnDanuGdVDcokp+9AaPtbwYs= dependencies: lodash.debounce "^3.1.1" redux-localstorage-filter@^0.1.1: version "0.1.1" - resolved "https://registry.npmjs.org/redux-localstorage-filter/-/redux-localstorage-filter-0.1.1.tgz#94c5ab68d8cda479bb3cc6cdf03569f8f63a188d" + resolved "https://registry.npmjs.org/redux-localstorage-filter/-/redux-localstorage-filter-0.1.1.tgz" integrity sha1-lMWraNjNpHm7PMbN8DVp+PY6GI0= redux-localstorage@^1.0.0-rc5: version "1.0.0-rc5" - resolved "https://registry.npmjs.org/redux-localstorage/-/redux-localstorage-1.0.0-rc5.tgz#7067bc4cb0b03b5c791025ac33dde6175d50d5d1" + resolved "https://registry.npmjs.org/redux-localstorage/-/redux-localstorage-1.0.0-rc5.tgz" integrity sha1-cGe8TLCwO1x5ECWsM93mF11Q1dE= redux-saga@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/redux-saga/-/redux-saga-1.1.3.tgz#9f3e6aebd3c994bbc0f6901a625f9a42b51d1112" + resolved "https://registry.npmjs.org/redux-saga/-/redux-saga-1.1.3.tgz" integrity sha512-RkSn/z0mwaSa5/xH/hQLo8gNf4tlvT18qXDNvedihLcfzh+jMchDgaariQoehCpgRltEm4zHKJyINEz6aqswTw== dependencies: "@redux-saga/core" "^1.1.3" redux@^4.0.4, redux@^4.0.5: version "4.0.5" - resolved "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + resolved "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz" integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== dependencies: loose-envify "^1.4.0" @@ -4421,36 +4421,36 @@ redux@^4.0.4, redux@^4.0.5: regenerate-unicode-properties@^8.2.0: version "8.2.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz" integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== dependencies: regenerate "^1.4.0" regenerate@^1.4.0: version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.11.0: version "0.11.1" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4: version "0.13.7" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: version "0.14.5" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + resolved "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz" integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" @@ -4458,7 +4458,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: regexpu-core@^4.7.1: version "4.7.1" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz" integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" @@ -4470,56 +4470,56 @@ regexpu-core@^4.7.1: regjsgen@^0.5.1: version "0.5.2" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== regjsparser@^0.6.4: version "0.6.7" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz#c00164e1e6713c2e3ee641f1701c4b7aa0a7f86c" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz" integrity sha512-ib77G0uxsA2ovgiYbCVGx4Pv3PSttAx2vIwidqQzbL2U5S4Q+j00HdSAneSBuyVcMvEnTXMjiGgB+DlXozVhpQ== dependencies: jsesc "~0.5.0" remove-trailing-separator@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + resolved "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz" integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= repeat-element@^1.1.2: version "1.1.3" - resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + resolved "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz" integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.6.1: version "1.6.1" - resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + resolved "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-main-filename@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== reselect@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz#f2529830e5d3d0e021408b246a206ef4ea4437f7" + resolved "https://registry.npmjs.org/reselect/-/reselect-4.0.0.tgz" integrity sha512-qUgANli03jjAyGlnbYVAV5vvnOmJnODyABz51RdBN7M4WaVu8mecZWgyQNkG8Yqe3KRGRt0l4K4B3XVEULC4CA== resolve-cwd@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz" integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= dependencies: resolve-from "^3.0.0" resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + resolved "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz" integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= dependencies: expand-tilde "^2.0.0" @@ -4527,34 +4527,34 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1: resolve-from@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz" integrity sha1-six699nWiBvItuZTM17rywoYh0g= resolve-pathname@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + resolved "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz" integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== resolve-url@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + resolved "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= ret@~0.1.10: version "0.1.15" - resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + resolved "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== dependencies: glob "^7.1.3" ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + resolved "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz" integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== dependencies: hash-base "^3.0.0" @@ -4562,36 +4562,36 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + resolved "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz" integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= dependencies: aproba "^1.1.1" safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-regex@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + resolved "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz" integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== scheduler@^0.19.1: version "0.19.1" - resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz" integrity sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA== dependencies: loose-envify "^1.1.0" @@ -4599,7 +4599,7 @@ scheduler@^0.19.1: schema-utils@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz" integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== dependencies: ajv "^6.1.0" @@ -4608,7 +4608,7 @@ schema-utils@^1.0.0: schema-utils@^2.6.5, schema-utils@^2.7.0: version "2.7.1" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: "@types/json-schema" "^7.0.5" @@ -4617,7 +4617,7 @@ schema-utils@^2.6.5, schema-utils@^2.7.0: schema-utils@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz" integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== dependencies: "@types/json-schema" "^7.0.6" @@ -4626,27 +4626,27 @@ schema-utils@^3.0.0: seamless-immutable@^7.0.1: version "7.1.4" - resolved "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz#6e9536def083ddc4dea0207d722e0e80d0f372f8" + resolved "https://registry.npmjs.org/seamless-immutable/-/seamless-immutable-7.1.4.tgz" integrity sha512-XiUO1QP4ki4E2PHegiGAlu6r82o5A+6tRh7IkGGTVg/h+UoeX4nFBeCGPOhb4CYjvkqsfm/TUtvOMYC1xmV30A== semver@7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@^6.0.0, semver@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== send@0.17.1: version "0.17.1" - resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + resolved "https://registry.npmjs.org/send/-/send-0.17.1.tgz" integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== dependencies: debug "2.6.9" @@ -4665,14 +4665,14 @@ send@0.17.1: serialize-javascript@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz" integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: randombytes "^2.1.0" serve-static@1.14.1: version "1.14.1" - resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + resolved "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz" integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== dependencies: encodeurl "~1.0.2" @@ -4682,12 +4682,12 @@ serve-static@1.14.1: set-blocking@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= set-value@^2.0.0, set-value@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + resolved "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== dependencies: extend-shallow "^2.0.1" @@ -4697,17 +4697,17 @@ set-value@^2.0.0, set-value@^2.0.1: setimmediate@^1.0.4: version "1.0.5" - resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + resolved "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz" integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= setprototypeof@1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" - resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + resolved "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== dependencies: inherits "^2.0.1" @@ -4715,24 +4715,24 @@ sha.js@^2.4.0, sha.js@^2.4.8: shallowequal@^1.0.1: version "1.1.0" - resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + resolved "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz" integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== shebang-command@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= snapdragon-node@^2.0.1: version "2.1.1" - resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + resolved "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz" integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" @@ -4741,14 +4741,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + resolved "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz" integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" - resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + resolved "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz" integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" @@ -4762,12 +4762,12 @@ snapdragon@^0.8.1: source-list-map@^2.0.0: version "2.0.1" - resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== source-map-resolve@^0.5.0: version "0.5.3" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz" integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: atob "^2.1.2" @@ -4778,7 +4778,7 @@ source-map-resolve@^0.5.0: source-map-support@~0.5.12: version "0.5.19" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== dependencies: buffer-from "^1.0.0" @@ -4786,41 +4786,41 @@ source-map-support@~0.5.12: source-map-url@^0.4.0: version "0.4.1" - resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + resolved "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + resolved "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz" integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" sprintf-js@~1.0.2: version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= ssri@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + resolved "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz" integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== dependencies: figgy-pudding "^3.5.1" static-extend@^0.1.1: version "0.1.2" - resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + resolved "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz" integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" @@ -4828,12 +4828,12 @@ static-extend@^0.1.1: "statuses@>= 1.5.0 < 2", statuses@~1.5.0: version "1.5.0" - resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= stream-browserify@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + resolved "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz" integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== dependencies: inherits "~2.0.1" @@ -4841,7 +4841,7 @@ stream-browserify@^2.0.1: stream-each@^1.1.0: version "1.2.3" - resolved "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + resolved "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz" integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== dependencies: end-of-stream "^1.1.0" @@ -4849,7 +4849,7 @@ stream-each@^1.1.0: stream-http@^2.7.2: version "2.8.3" - resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + resolved "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz" integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== dependencies: builtin-status-codes "^3.0.0" @@ -4860,17 +4860,17 @@ stream-http@^2.7.2: stream-shift@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + resolved "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== strict-uri-encode@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz" integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" @@ -4879,28 +4879,28 @@ string-width@^3.0.0, string-width@^3.1.0: string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== dependencies: safe-buffer "~5.2.0" string_decoder@~1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== dependencies: safe-buffer "~5.1.0" strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz" integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" style-loader@^1.2.1: version "1.3.0" - resolved "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" + resolved "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz" integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== dependencies: loader-utils "^2.0.0" @@ -4908,7 +4908,7 @@ style-loader@^1.2.1: styled-components@^4.0.0: version "4.4.1" - resolved "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz#e0631e889f01db67df4de576fedaca463f05c2f2" + resolved "https://registry.npmjs.org/styled-components/-/styled-components-4.4.1.tgz" integrity sha512-RNqj14kYzw++6Sr38n7197xG33ipEOktGElty4I70IKzQF1jzaD1U4xQ+Ny/i03UUhHlC5NWEO+d8olRCDji6g== dependencies: "@babel/helper-module-imports" "^7.0.0" @@ -4927,17 +4927,17 @@ styled-components@^4.0.0: stylis-rule-sheet@^0.0.10: version "0.0.10" - resolved "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" + resolved "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz" integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== stylis@^3.5.0: version "3.5.4" - resolved "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" + resolved "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz" integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== subscriptions-transport-ws@^0.9.5: version "0.9.18" - resolved "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz#bcf02320c911fbadb054f7f928e51c6041a37b97" + resolved "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz" integrity sha512-tztzcBTNoEbuErsVQpTN2xUNN/efAZXyCyL5m3x4t6SKrEiTL2N8SaKWBFWM4u56pL79ULif3zjyeq+oV+nOaA== dependencies: backo2 "^1.0.2" @@ -4948,31 +4948,31 @@ subscriptions-transport-ws@^0.9.5: supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^6.1.0: version "6.1.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== dependencies: has-flag "^3.0.0" symbol-observable@^1.0.4, symbol-observable@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + resolved "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz" integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== terser-webpack-plugin@^1.4.3: version "1.4.5" - resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz" integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" @@ -4996,7 +4996,7 @@ terser@4.8.1, terser@^4.1.2: through2@^2.0.0: version "2.0.5" - resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz" integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== dependencies: readable-stream "~2.3.6" @@ -5004,53 +5004,53 @@ through2@^2.0.0: timers-browserify@^2.0.4: version "2.0.12" - resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + resolved "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz" integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== dependencies: setimmediate "^1.0.4" tiny-invariant@^1.0.2: version "1.1.0" - resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" + resolved "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz" integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== tiny-warning@^1.0.0: version "1.0.3" - resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + resolved "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== to-arraybuffer@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + resolved "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= to-camel-case@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz#1a56054b2f9d696298ce66a60897322b6f423e46" + resolved "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz" integrity sha1-GlYFSy+daWKYzmamCJcyK29CPkY= dependencies: to-space-case "^1.0.0" to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= to-no-case@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz#c722907164ef6b178132c8e69930212d1b4aa16a" + resolved "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz" integrity sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo= to-object-path@^0.3.0: version "0.3.0" - resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + resolved "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz" integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz" integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" @@ -5058,14 +5058,14 @@ to-regex-range@^2.1.0: to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + resolved "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz" integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" @@ -5075,46 +5075,46 @@ to-regex@^3.0.1, to-regex@^3.0.2: to-space-case@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz#b052daafb1b2b29dc770cea0163e5ec0ebc9fc17" + resolved "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz" integrity sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc= dependencies: to-no-case "^1.0.0" toggle-selection@^1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= toidentifier@1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + resolved "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz" integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== tryer@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + resolved "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz" integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== ts-invariant@^0.4.0: version "0.4.4" - resolved "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz#97a523518688f93aafad01b0e80eb803eb2abd86" + resolved "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz" integrity sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA== dependencies: tslib "^1.9.3" tslib@^1.10.0, tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tty-browserify@0.0.0: version "0.0.0" - resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz" integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= type-is@~1.6.17, type-is@~1.6.18: version "1.6.18" - resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== dependencies: media-typer "0.3.0" @@ -5122,41 +5122,41 @@ type-is@~1.6.17, type-is@~1.6.18: typedarray@^0.0.6: version "0.0.6" - resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript-compare@^0.0.2: version "0.0.2" - resolved "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" + resolved "https://registry.npmjs.org/typescript-compare/-/typescript-compare-0.0.2.tgz" integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA== dependencies: typescript-logic "^0.0.0" typescript-logic@^0.0.0: version "0.0.0" - resolved "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196" + resolved "https://registry.npmjs.org/typescript-logic/-/typescript-logic-0.0.0.tgz" integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q== typescript-tuple@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2" + resolved "https://registry.npmjs.org/typescript-tuple/-/typescript-tuple-2.2.1.tgz" integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q== dependencies: typescript-compare "^0.0.2" uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" - resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz" integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz" integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== unicode-match-property-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz" integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" @@ -5164,17 +5164,17 @@ unicode-match-property-ecmascript@^1.0.4: unicode-match-property-value-ecmascript@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz" integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== unicode-property-aliases-ecmascript@^1.0.4: version "1.1.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz" integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== union-value@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + resolved "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== dependencies: arr-union "^3.1.0" @@ -5184,31 +5184,31 @@ union-value@^1.0.0: uniq@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= unique-filename@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + resolved "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz" integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== dependencies: unique-slug "^2.0.0" unique-slug@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + resolved "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz" integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== dependencies: imurmurhash "^0.1.4" unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= unset-value@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + resolved "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz" integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" @@ -5216,24 +5216,24 @@ unset-value@^1.0.0: upath@^1.1.1: version "1.2.0" - resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" urix@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + resolved "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz" integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url@^0.11.0: version "0.11.0" - resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz" integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= dependencies: punycode "1.3.2" @@ -5241,80 +5241,80 @@ url@^0.11.0: use@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + resolved "https://registry.npmjs.org/use/-/use-3.1.1.tgz" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util@0.10.3: version "0.10.3" - resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + resolved "https://registry.npmjs.org/util/-/util-0.10.3.tgz" integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= dependencies: inherits "2.0.1" util@^0.11.0: version "0.11.1" - resolved "https://registry.npmjs.org/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + resolved "https://registry.npmjs.org/util/-/util-0.11.1.tgz" integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== dependencies: inherits "2.0.3" utility-types@^1.0.0: version "1.1.0" - resolved "https://registry.npmjs.org/utility-types/-/utility-types-1.1.0.tgz#52408b6ed852fdd4076b48b30ed726f139b0f116" + resolved "https://registry.npmjs.org/utility-types/-/utility-types-1.1.0.tgz" integrity sha512-6PGyowB/ZDDAygpdZzdLu/9mn2EMf08/V1OOqTTc5EhADgd+/BQhinslzhD9xTVw3EWYa1jI3aBMZy5neBbSfw== utils-merge@1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + resolved "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= v8-compile-cache@^2.1.1: version "2.2.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz" integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== value-equal@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + resolved "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz" integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== vary@~1.1.2: version "1.1.2" - resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + resolved "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= vm-browserify@^1.0.1: version "1.1.2" - resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + resolved "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== vscode-languageserver-types@^3.15.1: version "3.16.0" - resolved "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz#ecf393fc121ec6974b2da3efb3155644c514e247" + resolved "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz" integrity sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA== warning@^4.0.1, warning@^4.0.3: version "4.0.3" - resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" + resolved "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz" integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== dependencies: loose-envify "^1.0.0" watchpack-chokidar2@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz#38500072ee6ece66f3769936950ea1771be1c957" + resolved "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz" integrity sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww== dependencies: chokidar "^2.1.8" watchpack@^1.7.4: version "1.7.5" - resolved "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz#1267e6c55e0b9b5be44c2023aed5437a2c26c453" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz" integrity sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ== dependencies: graceful-fs "^4.1.2" @@ -5325,7 +5325,7 @@ watchpack@^1.7.4: webpack-bundle-analyzer@^3.3.2: version "3.9.0" - resolved "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c" + resolved "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz" integrity sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA== dependencies: acorn "^7.1.1" @@ -5344,7 +5344,7 @@ webpack-bundle-analyzer@^3.3.2: webpack-cli@^3.3.12: version "3.3.12" - resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" + resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz" integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== dependencies: chalk "^2.4.2" @@ -5361,7 +5361,7 @@ webpack-cli@^3.3.12: webpack-sources@^1.4.0, webpack-sources@^1.4.1: version "1.4.3" - resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== dependencies: source-list-map "^2.0.0" @@ -5369,7 +5369,7 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1: webpack@^4.43.0: version "4.46.0" - resolved "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz#bf9b4404ea20a073605e0a011d188d77cb6ad542" + resolved "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz" integrity sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q== dependencies: "@webassemblyjs/ast" "1.9.0" @@ -5398,31 +5398,31 @@ webpack@^4.43.0: whatwg-fetch@>=0.10.0: version "3.5.0" - resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz#605a2cd0a7146e5db141e29d1c62ab84c0c4c868" + resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz" integrity sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A== which-module@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@^1.2.14, which@^1.2.9, which@^1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + resolved "https://registry.npmjs.org/which/-/which-1.3.1.tgz" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" worker-farm@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + resolved "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz" integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== dependencies: errno "~0.1.7" wrap-ansi@^5.1.0: version "5.1.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz" integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: ansi-styles "^3.2.0" @@ -5431,41 +5431,41 @@ wrap-ansi@^5.1.0: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= ws@^5.2.0: version "5.2.2" - resolved "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + resolved "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz" integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== dependencies: async-limiter "~1.0.0" ws@^6.0.0: version "6.2.1" - resolved "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + resolved "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== dependencies: async-limiter "~1.0.0" xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: version "4.0.1" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz" integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== yallist@^3.0.2: version "3.1.1" - resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== yargs-parser@^13.1.2: version "13.1.2" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz" integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" @@ -5473,7 +5473,7 @@ yargs-parser@^13.1.2: yargs@^13.3.2: version "13.3.2" - resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== dependencies: cliui "^5.0.0" @@ -5489,7 +5489,7 @@ yargs@^13.3.2: zen-observable-ts@^0.8.21: version "0.8.21" - resolved "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d" + resolved "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz" integrity sha512-Yj3yXweRc8LdRMrCC8nIc4kkjWecPAUVh0TI0OUrWXx6aX790vLcDlWca6I4vsyCGH3LpWxq0dJRcMOFoVqmeg== dependencies: tslib "^1.9.3" @@ -5497,10 +5497,10 @@ zen-observable-ts@^0.8.21: zen-observable@^0.7.1: version "0.7.1" - resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.7.1.tgz#f84075c0ee085594d3566e1d6454207f126411b3" + resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.7.1.tgz" integrity sha512-OI6VMSe0yeqaouIXtedC+F55Sr6r9ppS7+wTbSexkYdHbdt4ctTuPNXP/rwm7GTVI63YBc+EBT0b0tl7YnJLRg== zen-observable@^0.8.0: version "0.8.15" - resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" + resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ== diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java b/itests/src/test/java/org/apache/unomi/itests/AllITs.java index 60502de03..f415c3ab9 100644 --- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java +++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java @@ -64,7 +64,8 @@ GraphQLWebSocketIT.class, JSONSchemaIT.class, GraphQLProfileAliasesIT.class, - SendEventActionIT.class + SendEventActionIT.class, + HealthCheckIT.class, }) public class AllITs { } diff --git a/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java b/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java new file mode 100644 index 000000000..c3ed5c0d8 --- /dev/null +++ b/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java @@ -0,0 +1,214 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package org.apache.unomi.itests; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; +import org.apache.commons.io.IOUtils; +import org.apache.cxf.interceptor.security.AccessDeniedException; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.socket.PlainConnectionSocketFactory; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.karaf.itests.KarafTestSupport; +import org.apache.unomi.api.services.DefinitionsService; +import org.apache.unomi.api.services.EventService; +import org.apache.unomi.api.services.ProfileService; +import org.apache.unomi.lifecycle.BundleWatcher; +import org.apache.unomi.persistence.spi.PersistenceService; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.Configuration; +import org.ops4j.pax.exam.CoreOptions; +import org.ops4j.pax.exam.Option; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel; +import org.ops4j.pax.exam.options.MavenArtifactUrlReference; +import org.ops4j.pax.exam.options.extra.VMOption; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerSuite; +import org.ops4j.pax.exam.util.Filter; +import org.osgi.service.cm.ConfigurationAdmin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.inject.Inject; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.systemProperty; +import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*; + +/** + * Health Check Integration Tests + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerSuite.class) +public class HealthCheckIT extends BaseIT { + + private final static Logger LOGGER = LoggerFactory.getLogger(HealthCheckIT.class); + + protected static final String HEALTHCHECK_AUTH_USER_NAME = "health"; + protected static final String HEALTHCHECK_AUTH_PASSWORD = "health"; + protected static final String HEALTHCHECK_ENDPOINT = "/health/check"; + + @Test + public void testHealthCheck() { + try { + List response = get(HEALTHCHECK_ENDPOINT, new TypeReference<>() {}); + LOGGER.info("health check response: {}", response); + Assert.assertEquals(5, response.size()); + Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("karaf") && r.getStatus() == HealthCheckResponse.Status.LIVE)); + Assert.assertTrue(response.stream().anyMatch(r -> { + if (r.getName().equals("elasticsearch") && r.getStatus() == HealthCheckResponse.Status.LIVE) { + Map data = r.getData(); + String clusterName = (String) data.get("clusterName"); + String expectedClusterName = isOpenSearch() ? "docker-cluster" : "contextElasticSearchITests"; + return clusterName != null && clusterName.equals(expectedClusterName); + } + return false; + })); + Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("unomi") && r.getStatus() == HealthCheckResponse.Status.LIVE)); + Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("cluster") && r.getStatus() == HealthCheckResponse.Status.LIVE)); + Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("persistence") && r.getStatus() == HealthCheckResponse.Status.LIVE)); + } catch (Exception e) { + LOGGER.error("Error while executing health check", e); + fail("Error while executing health check" + e.getMessage()); + } + } + + protected T get(final String url, TypeReference typeReference) { + CloseableHttpResponse response = null; + try { + final HttpGet httpGet = new HttpGet(getFullUrl(url)); + response = executeHttpRequest(httpGet); + if (response.getStatusLine().getStatusCode() == 200) { + return objectMapper.readValue(response.getEntity().getContent(), typeReference); + } else { + return null; + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + try { + response.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return null; + } + + public BasicCredentialsProvider getHttpClientCredentialProvider() { + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(HEALTHCHECK_AUTH_USER_NAME, HEALTHCHECK_AUTH_PASSWORD)); + return credsProvider; + } + + public static class HealthCheckResponse { + private String name; + private Status status; + private long collectingTime; + private Map data; + + public HealthCheckResponse() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public long getCollectingTime() { + return collectingTime; + } + + public void setCollectingTime(long collectingTime) { + this.collectingTime = collectingTime; + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } + + @Override public String toString() { + return "HealthCheckResponse{" + "name='" + name + '\'' + ", status=" + status + ", collectingTime=" + collectingTime + ", data=" + + data + '}'; + } + + public enum Status { + DOWN, //Not available + UP, //Running or starting + LIVE, //Ready to serve requests + ERROR //Errors during check + } + } +} diff --git a/itests/src/test/java/org/apache/unomi/itests/LoggerConfigurationIT.java b/itests/src/test/java/org/apache/unomi/itests/LoggerConfigurationIT.java new file mode 100644 index 000000000..829b6e192 --- /dev/null +++ b/itests/src/test/java/org/apache/unomi/itests/LoggerConfigurationIT.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.itests; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.ops4j.pax.exam.junit.PaxExam; +import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; +import org.ops4j.pax.exam.spi.reactors.PerSuite; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; +import java.util.List; + +/** + * Test the effect of SafeExtendedThrowablePatternConverter on log injection by trying to simulate such an attack. + * Check into the log that no new line is injected. + */ +@RunWith(PaxExam.class) +@ExamReactorStrategy(PerSuite.class) +public class LoggerConfigurationIT extends BaseIT { + + private final static Logger LOGGER = LoggerFactory.getLogger(LoggerConfigurationIT.class); + + private void checkLogInjection() throws IOException { + Path log = Paths.get( + (String) configurationAdmin.getConfiguration("org.ops4j.pax.logging").getProperties().get("log4j2.appender.rolling.fileName")); + List lines = Files.readAllLines(log); + for (String line : lines) { + if (line.startsWith("PLOP")) { + Assert.fail("Log injection detected in line " + line); + } + } + LOGGER.info("YEAPA, No log injection detected"); + } + + @Test + public void testValueLogInjection() throws IOException { + testValueLogInjection("test"); + testValueLogInjection("log\r\nPLOP WARN\tinjection"); + checkLogInjection(); + } + + @Test + public void testExceptionLogInjection() throws IOException { + testExceptionLogInjection("8"); + testExceptionLogInjection("plop\r\n" + "PLOP" + new Date() + " [main] ERROR org.apache.unomi.itests.LoggerConfigurationIT - This line is a fake one to test log injection"); + checkLogInjection(); + } + + @Test + public void testExceptionLogInjectionWithMessage() throws IOException { + testExceptionLogInjectionWithMessage("8"); + testExceptionLogInjectionWithMessage("plop\r\n" + "PLOP" + new Date() + " [main] ERROR org.apache.unomi.itests.LoggerConfigurationIT - This line is a fake one to test log injection"); + checkLogInjection(); + } + + private void testValueLogInjection(String value) { + LOGGER.warn(value); + } + + private void testExceptionLogInjection(String value) { + try { + Integer.parseInt(value); + } catch (NumberFormatException e) { + LOGGER.error("", e); + } + } + + private void testExceptionLogInjectionWithMessage(String value) { + try { + Integer.parseInt(value); + } catch (NumberFormatException e) { + LOGGER.error(e.getMessage(), e); + } + } + +} diff --git a/itests/src/test/java/org/apache/unomi/itests/PatchIT.java b/itests/src/test/java/org/apache/unomi/itests/PatchIT.java index 40e70130a..098a03ad2 100644 --- a/itests/src/test/java/org/apache/unomi/itests/PatchIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/PatchIT.java @@ -35,7 +35,7 @@ @RunWith(PaxExam.class) @ExamReactorStrategy(PerSuite.class) public class PatchIT extends BaseIT { - private Logger logger = LoggerFactory.getLogger(PatchIT.class); + private Logger LOGGER = LoggerFactory.getLogger(PatchIT.class); @Test public void testPatch() throws IOException { diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileExportIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileExportIT.java index 2b52d53d1..8a9c58d67 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ProfileExportIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ProfileExportIT.java @@ -45,7 +45,7 @@ @RunWith(PaxExam.class) @ExamReactorStrategy(PerSuite.class) public class ProfileExportIT extends BaseIT { - private Logger logger = LoggerFactory.getLogger(ProfileExportIT.class); + private Logger LOGGER = LoggerFactory.getLogger(ProfileExportIT.class); @Test public void testExport() throws InterruptedException { @@ -108,7 +108,7 @@ public void testExport() throws InterruptedException { final File exportResult = new File("data/tmp/profiles-export.csv"); keepTrying("Failed waiting for export file to be created", () -> exportResult, File::exists, 1000, 100); - logger.info("PATH : {}", exportResult.getAbsolutePath()); + LOGGER.info("PATH : {}", exportResult.getAbsolutePath()); Assert.assertTrue(exportResult.exists()); List exportConfigurations = exportConfigurationService.getAll(); diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java index 2eb0d21a9..99b4aa1ed 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportBasicIT.java @@ -43,7 +43,7 @@ @RunWith(PaxExam.class) @ExamReactorStrategy(PerSuite.class) public class ProfileImportBasicIT extends BaseIT { - private Logger logger = LoggerFactory.getLogger(ProfileImportBasicIT.class); + private Logger LOGGER = LoggerFactory.getLogger(ProfileImportBasicIT.class); @Test public void testImportBasic() throws IOException, InterruptedException { @@ -64,13 +64,13 @@ public void testImportBasic() throws IOException, InterruptedException { importConfiguration.getProperties().put("mapping", mapping); importConfiguration.setActive(true); - logger.info("Save import config oneshot with ID : {}.", itemId); + LOGGER.info("Save import config oneshot with ID : {}.", itemId); importConfigurationService.save(importConfiguration, false); // Wait for the config to be processed Thread.sleep(5000); - logger.info("Check import config oneshot with ID : {}.", itemId); + LOGGER.info("Check import config oneshot with ID : {}.", itemId); List importConfigurations = importConfigurationService.getAll(); Assert.assertEquals(1, importConfigurations.size()); diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java index 40fd341ff..65e483f67 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportSurfersIT.java @@ -44,7 +44,7 @@ @RunWith(PaxExam.class) @ExamReactorStrategy(PerSuite.class) public class ProfileImportSurfersIT extends BaseIT { - private Logger logger = LoggerFactory.getLogger(ProfileImportSurfersIT.class); + private Logger LOGGER = LoggerFactory.getLogger(ProfileImportSurfersIT.class); @Test public void testImportSurfers() throws InterruptedException { @@ -91,7 +91,7 @@ public void testImportSurfers() throws InterruptedException { importConfigurationService.save(importConfigSurfers, true); - logger.info("ProfileImportSurfersIT setup successfully."); + LOGGER.info("ProfileImportSurfersIT setup successfully."); //Wait for data to be processed keepTrying("Failed waiting for surfers initial import to complete", @@ -139,7 +139,7 @@ public void testImportSurfers() throws InterruptedException { importConfigurationService.save(importConfigSurfersOverwrite, true); - logger.info("ProfileImportSurfersOverwriteIT setup successfully."); + LOGGER.info("ProfileImportSurfersOverwriteIT setup successfully."); //Wait for data to be processed keepTrying("Failed waiting for surfers overwrite import to complete", @@ -182,7 +182,7 @@ public void testImportSurfers() throws InterruptedException { importConfigurationService.save(importConfigSurfersDelete, true); - logger.info("ProfileImportSurfersDeleteIT setup successfully."); + LOGGER.info("ProfileImportSurfersDeleteIT setup successfully."); //Wait for data to be processed keepTrying("Failed waiting for surfers delete import to complete", diff --git a/itests/src/test/resources/org.apache.unomi.healthcheck.cfg b/itests/src/test/resources/org.apache.unomi.healthcheck.cfg new file mode 100644 index 000000000..710876fe4 --- /dev/null +++ b/itests/src/test/resources/org.apache.unomi.healthcheck.cfg @@ -0,0 +1,31 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Elasticsearch configuration +esAddresses = ${org.apache.unomi.elasticsearch.addresses:-localhost:9200} +esSSLEnabled = ${org.apache.unomi.elasticsearch.sslEnable:-false} +esLogin = ${org.apache.unomi.elasticsearch.username:-} +esPassword = ${org.apache.unomi.elasticsearch.password:-} +httpClient.trustAllCertificates = ${org.apache.unomi.elasticsearch.sslTrustAllCertificates:-false} + +# Security configuration +authentication.realm = ${org.apache.unomi.security.realm:-karaf} + +# Health check configuration +healthcheck.enabled = ${org.apache.unomi.healthcheck.enabled:-true} +healthcheck.providers = ${org.apache.unomi.healthcheck.providers:-cluster,elasticsearch,unomi,persistence} +healthcheck.timeout = ${org.apache.unomi.healthcheck.timeout:-400} diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java index f40f42a7a..6bff1e8dc 100644 --- a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java +++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java @@ -57,7 +57,7 @@ */ public class BundleWatcherImpl implements SynchronousBundleListener, ServiceListener, BundleWatcher { - private static final Logger logger = LoggerFactory.getLogger(BundleWatcherImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(BundleWatcherImpl.class.getName()); private static final String CDP_GRAPHQL_FEATURE = "cdp-graphql-feature"; @@ -99,7 +99,7 @@ public void setRequiredServices(String requiredServices) { try { requiredServicesFilters.add(bundleContext.createFilter(requiredService.trim())); } catch (InvalidSyntaxException e) { - logger.error("Error creating require service filter {}", requiredService.trim(), e); + LOGGER.error("Error creating require service filter {}", requiredService.trim(), e); } } } @@ -120,7 +120,7 @@ public void init() { bundleContext.addServiceListener(this); startupTime = System.currentTimeMillis(); System.out.println("Initializing Unomi..."); - logger.info("Bundle watcher initialized."); + LOGGER.info("Bundle watcher initialized."); } @Override @@ -138,7 +138,7 @@ public boolean allAdditionalBundleStarted() { } private void displayLogsForInactiveBundles(Map bundles) { - getInactiveBundles(bundles).forEach(inactiveBundle -> logger + getInactiveBundles(bundles).forEach(inactiveBundle -> LOGGER .warn("The bundle {} is in not active, some errors could happen when using the application", inactiveBundle)); } @@ -152,7 +152,7 @@ public void destroy() { if (scheduledFuture != null) { scheduledFuture.cancel(true); } - logger.info("Bundle watcher shutdown."); + LOGGER.info("Bundle watcher shutdown."); } public void checkExistingBundles() { @@ -184,7 +184,7 @@ private void checkInBundlesList(Bundle bundle, Map bundles) { private void managedBundleEvent(Bundle bundle, Map bundles, Boolean start) { if (bundle.getSymbolicName().startsWith("org.apache.unomi") && bundles.containsKey(bundle.getSymbolicName())) { - logger.info("Bundle {} was {}.", bundle.getSymbolicName(), start ? "started" : "stopped"); + LOGGER.info("Bundle {} was {}.", bundle.getSymbolicName(), start ? "started" : "stopped"); bundles.put(bundle.getSymbolicName(), start); if (start) { checkStartupComplete(); @@ -245,7 +245,7 @@ private void removeStartedService(ServiceReference serviceReference) { matchedRequiredServicesCount--; if (!shutdownMessageAlreadyDisplayed) { System.out.println("Apache Unomi shutting down..."); - logger.info("Apache Unomi no longer available, as required service {} is shutdown !", serviceReference); + LOGGER.info("Apache Unomi no longer available, as required service {} is shutdown !", serviceReference); shutdownMessageAlreadyDisplayed = true; } startupMessageAlreadyDisplayed = false; @@ -260,10 +260,10 @@ private void displayLogsForInactiveServices() { try { serviceReference = bundleContext.getServiceReferences((String) null, filterToString); } catch (InvalidSyntaxException e) { - logger.error("Failed to get the service reference for {}", filterToString, e); + LOGGER.error("Failed to get the service reference for {}", filterToString, e); } if (serviceReference == null) { - logger.warn("No service found for the filter {}, some errors could happen when using the application", filterToString); + LOGGER.warn("No service found for the filter {}, some errors could happen when using the application", filterToString); } }); } @@ -289,11 +289,11 @@ private void installFeatures() { System.out.println("Installing feature " + value); featuresService.installFeature(value, EnumSet.of(FeaturesService.Option.NoAutoRefreshManagedBundles, FeaturesService.Option.NoAutoRefreshUnmanagedBundles, FeaturesService.Option.NoAutoRefreshBundles)); - logger.info("Feature {} successfully installed in {} ms", value, System.currentTimeMillis() - featureStartupTime); + LOGGER.info("Feature {} successfully installed in {} ms", value, (System.currentTimeMillis() - featureStartupTime)); } installedFeatures.add(value); } catch (Exception e) { - logger.error("Error when installing {} feature", value, e); + LOGGER.error("Error when installing {} feature", value, e); } }); installedFeatures.forEach(value -> featuresToInstall.remove(value)); @@ -366,12 +366,12 @@ private void checkStartupComplete() { serverInfo.getServerBuildDate(), serverInfo.getServerTimestamp(), serverInfo.getServerScmBranch(), serverInfo.getServerBuildNumber()); System.out.println(versionMessage); - logger.info(versionMessage); + LOGGER.info(versionMessage); }); System.out.println("--------------------------------------------------------------------------------------------"); System.out.println("Server successfully started " + requiredBundles.size() + " bundles and " + requiredServicesFilters.size() + " required " + "services in " + totalStartupTime + " ms"); - logger.info("Server successfully started {} bundles and {} required services in {} ms", requiredBundles.size(), + LOGGER.info("Server successfully started {} bundles and {} required services in {} ms", requiredBundles.size(), requiredServicesFilters.size(), totalStartupTime); startupMessageAlreadyDisplayed = true; shutdownMessageAlreadyDisplayed = false; @@ -398,7 +398,7 @@ private List loadLogo(Bundle bundle) { } return logoLines; } catch (IOException e) { - logger.error("Error loading logo lines", e); + LOGGER.error("Error loading logo lines", e); } finally { if (bufferedReader != null) { try { diff --git a/manual/pom.xml b/manual/pom.xml index edbeaccd7..7326fbd5a 100644 --- a/manual/pom.xml +++ b/manual/pom.xml @@ -243,4 +243,4 @@ - \ No newline at end of file + diff --git a/manual/src/main/asciidoc/configuration.adoc b/manual/src/main/asciidoc/configuration.adoc index 7795d56d4..c127b247f 100644 --- a/manual/src/main/asciidoc/configuration.adoc +++ b/manual/src/main/asciidoc/configuration.adoc @@ -378,7 +378,7 @@ org.apache.unomi.security.personalization.sanitizeConditions=${env:UNOMI_SECURIT Groovy actions offer the ability to define a set of actions and action types (aka action descriptors) purely from Groovy scripts defined at runtime. -Initially submitted to Unomi through a purpose-built REST API endpoint, Groovy actions are then stored in Elasticsearch. When an event matches a rule configured to execute an action, the corresponding action is fetched from Elasticsearch and executed. +Initially submitted to Unomi through a purpose-built REST API endpoint, Groovy actions are then stored in Elasticsearch. When an event matches a rule configured to execute an action, the corresponding action is fetched from Elasticsearch and executed. ===== Anatomy of a Groovy Action @@ -401,7 +401,7 @@ Placed right before the function, the “@Action” annotation contains a set of |actionExecutor |String |YES -|Action executor contains the name of the script to call for the action type and must be prefixed with “*groovy:*”. The prefix indicates to Unomi which dispatcher to use when processing the action. +|Action executor contains the name of the script to call for the action type and must be prefixed with “*groovy:*”. The prefix indicates to Unomi which dispatcher to use when processing the action. The name must be the file name of the groovy file containing the action without the extension (*groovy:*). |name |String @@ -429,7 +429,7 @@ The function contained within the Groovy Action must be called `execute()` and i This integer serves as an indication whether the values of the session and profile should be persisted. In general, the codes used are defined in the https://github.com/apache/unomi/blob/master/api/src/main/java/org/apache/unomi/api/services/EventService.java[EventService interface]. -Each groovy actions extends by default a Base script +Each groovy actions extends by default a Base script https://github.com/apache/unomi/blob/master/extensions/groovy-actions/services/src/main/resources/META-INF/base/BaseScript.groovy[defined here] ===== REST API @@ -450,7 +450,7 @@ Delete an Action: [source,bash] ---- curl -X DELETE 'http://localhost:8181/cxs/groovyActions/' \ ---user karaf:karaf +--user karaf:karaf ---- Note that when a groovy action is deleted by the API, the action type associated with this action will also be deleted. @@ -459,12 +459,12 @@ Note that when a groovy action is deleted by the API, the action type associated In this short example, we’re going to create a Groovy Action that will be adding “Hello world!” to the logs whenever a new view event is triggered. -The first step consists in creating the groovy script on your filesystem, start by creating the file `hello-world.groovy`: +The first step consists in creating the groovy script on your filesystem, start by creating the file `helloWorldGroovyAction.groovy`: [source,groovy] ---- @Action(id = "helloWorldGroovyAction", - actionExecutor = "groovy:helloWorldAction", + actionExecutor = "groovy:helloWorldGroovyAction", parameters = [@Parameter(id = "location", type = "string", multivalued = false)]) def execute() { logger.info("Hello {}", action.getParameterValues().get("location")) @@ -472,16 +472,18 @@ def execute() { } ---- -As the last instruction of the script is `EventService.NO_CHANGE`, data will not be persisted. +As the last instruction of the script is `EventService.NO_CHANGE`, data will not be persisted. -Once the action has been created you need to submit it to Unomi (from the same folder as `hello-world.groovy`). +Once the action has been created you need to submit it to Unomi (from the same folder as `helloWorldGroovyAction.groovy`). [source,bash] ---- curl -X POST 'http://localhost:8181/cxs/groovyActions' \ --user karaf:karaf \ ---form 'file=@hello-world.groovy' +--form 'file=@helloWorldGroovyAction.groovy' ---- +Important: A bug ( https://issues.apache.org/jira/browse/UNOMI-847[UNOMI-847] ) in Apache Unomi 2.5 and lower requires the filename of a Groovy file being submitted to be the same than the id of the Groovy action (as per the example above). + Finally, register a rule to trigger execution of the groovy action: [source,bash] ---- @@ -519,7 +521,7 @@ Once you’re done with the Hello World! action, it can be deleted using the fol [source,bash] ---- curl -X DELETE 'http://localhost:8181/cxs/groovyActions/helloWorldGroovyAction' \ ---user karaf:karaf +--user karaf:karaf ---- And the corresponding rule can be deleted using the following command: @@ -544,7 +546,7 @@ import org.osgi.framework.ServiceReference import org.slf4j.Logger import org.slf4j.LoggerFactory -final Logger logger = LoggerFactory.getLogger(GroovyActionDispatcher.class.getName()); +final Logger LOGGER = LoggerFactory.getLogger(GroovyActionDispatcher.class.getName()); @Action(id = "displayNumberOfProfilesAction", actionExecutor = "groovy:DisplayNumberOfProfilesAction", description = "Display the number of existing profiles") def execute() { @@ -560,8 +562,8 @@ def execute() { ProfileService profileService = context.getService(serviceReference); // Example of displaying the number of profile - logger.info("Display profile count") - logger.info(profileService.getAllProfilesCount().toString()) + LOGGER.info("Display profile count") + LOGGER.info("{}", profileService.getAllProfilesCount().toString()) return EventService.NO_CHANGE } @@ -585,7 +587,7 @@ org.apache.unomi.services.actions;version ==== Scripting roadmap -Scripting will probably undergo major changes in future versions of Apache Unomi, with the likely retirement of MVEL in favor of Groovy Actions detailed above. +Scripting will probably undergo major changes in future versions of Apache Unomi, with the likely retirement of MVEL in favor of Groovy Actions detailed above. These changes will not happen on maintenance versions of Apache Unomi, only in the next major version. Maintenance versions will of course maintain compatibility with existing scripting solutions. @@ -635,7 +637,7 @@ highly recommended that you design your client applications to use the HTTPS por The user accounts to access the REST API are actually routed through Karaf's JAAS support, which you may find the documentation for here : -* http://karaf.apache.org/manual/latest/users-guide/security.html[http://karaf.apache.org/manual/latest/users-guide/security.html] +* https://karaf.apache.org/manual/latest/#_security_2[https://karaf.apache.org/manual/latest/#_security_2] The default username/password is @@ -839,7 +841,7 @@ sslTrustAllCertificates=true ==== Permissions -Apache Unomi requires a particular set of Elasticsearch permissions for its operation. +Apache Unomi requires a particular set of Elasticsearch permissions for its operation. If you are using Elasticsearch in a production environment, you will most likely need to fine tune permissions given to the user used by Unomi. @@ -847,3 +849,92 @@ The following permissions are required by Unomi: - required cluster privileges: `manage` OR `all` - required index privileges on unomi indices: `write, manage, read` OR `all` + +=== Health Check Extension + +The Health Check extension provides a way to check is required Unomi components are 'live'. + +It consists in a simple http endpoint that provide a JSON view of integrated health checks. It can then be used to determine if the server +is up and running and can serve requests. + +The health check endpoint is available at the following URL: /health/check and returns a simple JSON response that includes all health check provider responses. + +Basic Http Authentication enforce security for the health check endpoint using the existing karaf realm. The user needs to have the specific role **health** +to access the endpoint. Users and roles can be configured in the etc/users.properties file. By default, a login/pass health/health is configured. + +Specific configuration is located in : org.apache.unomi.healthcheck.cfg Existing health checks are using configuration from that file, including authentication realm. + +Existing health checks gives information about : +- Karaf (as soon as the karaf container is started, that check is LIVE) +- Elasticsearch (connection to elasticsearch cluster and its health) +- Unomi (unomi bundles status) +- Persistence (unomi to elasticsearch binding) +- Cluster health (unomi cluster status and nodes information) + +All healthcheck can have a status : +- DOWN (service is not available) +- UP (service is up but does not respond to request (starting or misconfigured)) +- LIVE (service is ready to serve request) +- ERROR (an error occurred during service health check) + +Any subsystem health check have a timeout of 400ms where check is cancelled and will be returned as error. + +Typical response to /health/check when unomi NOT started is : + +[source,json] +---- +[ + { + "name":"karaf", + "status":"LIVE", + "collectingTime":0 + }, + { + "name":"cluster", + "status":"DOWN", + "collectingTime":0 + }, + { + "name":"elasticsearch", + "status":"LIVE", + "collectingTime":6 + }, + { + "name":"persistence", + "status":"DOWN", + "collectingTime":0 + }, + { + "name":"unomi", + "status":"DOWN", + "collectingTime":0 + } +] +---- + +Existing health check can be extended by adding specific provider in the extension. A provider is a class that implements the HealthCheckProvider interface. + +[source,java] +---- +package org.apache.unomi.healthcheck; + +public interface HealthCheckProvider { + String name(); + HealthCheckResponse execute(); +} +---- + +Calls to provider are supposed to be done at a regular rate (every 15 seconds for example) and should be fast to execute. Feel free to include any caching strategy if needed. + + +==== Configuration + +Healthcheck extension configuration is located in the file etc/org.apache.unomi.healthcheck.cfg + +Extension can be enabled by setting the property `enabled` to `true`. An environment variable can be used to set this property : UNOMI_HEALTHCHECK_ENABLED. +You must restart the bundle for that config to take effect. + +By default, all healthcheck providers are included but the list of those included providers can be customized by setting the property `providers` with a comma separated list of provider names. An environment variable can be used to set this property : UNOMI_HEALTHCHECK_PROVIDERS. +Karaf provider is the one needed by healthcheck (always LIVE), it cannot be ignored. + +The timeout used for each health check can be set by setting the property `timeout` to the desired value in milliseconds. An environment variable can be used to set this property : UNOMI_HEALTHCHECK_TIMEOUT diff --git a/metrics/src/main/java/org/apache/unomi/metrics/commands/ViewCommand.java b/metrics/src/main/java/org/apache/unomi/metrics/commands/ViewCommand.java index b3cefe84c..1d7b74737 100644 --- a/metrics/src/main/java/org/apache/unomi/metrics/commands/ViewCommand.java +++ b/metrics/src/main/java/org/apache/unomi/metrics/commands/ViewCommand.java @@ -18,10 +18,10 @@ import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; +import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.karaf.shell.commands.Argument; import org.apache.karaf.shell.commands.Command; import org.apache.unomi.metrics.Metric; -import org.apache.unomi.persistence.spi.CustomObjectMapper; @Command(scope = "metrics", name = "view", description = "This will display all the data for a single metric ") public class ViewCommand extends MetricsCommandSupport{ @@ -40,7 +40,7 @@ protected Object doExecute() throws Exception { // the caller values easier to read. DefaultPrettyPrinter defaultPrettyPrinter = new DefaultPrettyPrinter(); defaultPrettyPrinter = defaultPrettyPrinter.withArrayIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE); - String jsonMetric = CustomObjectMapper.getObjectMapper().writer(defaultPrettyPrinter).writeValueAsString(metric); + String jsonMetric = new ObjectMapper().writer(defaultPrettyPrinter).writeValueAsString(metric); System.out.println(jsonMetric); return null; } diff --git a/package/src/main/resources/etc/org.ops4j.pax.logging.cfg b/package/src/main/resources/etc/org.ops4j.pax.logging.cfg index 43f027976..465a55e5a 100644 --- a/package/src/main/resources/etc/org.ops4j.pax.logging.cfg +++ b/package/src/main/resources/etc/org.ops4j.pax.logging.cfg @@ -18,7 +18,7 @@ ################################################################################ # Common pattern layout for appenders -log4j2.pattern = %d{ISO8601} | %-5p | %-16t | %-32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %encode{ %.-500m }{CRLF}%n +log4j2.pattern = %d{ISO8601} | %-5p | %-16t | %-32c{1} | %X{bundle.id} - %X{bundle.name} - %X{bundle.version} | %encode{ %.-500m }{CRLF}%n%sxThrowable # Root logger log4j2.rootLogger.level = ${org.apache.unomi.logs.root.level:-INFO} diff --git a/package/src/main/resources/etc/users.properties b/package/src/main/resources/etc/users.properties index 3848b1242..ee3acc547 100644 --- a/package/src/main/resources/etc/users.properties +++ b/package/src/main/resources/etc/users.properties @@ -30,4 +30,5 @@ # with the name "karaf". # karaf = ${org.apache.unomi.security.root.password:-karaf},_g_:admingroup +health = ${org.apache.unomi.healthcheck.password:-health},health _g_\:admingroup = group,admin,manager,viewer,systembundles,ssh,ROLE_UNOMI_ADMIN diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java index 538f71e4c..02b079ef6 100644 --- a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/PropertyHelper.java @@ -21,7 +21,6 @@ import org.apache.commons.beanutils.NestedNullException; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.beanutils.expression.DefaultResolver; -import org.apache.unomi.api.Profile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +33,7 @@ */ public class PropertyHelper { - private static final Logger logger = LoggerFactory.getLogger(PropertyHelper.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(PropertyHelper.class.getName()); private static DefaultResolver resolver = new DefaultResolver(); public static boolean setProperty(Object target, String propertyName, Object propertyValue, String setPropertyStrategy) { @@ -109,7 +108,7 @@ public static boolean setProperty(Object target, String propertyName, Object pro } } } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { - logger.error("Cannot set property", e); + LOGGER.error("Cannot set property", e); } return false; } @@ -169,16 +168,16 @@ public static Boolean getBooleanValue(Object setPropertyValueBoolean) { return ((Boolean) setPropertyValueBoolean); } else if (setPropertyValueBoolean instanceof Number) { if (((Number) setPropertyValueBoolean).intValue() >= 1) { - return new Boolean(true); + return Boolean.TRUE; } else { - return new Boolean(false); + return Boolean.FALSE; } } else { if (((String) setPropertyValueBoolean).equalsIgnoreCase("true") || ((String) setPropertyValueBoolean).equalsIgnoreCase("on") || ((String) setPropertyValueBoolean).equalsIgnoreCase("yes") || ((String) setPropertyValueBoolean).equalsIgnoreCase("1")) { - return new Boolean(true); + return Boolean.TRUE; } else { - return new Boolean(false); + return Boolean.FALSE; } } diff --git a/plugins/baseplugin/pom.xml b/plugins/baseplugin/pom.xml index 832f02c60..cd78499d6 100644 --- a/plugins/baseplugin/pom.xml +++ b/plugins/baseplugin/pom.xml @@ -42,6 +42,10 @@ 2.3.2 provided + + commons-collections + commons-collections + commons-beanutils commons-beanutils diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java index 258ddba91..343d8997c 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/CopyPropertiesAction.java @@ -35,7 +35,7 @@ public class CopyPropertiesAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(CopyPropertiesAction.class); + private static final Logger LOGGER = LoggerFactory.getLogger(CopyPropertiesAction.class); private ProfileService profileService; public void setProfileService(ProfileService profileService) { @@ -71,11 +71,8 @@ public int execute(Action action, Event event) { if (multipleIsExpected) { changed = PropertyHelper.setProperty(event.getProfile(), propertyName, entry.getValue(), "addValues"); } else if (entry.getValue() instanceof List) { - logger.error( - "Impossible to copy the property of type List to the profile, either a single value already exist on the profile or the property type is declared as a single value property. Enable debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("cannot copy property {}, because it's a List", mappedProperty); - } + LOGGER.error("Impossible to copy the property of type List to the profile, either a single value already exist on the profile or the property type is declared as a single value property. Enable debug log level for more information"); + LOGGER.debug("cannot copy property {}, because it's a List", mappedProperty); } else { changed = PropertyHelper.setProperty(event.getProfile(), propertyName, entry.getValue(), singleValueStrategy); } @@ -108,8 +105,7 @@ private Map getEventPropsToCopy(Action action, Event event) { propsToCopy.putAll((Map) targetProperties); } } catch (Exception e) { - logger.error("Unable to extract properties to be copied from the event to the profile using root property: {}", rootProperty, - e); + LOGGER.error("Unable to extract properties to be copied from the event to the profile using root property: {}", rootProperty, e); } return propsToCopy; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/EvaluateVisitPropertiesAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/EvaluateVisitPropertiesAction.java index f74c2ee5b..43f81cd69 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/EvaluateVisitPropertiesAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/EvaluateVisitPropertiesAction.java @@ -37,7 +37,7 @@ * Depending on the event timestamp it will adjust one or multiples of this properties accordingly to the logical chronology. */ public class EvaluateVisitPropertiesAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(EvaluateVisitPropertiesAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(EvaluateVisitPropertiesAction.class.getName()); public int execute(Action action, Event event) { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); @@ -88,12 +88,10 @@ private Date extractDateFromProperty(Profile profile, String propertyName, DateF } } } catch (ParseException e) { - logger.error("Error parsing {} date property. See debug log level for more information", propertyName); - if (logger.isDebugEnabled()) { - logger.debug("Error parsing date: {}, on profile: {}", property, profile.getItemId(), e); - } + LOGGER.error("Error parsing {} date property. See debug log level for more information", propertyName); + LOGGER.debug("Error parsing date: {}, on profile: {}", property, profile.getItemId(), e); } return date; } -} \ No newline at end of file +} diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/IncrementPropertyAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/IncrementPropertyAction.java index c4b1dfeb1..275d36c28 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/IncrementPropertyAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/IncrementPropertyAction.java @@ -31,7 +31,7 @@ import java.util.Map; public class IncrementPropertyAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(IncrementPropertyAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(IncrementPropertyAction.class.getName()); @Override public int execute(final Action action, final Event event) { @@ -51,15 +51,11 @@ public int execute(final Action action, final Event event) { return storeInSession ? EventService.SESSION_UPDATED : EventService.PROFILE_UPDATED; } } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { - logger.warn("Error resolving nested property of object. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Error resolving nested property of item: {}", storeInSession ? session : profile, e); - } + LOGGER.warn("Error resolving nested property of object. See debug log level for more information"); + LOGGER.debug("Error resolving nested property of item: {}", storeInSession ? session : profile, e); } catch (IllegalStateException ee) { - logger.warn("Error increment existing property, because existing property doesn't have expected type. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug(ee.getMessage(), ee); - } + LOGGER.warn("Error increment existing property, because existing property doesn't have expected type. See debug log level for more information"); + LOGGER.debug("{}", ee.getMessage(), ee); } return EventService.NO_CHANGE; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java index 3ebb0342a..be18678b7 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/ModifyConsentAction.java @@ -34,7 +34,7 @@ */ public class ModifyConsentAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(ModifyConsentAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ModifyConsentAction.class.getName()); public static final String CONSENT_PROPERTY_NAME = "consent"; @@ -52,13 +52,11 @@ public int execute(Action action, Event event) { consent = new Consent(consentMap, dateFormat); isProfileUpdated = profile.setConsent(consent); } catch (ParseException e) { - logger.error("Error parsing consent dates (statusDate or revokeDate). See debug log level to have more information"); - if (logger.isDebugEnabled()) { - logger.debug("Error parsing consent dates (statusDate or revokeDate).", e); - } + LOGGER.error("Error parsing consent dates (statusDate or revokeDate). See debug log level to have more information"); + LOGGER.debug("Error parsing consent dates (statusDate or revokeDate).", e); } } else { - logger.warn("Event properties for modifyConsent is missing typeIdentifier and grant properties. We will ignore this event."); + LOGGER.warn("Event properties for modifyConsent is missing typeIdentifier and grant properties. We will ignore this event."); } } return isProfileUpdated ? EventService.PROFILE_UPDATED : EventService.NO_CHANGE; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java index 25743b96b..f67eb158b 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/SetPropertyAction.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicLong; public class SetPropertyAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(SetPropertyAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SetPropertyAction.class.getName()); private EventService eventService; // TODO Temporary solution that should be handle by: https://issues.apache.org/jira/browse/UNOMI-630 (Implement a global solution to avoid multiple same log pollution.) @@ -127,7 +127,7 @@ private Object getPropertyValue(Action action, Event event) { long timeStamp = nowDeprecatedLogTimestamp.get(); long currentTimeStamp = new Date().getTime(); if (timeStamp == 0 || (timeStamp + TimeUnit.HOURS.toMillis(6) < currentTimeStamp)) { - logger.warn("SetPropertyAction with setPropertyValue: 'now' is deprecated, " + + LOGGER.warn("SetPropertyAction with setPropertyValue: 'now' is deprecated, " + "please use 'setPropertyValueCurrentEventTimestamp' or 'setPropertyValueCurrentDate' instead of 'setPropertyValue'"); nowDeprecatedLogTimestamp.set(currentTimeStamp); } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/UpdatePropertiesAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/UpdatePropertiesAction.java index 385918e67..eb890ad15 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/UpdatePropertiesAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/UpdatePropertiesAction.java @@ -44,7 +44,7 @@ public class UpdatePropertiesAction implements ActionExecutor { public static final String TARGET_TYPE_PROFILE = "profile"; - Logger logger = LoggerFactory.getLogger(UpdatePropertiesAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(UpdatePropertiesAction.class.getName()); private ProfileService profileService; private EventService eventService; @@ -59,7 +59,7 @@ public int execute(Action action, Event event) { if (StringUtils.isNotBlank(targetId) && event.getProfile() != null && !targetId.equals(event.getProfile().getItemId())) { target = TARGET_TYPE_PROFILE.equals(targetType) ? profileService.load(targetId) : profileService.loadPersona(targetId); if (target == null) { - logger.warn("No profile found with Id : {}. Update skipped.", targetId); + LOGGER.warn("No profile found with Id : {}. Update skipped.", targetId); return EventService.NO_CHANGE; } } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java index b27c5ef6d..fa33b29b6 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java @@ -34,7 +34,7 @@ */ public class BooleanConditionESQueryBuilder implements ConditionESQueryBuilder { - private static final Logger logger = LoggerFactory.getLogger(BooleanConditionESQueryBuilder.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(BooleanConditionESQueryBuilder.class.getName()); @Override public QueryBuilder buildQuery(Condition condition, Map context, @@ -60,20 +60,16 @@ public QueryBuilder buildQuery(Condition condition, Map context, boolQueryBuilder.must(andFilter); } } else { - logger.warn("Null filter for boolean AND sub condition. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Null filter for boolean AND sub condition {}", conditions.get(i)); - } + LOGGER.warn("Null filter for boolean AND sub condition. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) LOGGER.debug("Null filter for boolean AND sub condition {}", conditions.get(i)); } } else { QueryBuilder orFilter = dispatcher.buildFilter(conditions.get(i), context); if (orFilter != null) { boolQueryBuilder.should(orFilter); } else { - logger.warn("Null filter for boolean OR sub condition. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Null filter for boolean OR sub condition {}", conditions.get(i)); - } + LOGGER.warn("Null filter for boolean OR sub condition. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) LOGGER.debug("Null filter for boolean OR sub condition {}", conditions.get(i)); } } } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java index 5650042fa..77c3240b8 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/HardcodedPropertyAccessorRegistry.java @@ -21,8 +21,6 @@ import org.apache.unomi.api.goals.Goal; import org.apache.unomi.api.rules.Rule; import org.apache.unomi.plugins.baseplugin.conditions.accessors.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.*; import java.util.stream.Collectors; @@ -33,8 +31,6 @@ */ public class HardcodedPropertyAccessorRegistry { - private static final Logger logger = LoggerFactory.getLogger(HardcodedPropertyAccessorRegistry.class.getName()); - protected Map, HardcodedPropertyAccessor> propertyAccessors = new HashMap<>(); protected Map, List>> cachedClassAncestors = new HashMap<>(); diff --git a/plugins/kafka-injector/src/main/java/org/apache/unomi/kafka/KafkaInjector.java b/plugins/kafka-injector/src/main/java/org/apache/unomi/kafka/KafkaInjector.java index 108ea8cd6..4f8154b1b 100644 --- a/plugins/kafka-injector/src/main/java/org/apache/unomi/kafka/KafkaInjector.java +++ b/plugins/kafka-injector/src/main/java/org/apache/unomi/kafka/KafkaInjector.java @@ -30,13 +30,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.Dictionary; -import java.util.HashMap; -import java.util.Map; import java.util.Properties; import java.util.concurrent.Executors; diff --git a/plugins/mail/src/main/java/org/apache/unomi/plugins/mail/actions/SendMailAction.java b/plugins/mail/src/main/java/org/apache/unomi/plugins/mail/actions/SendMailAction.java index 3d73e0b32..621d377f1 100644 --- a/plugins/mail/src/main/java/org/apache/unomi/plugins/mail/actions/SendMailAction.java +++ b/plugins/mail/src/main/java/org/apache/unomi/plugins/mail/actions/SendMailAction.java @@ -38,7 +38,7 @@ import java.util.Map; public class SendMailAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(SendMailAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SendMailAction.class.getName()); private PersistenceService persistenceService; @@ -97,7 +97,7 @@ public int execute(Action action, Event event) { if (profileNotif != null && profileNotif.get(notifType) != null && ((HashMap) profileNotif.get(notifType)).get(notifTypeId) != null) { Integer notifTypeAck = (Integer) ((HashMap) profileNotif.get(notifType) ).get(notifTypeId); if(notifyOnce.booleanValue() && notifTypeAck > 0){ - logger.info("Notification "+notifType+" already sent for the profile "+event.getProfileId()); + LOGGER.info("Notification {} already sent for the profile {}", notifType, event.getProfileId()); return EventService.NO_CHANGE; }else{ ((HashMap) profileNotif.get(notifType) ).put(notifTypeId, notifTypeAck+1); @@ -158,7 +158,7 @@ public int execute(Action action, Event event) { // send the email email.send(); } catch (EmailException e) { - logger.error("Cannot send mail",e); + LOGGER.error("Cannot send mail",e); } return EventService.NO_CHANGE; diff --git a/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java b/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java index 58527fed7..a14edbfa8 100644 --- a/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java +++ b/plugins/request/src/main/java/org/apache/unomi/plugins/request/actions/SetRemoteHostInfoAction.java @@ -43,7 +43,7 @@ import java.util.Map; public class SetRemoteHostInfoAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(SetRemoteHostInfoAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SetRemoteHostInfoAction.class.getName()); private UserAgentDetectorServiceImpl userAgentDetectorService; @@ -115,28 +115,20 @@ public int execute(Action action, Event event) { } String remoteAddr = httpServletRequest.getRemoteAddr(); - if (logger.isDebugEnabled()) { - logger.debug("Remote address is " + remoteAddr); - } + LOGGER.debug("Remote address is {}", remoteAddr); String remoteAddrParameter = httpServletRequest.getParameter("remoteAddr"); - if (logger.isDebugEnabled()) { - logger.debug("Remote address param is " + remoteAddrParameter); - } + LOGGER.debug("Remote address param is {}", remoteAddrParameter); String xff = httpServletRequest.getHeader("X-Forwarded-For"); - if (logger.isDebugEnabled()) { - logger.debug("X-Forwarded-For is " + xff); - } - if (remoteAddrParameter != null && remoteAddrParameter.length() > 0) { + LOGGER.debug("X-Forwarded-For is {}", xff); + if (remoteAddrParameter != null && !remoteAddrParameter.isEmpty()) { remoteAddr = remoteAddrParameter; - } else if (xff != null && !xff.equals("")) { + } else if (xff != null && !xff.isEmpty()) { if (xff.indexOf(',') > -1) { xff = xff.substring(0, xff.indexOf(',')); } remoteAddr = xff; } - if (logger.isDebugEnabled()) { - logger.debug("Remote address used to localized is " + remoteAddr); - } + LOGGER.debug("Remote address used to localized is {}", remoteAddr); try { if (isAValidIPAddress(remoteAddr)) { @@ -156,7 +148,7 @@ public int execute(Action action, Event event) { session.setProperty("countryAndCity", session.getProperty("sessionCountryName") + "@@" + session.getProperty("sessionCity") + "@@" + session.getProperty("sessionAdminSubDiv1") + "@@" + session.getProperty("sessionAdminSubDiv2")); } catch (Exception e) { - logger.error("Cannot lookup IP", e); + LOGGER.error("Cannot lookup IP", e); } @@ -189,7 +181,7 @@ public void postConstruct() { try { this.databaseReader = new DatabaseReader.Builder(database).build(); } catch (IOException e) { - logger.error("Cannot read IP database", e); + LOGGER.error("Cannot read IP database", e); } } @@ -213,7 +205,7 @@ private boolean ipLookupInDatabase(String remoteAddr, Session session) { session.setProperty("sessionCityId", cityResponse.getCity().getGeoNameId()); } - if (cityResponse.getSubdivisions().size() > 0) { + if (!cityResponse.getSubdivisions().isEmpty()) { session.setProperty("sessionAdminSubDiv1", cityResponse.getSubdivisions().get(0).getGeoNameId()); } if (cityResponse.getSubdivisions().size() > 1) { @@ -232,10 +224,8 @@ private boolean ipLookupInDatabase(String remoteAddr, Session session) { } return true; } catch (IOException | GeoIp2Exception e) { - logger.warn("Cannot resolve IP, enable debug log level for complete stacktrace"); - if (logger.isDebugEnabled()) { - logger.debug("Cannot resolve IP: {}", remoteAddr, e); - } + LOGGER.warn("Cannot resolve IP, enable debug log level for complete stacktrace"); + LOGGER.debug("Cannot resolve IP: {}", remoteAddr, e); } return false; } @@ -246,10 +236,8 @@ private static boolean isAValidIPAddress(String remoteAddr) { try { addr = InetAddress.getByName(remoteAddr); } catch (UnknownHostException e) { - logger.warn("Cannot resolve IP, enable debug log level for complete stacktrace"); - if (logger.isDebugEnabled()) { - logger.debug("Cannot resolve IP: {}", remoteAddr, e); - } + LOGGER.warn("Cannot resolve IP, enable debug log level for complete stacktrace"); + LOGGER.debug("Cannot resolve IP: {}", remoteAddr, e); return false; } // Check if the address is a valid special local or loop back diff --git a/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java b/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java index fc379bd7b..de1e9ea20 100644 --- a/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java +++ b/plugins/request/src/main/java/org/apache/unomi/plugins/request/useragent/UserAgentDetectorServiceImpl.java @@ -28,7 +28,7 @@ */ public class UserAgentDetectorServiceImpl { - private static final Logger logger = LoggerFactory.getLogger(UserAgentDetectorServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(UserAgentDetectorServiceImpl.class.getName()); private UserAgentAnalyzer userAgentAnalyzer; @@ -50,7 +50,7 @@ public void postConstruct() { // Use custom cache for jdk8 compatibility if (getCurrentJVMMajorVersion() < 11) { - logger.info("Use JVM 8 compliant version of the agent analyzer caching"); + LOGGER.info("Use JVM 8 compliant version of the agent analyzer caching"); userAgentAnalyzerBuilder.useJava8CompatibleCaching(); } @@ -64,7 +64,7 @@ public void postConstruct() { .withField(nl.basjes.parse.useragent.UserAgent.DEVICE_BRAND) .build(); this.userAgentAnalyzer.initializeMatchers(); - logger.info("UserAgentDetector service initialized."); + LOGGER.info("UserAgentDetector service initialized."); } private int getCurrentJVMMajorVersion() { @@ -83,7 +83,7 @@ public void preDestroy() { userAgentAnalyzer.destroy(); userAgentAnalyzer = null; } - logger.info("UserAgentDetector service shutdown."); + LOGGER.info("UserAgentDetector service shutdown."); } public UserAgent parseUserAgent(String header) { @@ -98,9 +98,7 @@ public UserAgent parseUserAgent(String header) { userAgent.setUserAgentName(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.AGENT_NAME)); userAgent.setUserAgentVersion(yauaaAgent.getValue(nl.basjes.parse.useragent.UserAgent.AGENT_VERSION)); - if (logger.isDebugEnabled()) { - logger.debug(userAgent.toString()); - } + LOGGER.debug("{}", userAgent); return userAgent; } diff --git a/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java b/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java index 3c9c7aed2..019fe92ae 100644 --- a/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java +++ b/plugins/request/src/test/java/org/apache/unomi/plugins/request/actions/UserAgentDetectorTest.java @@ -21,7 +21,6 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import java.util.logging.Logger; import org.apache.unomi.plugins.request.useragent.UserAgent; import org.apache.unomi.plugins.request.useragent.UserAgentDetectorServiceImpl; @@ -30,11 +29,13 @@ import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class UserAgentDetectorTest { - private static final Logger logger = Logger.getLogger(UserAgentDetectorTest.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(UserAgentDetectorTest.class.getName()); private UserAgentDetectorServiceImpl userAgentDetectorService; @@ -44,7 +45,7 @@ public void init() { this.userAgentDetectorService = new UserAgentDetectorServiceImpl(); this.userAgentDetectorService.postConstruct(); long end = System.currentTimeMillis(); - logger.info("Duration starting user agent (in msec) > " + (end - start)); + LOGGER.info("Duration starting user agent (in msec) > {}", end - start); } @After @@ -59,8 +60,8 @@ public void testFirstUserAgentDetection() { long start = System.currentTimeMillis(); UserAgent agent = this.userAgentDetectorService.parseUserAgent(header); long end = System.currentTimeMillis(); - logger.info("Duration user agent parsing (in msec) > " + (end - start)); - logger.info(agent.toString()); + LOGGER.info("Duration user agent parsing (in msec) > {}", end - start); + LOGGER.info(agent.toString()); } @Test @@ -69,7 +70,7 @@ public void testUserAgentDetectionPerformance() throws InterruptedException { ExecutorService executorService = Executors.newFixedThreadPool(3000); for (int cpt = 1; cpt < 6; cpt++) { - logger.info("Execution " + cpt + "/5"); + LOGGER.info("Execution {}/5", cpt); executeWorker(executorService, workerCount); } } @@ -82,7 +83,7 @@ private void executeWorker(ExecutorService executorService, int workerCount) thr } executorService.invokeAll(callables); long totalTime = System.currentTimeMillis() - startTime; - logger.info("AgentWorker workers completed execution in " + totalTime + "ms"); + LOGGER.info("AgentWorker workers completed execution in {}ms", totalTime); } private class AgentWorker implements Callable { diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java index 4dba00ab0..92e75277a 100644 --- a/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java +++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/ContextRequestDeserializer.java @@ -29,8 +29,6 @@ import org.apache.unomi.rest.exception.InvalidRequestException; import org.apache.unomi.schema.api.SchemaService; import org.apache.unomi.utils.HttpUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; @@ -42,8 +40,6 @@ */ public class ContextRequestDeserializer extends StdDeserializer { - private static final Logger logger = LoggerFactory.getLogger(ContextRequestDeserializer.class); - private final SchemaService schemaService; public ContextRequestDeserializer(SchemaService schemaRegistry) { diff --git a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java index b55e4f8c5..c1f3aea02 100644 --- a/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java +++ b/rest/src/main/java/org/apache/unomi/rest/deserializers/EventsCollectorRequestDeserializer.java @@ -27,8 +27,6 @@ import org.apache.unomi.rest.exception.InvalidRequestException; import org.apache.unomi.schema.api.SchemaService; import org.apache.unomi.utils.HttpUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.ArrayList; @@ -39,8 +37,6 @@ */ public class EventsCollectorRequestDeserializer extends StdDeserializer { - private static final Logger logger = LoggerFactory.getLogger(EventsCollectorRequestDeserializer.class); - private final SchemaService schemaService; public EventsCollectorRequestDeserializer(SchemaService schemaRegistry) { diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/CampaignsServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/CampaignsServiceEndPoint.java index f01d153c7..032dedd6f 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/CampaignsServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/CampaignsServiceEndPoint.java @@ -51,13 +51,13 @@ @Component(service=CampaignsServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class CampaignsServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(CampaignsServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(CampaignsServiceEndPoint.class.getName()); @Reference private GoalsService goalsService; public CampaignsServiceEndPoint() { - logger.info("Initializing campaigns service endpoint..."); + LOGGER.info("Initializing campaigns service endpoint..."); } @WebMethod(exclude=true) diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ClusterServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ClusterServiceEndPoint.java index d0c7cf29b..a2f9ddeb4 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ClusterServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ClusterServiceEndPoint.java @@ -47,7 +47,7 @@ @Path("/cluster") @Component(service=ClusterServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class ClusterServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(ClusterServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ClusterServiceEndPoint.class.getName()); @Context private MessageContext messageContext; @@ -56,7 +56,7 @@ public class ClusterServiceEndPoint { private ClusterService clusterService; public ClusterServiceEndPoint() { - logger.info("Initializing cluster service endpoint..."); + LOGGER.info("Initializing cluster service endpoint..."); } @WebMethod(exclude = true) @@ -92,10 +92,8 @@ public void purge(@PathParam("date") String date) { try { clusterService.purge(new SimpleDateFormat("yyyy-MM-dd").parse(date)); } catch (ParseException e) { - logger.error("Cannot parse date, expected format is: yyyy-MM-dd. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Cannot parse date: {}", date, e); - } + LOGGER.error("Cannot parse date, expected format is: yyyy-MM-dd. See debug log level for more information"); + LOGGER.debug("Cannot parse date: {}", date, e); } } diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java index df04e6d6c..1d50168b2 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ContextJsonEndpoint.java @@ -51,7 +51,7 @@ @Path("/") @Component(service = ContextJsonEndpoint.class, property = "osgi.jaxrs.resource=true") public class ContextJsonEndpoint { - private static final Logger logger = LoggerFactory.getLogger(ContextJsonEndpoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ContextJsonEndpoint.class.getName()); private final boolean sanitizeConditions = Boolean .parseBoolean(System.getProperty("org.apache.unomi.security.personalization.sanitizeConditions", "true")); @@ -282,7 +282,7 @@ private void processOverrides(ContextRequest contextRequest, Profile profile, Se } public void destroy() { - logger.info("Context servlet shutdown."); + LOGGER.info("Context servlet shutdown."); } private List sanitizePersonalizedContentObjects( @@ -342,10 +342,8 @@ private Object sanitizeValue(Object value) { if (value instanceof String) { String stringValue = (String) value; if (stringValue.startsWith("script::") || stringValue.startsWith("parameter::")) { - logger.warn("Scripting detected in context request, filtering out. See debug level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Scripting detected in context request with value {}, filtering out...", value); - } + LOGGER.warn("Scripting detected in context request, filtering out. See debug level for more information"); + LOGGER.debug("Scripting detected in context request with value {}, filtering out...", value); return null; } else { return stringValue; diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/DefinitionsServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/DefinitionsServiceEndPoint.java index acd76ba2b..37353d2f1 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/DefinitionsServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/DefinitionsServiceEndPoint.java @@ -30,8 +30,6 @@ import org.apache.unomi.rest.service.impl.LocalizationHelper; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.jws.WebMethod; import javax.jws.WebService; @@ -51,8 +49,6 @@ @Path("/definitions") @Component(service=DefinitionsServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class DefinitionsServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(DefinitionsServiceEndPoint.class.getName()); - @Reference private DefinitionsService definitionsService; diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java index 83a656e4e..8b2b2a7c1 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/QueryServiceEndPoint.java @@ -50,7 +50,7 @@ @Path("/query") @Component(service=QueryServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class QueryServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(QueryServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(QueryServiceEndPoint.class.getName()); @Reference private QueryService queryService; @@ -149,7 +149,7 @@ public long getQueryCount(@PathParam("type") String type, @QueryParam("validate" count = queryService.getQueryCount(type, condition); } catch (IllegalArgumentException e) { if(validate == null || validate) { - logger.error(e.getMessage(), e); + LOGGER.error("{}", e.getMessage(), e); response.setStatus(Response.Status.BAD_REQUEST.getStatusCode()); } } diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ScopeServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ScopeServiceEndPoint.java index cc4110b12..a9dc82041 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ScopeServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ScopeServiceEndPoint.java @@ -49,13 +49,13 @@ @Component(service = ScopeServiceEndPoint.class, property = "osgi.jaxrs.resource=true") public class ScopeServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(ScopeServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ScopeServiceEndPoint.class.getName()); @Reference private ScopeService scopeService; public ScopeServiceEndPoint() { - logger.info("Initializing scope service endpoint..."); + LOGGER.info("Initializing scope service endpoint..."); } @WebMethod(exclude = true) diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ScoringServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ScoringServiceEndPoint.java index bf3176a55..2c4dda495 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ScoringServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ScoringServiceEndPoint.java @@ -50,13 +50,13 @@ @Component(service=ScoringServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class ScoringServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(ScoringServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ScoringServiceEndPoint.class.getName()); @Reference private SegmentService segmentService; public ScoringServiceEndPoint() { - logger.info("Initializing scoring service endpoint..."); + LOGGER.info("Initializing scoring service endpoint..."); } @WebMethod(exclude = true) diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/UserListServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/UserListServiceEndPoint.java index 468e28edb..910f7564f 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/UserListServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/UserListServiceEndPoint.java @@ -50,13 +50,13 @@ @Component(service=UserListServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class UserListServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(UserListServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(UserListServiceEndPoint.class.getName()); @Reference private UserListService userListService; public UserListServiceEndPoint() { - logger.info("Initializing user lists service endpoint..."); + LOGGER.info("Initializing user lists service endpoint..."); } @WebMethod(exclude=true) diff --git a/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java index c793f602f..b2e09fea2 100644 --- a/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java +++ b/rest/src/main/java/org/apache/unomi/rest/exception/InvalidRequestExceptionMapper.java @@ -28,12 +28,12 @@ @Provider @Component(service = ExceptionMapper.class) public class InvalidRequestExceptionMapper implements ExceptionMapper { - private static final Logger logger = LoggerFactory.getLogger(InvalidRequestExceptionMapper.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(InvalidRequestExceptionMapper.class.getName()); @Override public Response toResponse(InvalidRequestException exception) { - logger.error("{} - set InvalidRequestExceptionMapper to debug level to get full error", exception.getMessage()); - logger.debug("error", exception); + LOGGER.error("{} - set InvalidRequestExceptionMapper to debug level to get full error", exception.getMessage()); + LOGGER.debug("error", exception); return Response.status(Response.Status.BAD_REQUEST).header("Content-Type", MediaType.TEXT_PLAIN) .entity("Request rejected by the server because: " + exception.getResponseMessage()).build(); diff --git a/rest/src/main/java/org/apache/unomi/rest/exception/RuntimeExceptionMapper.java b/rest/src/main/java/org/apache/unomi/rest/exception/RuntimeExceptionMapper.java index 00ee3dce1..69cb70813 100644 --- a/rest/src/main/java/org/apache/unomi/rest/exception/RuntimeExceptionMapper.java +++ b/rest/src/main/java/org/apache/unomi/rest/exception/RuntimeExceptionMapper.java @@ -31,19 +31,19 @@ @Provider @Component(service=ExceptionMapper.class) public class RuntimeExceptionMapper implements ExceptionMapper { - private static final Logger logger = LoggerFactory.getLogger(RuntimeExceptionMapper.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(RuntimeExceptionMapper.class.getName()); @Override public Response toResponse(RuntimeException exception) { HashMap body = new HashMap<>(); body.put("errorMessage", "internalServerError"); - logger.error( + LOGGER.error( "Internal server error {}: {} in {} (Set RuntimeExceptionMapper in debug to get the full stacktrace)", exception.getMessage(), exception, ArrayUtils.isEmpty(exception.getStackTrace()) ? "Stack not available" : exception.getStackTrace()[0] ); - logger.debug("{}", exception.getMessage(), exception); + LOGGER.debug("{}", exception.getMessage(), exception); return Response.status(Response.Status.INTERNAL_SERVER_ERROR).header("Content-Type", MediaType.APPLICATION_JSON).entity(body).build(); } } diff --git a/rest/src/main/java/org/apache/unomi/rest/exception/ValidationExceptionMapper.java b/rest/src/main/java/org/apache/unomi/rest/exception/ValidationExceptionMapper.java index 98ec93700..b26023e40 100644 --- a/rest/src/main/java/org/apache/unomi/rest/exception/ValidationExceptionMapper.java +++ b/rest/src/main/java/org/apache/unomi/rest/exception/ValidationExceptionMapper.java @@ -29,17 +29,13 @@ @Provider @Component(service = ExceptionMapper.class) public class ValidationExceptionMapper implements ExceptionMapper { - private static final Logger logger = LoggerFactory.getLogger(ValidationExceptionMapper.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ValidationExceptionMapper.class.getName()); @Override public Response toResponse(ConstraintViolationException exception) { exception.getConstraintViolations().forEach(constraintViolation -> { - if (logger.isDebugEnabled()) { - logger.debug(String.format("value %s from %s %s", constraintViolation.getInvalidValue(), - constraintViolation.getPropertyPath().toString(), constraintViolation.getMessage()), exception); - } - logger.error(constraintViolation.getPropertyPath().toString() + " " + constraintViolation.getMessage() + ". Enable debug log " - + "level for more informations about the invalid value received"); + LOGGER.error("{} {}. {}", constraintViolation.getPropertyPath(), constraintViolation.getMessage(), (LOGGER.isDebugEnabled())?"":"Enable debug log level for more information about the invalid value received"); + if (LOGGER.isDebugEnabled()) LOGGER.debug("value {} from {} {}", constraintViolation.getInvalidValue(), constraintViolation.getPropertyPath(), constraintViolation.getMessage(), exception); }); return Response.status(Response.Status.BAD_REQUEST).header("Content-Type", MediaType.TEXT_PLAIN) diff --git a/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java b/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java index f2b85feb7..1f49acd13 100644 --- a/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java +++ b/rest/src/main/java/org/apache/unomi/rest/server/RestServer.java @@ -60,7 +60,7 @@ @Component public class RestServer { - private static final Logger logger = LoggerFactory.getLogger(RestServer.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(RestServer.class.getName()); private Server server; private BundleContext bundleContext; @@ -124,15 +124,15 @@ public void activate(ComponentContext componentContext) throws Exception { public Object addingService(ServiceReference reference) { Object serviceBean = bundleContext.getService(reference); while (serviceBean == null) { - logger.info("Waiting for service " + reference.getProperty("objectClass") + " to become available..."); + LOGGER.info("Waiting for service {} to become available...", reference.getProperty("objectClass")); serviceBean = bundleContext.getService(reference); try { Thread.sleep(100); } catch (InterruptedException e) { - logger.warn("Interrupted thread exception", e); + LOGGER.warn("Interrupted thread exception", e); } } - logger.info("Registering JAX RS service " + serviceBean.getClass().getName()); + LOGGER.info("Registering JAX RS service {}", serviceBean.getClass().getName()); serviceBeans.add(serviceBean); timeOfLastUpdate = System.currentTimeMillis(); refreshServer(); @@ -141,14 +141,14 @@ public Object addingService(ServiceReference reference) { @Override public void modifiedService(ServiceReference reference, Object service) { - logger.info("Refreshing JAX RS server because service " + service.getClass().getName() + " was modified."); + LOGGER.info("Refreshing JAX RS server because service {} was modified.", service.getClass().getName()); timeOfLastUpdate = System.currentTimeMillis(); refreshServer(); } @Override public void removedService(ServiceReference reference, Object service) { - logger.info("Removing JAX RS service " + service.getClass().getName()); + LOGGER.info("Removing JAX RS service {}", service.getClass().getName()); serviceBeans.remove(service); timeOfLastUpdate = System.currentTimeMillis(); refreshServer(); @@ -167,7 +167,7 @@ public void deactivate() throws Exception { private synchronized void refreshServer() { long now = System.currentTimeMillis(); - logger.info("Time (millis) since last update: {}", now - timeOfLastUpdate); + LOGGER.info("Time (millis) since last update: {}", now - timeOfLastUpdate); if (now - timeOfLastUpdate < startupDelay) { if (refreshTimer != null) { return; @@ -176,8 +176,7 @@ private synchronized void refreshServer() { public void run() { refreshTimer = null; refreshServer(); - logger.info( - "Refreshed server task performed on: " + new Date() + " Thread's name: " + Thread.currentThread().getName()); + LOGGER.info("Refreshed server task performed on: {} Thread's name: {}", new Date(), Thread.currentThread().getName()); } }; refreshTimer = new Timer("Timer-Refresh-REST-API"); @@ -187,16 +186,16 @@ public void run() { } if (server != null) { - logger.info("JAX RS Server: Shutting down server..."); + LOGGER.info("JAX RS Server: Shutting down server..."); server.destroy(); } if (serviceBeans.isEmpty()) { - logger.info("JAX RS Server: Server not started because no JAX RS EndPoint registered yet"); + LOGGER.info("JAX RS Server: Server not started because no JAX RS EndPoint registered yet"); return; } - logger.info("JAX RS Server: Configuring server..."); + LOGGER.info("JAX RS Server: Configuring server..."); List> inInterceptors = new ArrayList<>(); List> outInterceptors = new ArrayList<>(); @@ -249,7 +248,7 @@ public void run() { jaxrsServerFactoryBean.setOutInterceptors(outInterceptors); jaxrsServerFactoryBean.setServiceBeans(serviceBeans); - logger.info("JAX RS Server: Starting server with {} JAX RS EndPoints registered", serviceBeans.size()); + LOGGER.info("JAX RS Server: Starting server with {} JAX RS EndPoints registered", serviceBeans.size()); server = jaxrsServerFactoryBean.create(); server.getEndpoint().getEndpointInfo().setName(UNOMI_REST_SERVER_END_POINT_NAME); } diff --git a/rest/src/main/java/org/apache/unomi/rest/service/impl/LocalizationHelper.java b/rest/src/main/java/org/apache/unomi/rest/service/impl/LocalizationHelper.java index b67ebd3f7..01fd8ec7b 100644 --- a/rest/src/main/java/org/apache/unomi/rest/service/impl/LocalizationHelper.java +++ b/rest/src/main/java/org/apache/unomi/rest/service/impl/LocalizationHelper.java @@ -30,8 +30,6 @@ import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Collection; @@ -44,8 +42,6 @@ @Component(service=LocalizationHelper.class) public class LocalizationHelper { - private static final Logger logger = LoggerFactory.getLogger(LocalizationHelper.class.getName()); - private BundleContext bundleContext; @Reference diff --git a/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java b/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java index 87572eb22..2ed4b4027 100644 --- a/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java +++ b/rest/src/main/java/org/apache/unomi/utils/HttpUtils.java @@ -40,7 +40,7 @@ * This is duplicate of the class from the wab bundle, the original file will be removed once endpoints forwarded */ public class HttpUtils { - private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class); + private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class); private static final int MAX_COOKIE_AGE_IN_SECONDS = 60 * 60 * 24 * 365; // 1 year @@ -123,8 +123,6 @@ public static List filterValidEvents(ArrayNode eventsNode, SchemaService for (JsonNode event : eventsNode) { if (schemaService.isEventValid(event.toString())) { filteredEvents.add(jsonParser.getCodec().treeToValue(event, Event.class)); - } else { - logger.error("An event was rejected - switch to DEBUG log level for more information OR test the payload of your event against the \"validateEvent\" endpoint."); } } return filteredEvents; diff --git a/samples/login-integration/pom.xml b/samples/login-integration/pom.xml index 7e2e902dc..b04f60d97 100644 --- a/samples/login-integration/pom.xml +++ b/samples/login-integration/pom.xml @@ -61,4 +61,4 @@ - \ No newline at end of file + diff --git a/samples/login-integration/src/main/webapp/javascript/login-example.js b/samples/login-integration/src/main/webapp/javascript/login-example.js index 0ccdcc300..c4c80d88d 100644 --- a/samples/login-integration/src/main/webapp/javascript/login-example.js +++ b/samples/login-integration/src/main/webapp/javascript/login-example.js @@ -20,9 +20,9 @@ // We use this method to generate unique sessions IDs function generateGuid() { function s4() { - return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); + var array = new Uint16Array(1); + window.crypto.getRandomValues(array); + return array[0].toString(16).padStart(4, '0'); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + diff --git a/samples/trainingplugin/pom.xml b/samples/trainingplugin/pom.xml index 1637043a9..a865201ab 100644 --- a/samples/trainingplugin/pom.xml +++ b/samples/trainingplugin/pom.xml @@ -50,4 +50,4 @@ - \ No newline at end of file + diff --git a/samples/tweet-button-plugin/pom.xml b/samples/tweet-button-plugin/pom.xml index 3fa47e04a..e3d06ae0e 100644 --- a/samples/tweet-button-plugin/pom.xml +++ b/samples/tweet-button-plugin/pom.xml @@ -53,4 +53,4 @@ - \ No newline at end of file + diff --git a/samples/tweet-button-plugin/src/main/webapp/index.html b/samples/tweet-button-plugin/src/main/webapp/index.html index 244ae438f..7e04c997a 100644 --- a/samples/tweet-button-plugin/src/main/webapp/index.html +++ b/samples/tweet-button-plugin/src/main/webapp/index.html @@ -61,12 +61,9 @@ if (window.performance && typeof window.performance.now === "function") { d += performance.now(); //use high-precision timer if available } - var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { - var r = (d + Math.random() * 16) % 16 | 0; - d = Math.floor(d / 16); - return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); - }); - return uuid; + return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => + (+c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16) + ); } function contextRequest(successCallback, errorCallback, payload) { diff --git a/scripting/src/main/java/org/apache/unomi/scripting/ExpressionFilter.java b/scripting/src/main/java/org/apache/unomi/scripting/ExpressionFilter.java index 87669aa64..985ed17e6 100644 --- a/scripting/src/main/java/org/apache/unomi/scripting/ExpressionFilter.java +++ b/scripting/src/main/java/org/apache/unomi/scripting/ExpressionFilter.java @@ -26,7 +26,7 @@ * An expression filter is used to allow/deny scripts for execution. */ public class ExpressionFilter { - private static final Logger logger = LoggerFactory.getLogger(ExpressionFilter.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ExpressionFilter.class.getName()); private final Set allowedExpressionPatterns; private final Set forbiddenExpressionPatterns; @@ -38,19 +38,13 @@ public ExpressionFilter(Set allowedExpressionPatterns, Set for public String filter(String expression) { if (forbiddenExpressionPatterns != null && expressionMatches(expression, forbiddenExpressionPatterns)) { - logger.warn("Expression filtered because forbidden. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Expression {} is forbidden by expression filter", expression); - } - + LOGGER.warn("Expression filtered because forbidden. See debug log level for more information"); + LOGGER.debug("Expression {} is forbidden by expression filter", expression); return null; } if (allowedExpressionPatterns != null && !expressionMatches(expression, allowedExpressionPatterns)) { - logger.warn("Expression filtered because not allowed. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Expression {} is not allowed by expression filter", expression); - } - + LOGGER.warn("Expression filtered because not allowed. See debug log level for more information"); + LOGGER.debug("Expression {} is not allowed by expression filter", expression); return null; } return expression; diff --git a/scripting/src/main/java/org/apache/unomi/scripting/internal/ExpressionFilterFactoryImpl.java b/scripting/src/main/java/org/apache/unomi/scripting/internal/ExpressionFilterFactoryImpl.java index 5831842c8..bb98e6541 100644 --- a/scripting/src/main/java/org/apache/unomi/scripting/internal/ExpressionFilterFactoryImpl.java +++ b/scripting/src/main/java/org/apache/unomi/scripting/internal/ExpressionFilterFactoryImpl.java @@ -36,7 +36,7 @@ public class ExpressionFilterFactoryImpl implements ExpressionFilterFactory,BundleListener { - private static final Logger logger = LoggerFactory.getLogger(ExpressionFilterFactoryImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ExpressionFilterFactoryImpl.class.getName()); private final Map>> allowedExpressionPatternsByBundle = new HashMap<>(); @@ -87,7 +87,7 @@ private Set loadPatternsFromConfig(String propertyKey) { patterns.add(Pattern.compile(jsonPattern.asText())); } } catch (IOException e) { - logger.error("Error while loading expressions definition from " + propertyKey, e); + LOGGER.error("Error while loading expressions definition from {}", propertyKey, e); } return patterns; } @@ -135,7 +135,7 @@ private void loadPredefinedAllowedPatterns(BundleContext bundleContext) { while (predefinedAllowedExpressions.hasMoreElements()) { URL predefinedAllowedExpressionsURL = predefinedAllowedExpressions.nextElement(); - logger.debug("Found predefined allowed expressions at " + predefinedAllowedExpressionsURL + ", loading... "); + LOGGER.debug("Found predefined allowed expressions at {}, loading... ", predefinedAllowedExpressionsURL); try { JsonNode predefinedAllowedExpressionsNode = objectMapper.readTree(predefinedAllowedExpressionsURL); Set bundleAllowedExpressions = new HashSet<>(); @@ -151,7 +151,7 @@ private void loadPredefinedAllowedPatterns(BundleContext bundleContext) { existingAllowedExpressions.addAll(bundleAllowedExpressions); allowedExpressionPatternsByCollection.put(collection, existingAllowedExpressions); } catch (IOException e) { - logger.error("Error while loading expressions definition " + predefinedAllowedExpressionsURL, e); + LOGGER.error("Error while loading expressions definition {}", predefinedAllowedExpressionsURL, e); } } diff --git a/services/src/main/java/org/apache/unomi/services/actions/impl/ActionExecutorDispatcherImpl.java b/services/src/main/java/org/apache/unomi/services/actions/impl/ActionExecutorDispatcherImpl.java index defff447f..e5805a4f4 100644 --- a/services/src/main/java/org/apache/unomi/services/actions/impl/ActionExecutorDispatcherImpl.java +++ b/services/src/main/java/org/apache/unomi/services/actions/impl/ActionExecutorDispatcherImpl.java @@ -38,11 +38,11 @@ import java.util.concurrent.ConcurrentHashMap; public class ActionExecutorDispatcherImpl implements ActionExecutorDispatcher { - private static final Logger logger = LoggerFactory.getLogger(ActionExecutorDispatcherImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ActionExecutorDispatcherImpl.class.getName()); private final Map valueExtractors = new HashMap<>(11); - private Map executors = new ConcurrentHashMap<>(); + private final Map executors = new ConcurrentHashMap<>(); private MetricsService metricsService; - private Map actionDispatchers = new ConcurrentHashMap<>(); + private final Map actionDispatchers = new ConcurrentHashMap<>(); private BundleContext bundleContext; private ScriptExecutor scriptExecutor; @@ -96,7 +96,7 @@ public int execute(Action action, Event event) { String actionName = actionKey.substring(colonPos + 1); ActionDispatcher actionDispatcher = actionDispatchers.get(actionPrefix); if (actionDispatcher == null) { - logger.warn("Couldn't find any action dispatcher for prefix '{}', action {} won't execute !", actionPrefix, actionKey); + LOGGER.warn("Couldn't find any action dispatcher for prefix '{}', action {} won't execute !", actionPrefix, actionKey); } return actionDispatcher.execute(action, event, actionName); } else if (executors.containsKey(actionKey)) { @@ -109,7 +109,7 @@ public Integer execute(Object... args) throws Exception { } }.runWithTimer(); } catch (Exception e) { - logger.error("Error executing action with key=" + actionKey, e); + LOGGER.error("Error executing action with key={}", actionKey, e); } } return EventService.NO_CHANGE; diff --git a/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterServiceImpl.java index 284b250d9..ec4cfe523 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterServiceImpl.java @@ -50,7 +50,7 @@ public class ClusterServiceImpl implements ClusterService { public static final String KARAF_CELLAR_CLUSTER_NODE_CONFIGURATION = "org.apache.unomi.nodes"; public static final String KARAF_CLUSTER_CONFIGURATION_PUBLIC_ENDPOINTS = "publicEndpoints"; public static final String KARAF_CLUSTER_CONFIGURATION_INTERNAL_ENDPOINTS = "internalEndpoints"; - private static final Logger logger = LoggerFactory.getLogger(ClusterServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ClusterServiceImpl.class.getName()); PersistenceService persistenceService; private ClusterManager karafCellarClusterManager; private EventProducer karafCellarEventProducer; @@ -115,7 +115,7 @@ public void init() { boolean setupConfigOk = true; group = karafCellarGroupManager.findGroupByName(karafCellarGroupName); if (setupConfigOk && group == null) { - logger.error("Cluster group " + karafCellarGroupName + " doesn't exist, creating it..."); + LOGGER.error("Cluster group {} doesn't exist, creating it...", karafCellarGroupName); group = karafCellarGroupManager.createGroup(karafCellarGroupName); if (group != null) { setupConfigOk = true; @@ -126,13 +126,14 @@ public void init() { // check if the producer is ON if (setupConfigOk && karafCellarEventProducer.getSwitch().getStatus().equals(SwitchStatus.OFF)) { - logger.error("Cluster event producer is OFF"); + LOGGER.error("Cluster event producer is OFF"); setupConfigOk = false; } // check if the config pid is allowed if (setupConfigOk && !isClusterConfigPIDAllowed(group, Constants.CATEGORY, KARAF_CELLAR_CLUSTER_NODE_CONFIGURATION, EventType.OUTBOUND)) { - logger.error("Configuration PID " + KARAF_CELLAR_CLUSTER_NODE_CONFIGURATION + " is blocked outbound for cluster group " + karafCellarGroupName); + LOGGER.error("Configuration PID " + KARAF_CELLAR_CLUSTER_NODE_CONFIGURATION + " is blocked outbound for cluster group {}", + karafCellarGroupName); setupConfigOk = false; } @@ -162,18 +163,18 @@ public void run() { try { updateSystemStats(); } catch (Throwable t) { - logger.error("Error updating system statistics", t); + LOGGER.error("Error updating system statistics", t); } } }; schedulerService.getScheduleExecutorService().scheduleWithFixedDelay(statisticsTask, 0, nodeStatisticsUpdateFrequency, TimeUnit.MILLISECONDS); } - logger.info("Cluster service initialized."); + LOGGER.info("Cluster service initialized."); } public void destroy() { - logger.info("Cluster service shutdown."); + LOGGER.info("Cluster service shutdown."); } @Override @@ -298,14 +299,8 @@ private void updateSystemStats() { Double systemCpuLoad = null; try { systemCpuLoad = (Double) ManagementFactory.getPlatformMBeanServer().getAttribute(operatingSystemMXBeanName, "SystemCpuLoad"); - } catch (MBeanException e) { - logger.error("Error retrieving system CPU load", e); - } catch (AttributeNotFoundException e) { - logger.error("Error retrieving system CPU load", e); - } catch (InstanceNotFoundException e) { - logger.error("Error retrieving system CPU load", e); - } catch (ReflectionException e) { - logger.error("Error retrieving system CPU load", e); + } catch (MBeanException | AttributeNotFoundException | InstanceNotFoundException | ReflectionException e) { + LOGGER.error("Error retrieving system CPU load", e); } final OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); double systemLoadAverage = operatingSystemMXBean.getSystemLoadAverage(); diff --git a/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterSystemStatisticsEventHandler.java b/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterSystemStatisticsEventHandler.java index ac0488def..9eecaf4ba 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterSystemStatisticsEventHandler.java +++ b/services/src/main/java/org/apache/unomi/services/impl/cluster/ClusterSystemStatisticsEventHandler.java @@ -39,7 +39,7 @@ public class ClusterSystemStatisticsEventHandler extends CellarSupport implements EventHandler { public static final String SWITCH_ID = "org.apache.unomi.cluster.system.statistics.handler"; - private static final Logger logger = LoggerFactory.getLogger(ClusterSystemStatisticsEventHandler.class.getName()); + private static final Logger LLOGGER = LoggerFactory.getLogger(ClusterSystemStatisticsEventHandler.class.getName()); private final Switch eventSwitch = new BasicSwitch(SWITCH_ID); private ClusterServiceImpl clusterServiceImpl; @@ -59,19 +59,19 @@ public void destroy() { public void handle(ClusterSystemStatisticsEvent event) { // check if the handler is ON if (this.getSwitch().getStatus().equals(SwitchStatus.OFF)) { - logger.debug("CELLAR SYSTEM STATS: {} switch is OFF, cluster event not handled", SWITCH_ID); + LLOGGER.debug("CELLAR SYSTEM STATS: {} switch is OFF, cluster event not handled", SWITCH_ID); return; } if (groupManager == null) { //in rare cases for example right after installation this happens! - logger.error("CELLAR SYSTEM STATS: retrieved event {} while groupManager is not available yet!", event); + LLOGGER.error("CELLAR SYSTEM STATS: retrieved event {} while groupManager is not available yet!", event); return; } // check if the group is local if (!groupManager.isLocalGroup(event.getSourceGroup().getName())) { - logger.info("CELLAR SYSTEM STATS: node is not part of the event cluster group {}",event.getSourceGroup().getName()); + LLOGGER.info("CELLAR SYSTEM STATS: node is not part of the event cluster group {}",event.getSourceGroup().getName()); return; } @@ -84,7 +84,7 @@ public void handle(ClusterSystemStatisticsEvent event) { // check if it's not a "local" event if (event.getSourceNode() != null && event.getSourceNode().getId().equalsIgnoreCase(clusterManager.getNode().getId())) { - logger.trace("CELLAR SYSTEM STATS: cluster event is local (coming from local synchronizer or listener)"); + LLOGGER.trace("CELLAR SYSTEM STATS: cluster event is local (coming from local synchronizer or listener)"); return; } diff --git a/services/src/main/java/org/apache/unomi/services/impl/configsharing/ConfigSharingServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/configsharing/ConfigSharingServiceImpl.java index 88a28b863..e1ed38dfe 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/configsharing/ConfigSharingServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/configsharing/ConfigSharingServiceImpl.java @@ -33,7 +33,7 @@ */ public class ConfigSharingServiceImpl implements ConfigSharingService, SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(ConfigSharingServiceImpl.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigSharingServiceImpl.class); private BundleContext bundleContext; private Map configProperties = new ConcurrentHashMap(); @@ -53,10 +53,7 @@ public Object getProperty(String name) { @Override public Object setProperty(String name, Object newValue) { - boolean existed = false; - if (configProperties.containsKey(name)) { - existed = true; - } + boolean existed = configProperties.containsKey(name); Object oldValue = configProperties.put(name, newValue); if (existed) { firePropertyUpdatedEvent(name, oldValue, newValue); @@ -73,10 +70,7 @@ public boolean hasProperty(String name) { @Override public Object removeProperty(String name) { - boolean existed = false; - if (configProperties.containsKey(name)) { - existed = true; - } + boolean existed = configProperties.containsKey(name); Object oldValue = configProperties.remove(name); if (existed) { firePropertyRemovedEvent(name, oldValue); @@ -91,7 +85,7 @@ public Set getPropertyNames() { public void preDestroy() throws Exception { bundleContext.removeBundleListener(this); - logger.info("Config sharing service for Service is shutdown."); + LOGGER.info("Config sharing service for Service is shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -142,7 +136,7 @@ private List getListeners() { } } } catch (InvalidSyntaxException e) { - logger.error("Error retrieving listeners", e); + LOGGER.error("Error retrieving listeners", e); return listeners; } return listeners; diff --git a/services/src/main/java/org/apache/unomi/services/impl/definitions/DefinitionsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/definitions/DefinitionsServiceImpl.java index 32ccdfc6f..8fa7e1e68 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/definitions/DefinitionsServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/definitions/DefinitionsServiceImpl.java @@ -54,7 +54,7 @@ public class DefinitionsServiceImpl implements DefinitionsService, SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(DefinitionsServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(DefinitionsServiceImpl.class.getName()); private PersistenceService persistenceService; private SchedulerService schedulerService; @@ -90,7 +90,7 @@ public void setDefinitionsRefreshInterval(long definitionsRefreshInterval) { } public void postConstruct() { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); processBundleStartup(bundleContext); @@ -104,7 +104,7 @@ public void postConstruct() { bundleContext.addBundleListener(this); scheduleTypeReloads(); conditionBuilder = new ConditionBuilder(this); - logger.info("Definitions service initialized."); + LOGGER.info("Definitions service initialized."); } private void scheduleTypeReloads() { @@ -115,7 +115,7 @@ public void run() { } }; schedulerService.getScheduleExecutorService().scheduleAtFixedRate(task, 10000, definitionsRefreshInterval, TimeUnit.MILLISECONDS); - logger.info("Scheduled task for condition type loading each 10s"); + LOGGER.info("Scheduled task for condition type loading each 10s"); } public void reloadTypes(boolean refresh) { @@ -127,7 +127,7 @@ public void reloadTypes(boolean refresh) { loadConditionTypesFromPersistence(); loadActionTypesFromPersistence(); } catch (Throwable t) { - logger.error("Error loading definitions from persistence back-end", t); + LOGGER.error("Error loading definitions from persistence back-end", t); } } @@ -139,7 +139,7 @@ private void loadConditionTypesFromPersistence() { } this.conditionTypeById = newConditionTypesById; } catch (Exception e) { - logger.error("Error loading condition types from persistence service", e); + LOGGER.error("Error loading condition types from persistence service", e); } } @@ -151,7 +151,7 @@ private void loadActionTypesFromPersistence() { } this.actionTypeById = newActionTypesById; } catch (Exception e) { - logger.error("Error loading action types from persistence service", e); + LOGGER.error("Error loading action types from persistence service", e); } } @@ -191,7 +191,7 @@ private void processBundleStop(BundleContext bundleContext) { public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("Definitions service shutdown."); + LOGGER.info("Definitions service shutdown."); } private void loadPredefinedConditionTypes(BundleContext bundleContext) { @@ -202,14 +202,14 @@ private void loadPredefinedConditionTypes(BundleContext bundleContext) { while (predefinedConditionEntries.hasMoreElements()) { URL predefinedConditionURL = predefinedConditionEntries.nextElement(); - logger.debug("Found predefined condition at " + predefinedConditionURL + ", loading... "); + LOGGER.debug("Found predefined condition at {}, loading... ", predefinedConditionURL); try { ConditionType conditionType = CustomObjectMapper.getObjectMapper().readValue(predefinedConditionURL, ConditionType.class); setConditionType(conditionType); - logger.info("Predefined condition type with id {} registered", conditionType.getMetadata().getId()); + LOGGER.info("Predefined condition type with id {} registered", conditionType.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading condition definition " + predefinedConditionURL, e); + LOGGER.error("Error while loading condition definition {}", predefinedConditionURL, e); } } } @@ -223,14 +223,14 @@ private void loadPredefinedActionTypes(BundleContext bundleContext) { ArrayList pluginTypeArrayList = (ArrayList) pluginTypes.get(bundleContext.getBundle().getBundleId()); while (predefinedActionsEntries.hasMoreElements()) { URL predefinedActionURL = predefinedActionsEntries.nextElement(); - logger.debug("Found predefined action at " + predefinedActionURL + ", loading... "); + LOGGER.debug("Found predefined action at {}, loading... ", predefinedActionURL); try { ActionType actionType = CustomObjectMapper.getObjectMapper().readValue(predefinedActionURL, ActionType.class); setActionType(actionType); - logger.info("Predefined action type with id {} registered", actionType.getMetadata().getId()); + LOGGER.info("Predefined action type with id {} registered", actionType.getMetadata().getId()); } catch (Exception e) { - logger.error("Error while loading action definition " + predefinedActionURL, e); + LOGGER.error("Error while loading action definition {}", predefinedActionURL, e); } } @@ -244,7 +244,7 @@ private void loadPredefinedValueTypes(BundleContext bundleContext) { ArrayList pluginTypeArrayList = (ArrayList) pluginTypes.get(bundleContext.getBundle().getBundleId()); while (predefinedPropertiesEntries.hasMoreElements()) { URL predefinedPropertyURL = predefinedPropertiesEntries.nextElement(); - logger.debug("Found predefined value type at " + predefinedPropertyURL + ", loading... "); + LOGGER.debug("Found predefined value type at {}, loading... ", predefinedPropertyURL); try { ValueType valueType = CustomObjectMapper.getObjectMapper().readValue(predefinedPropertyURL, ValueType.class); @@ -262,11 +262,11 @@ private void loadPredefinedValueTypes(BundleContext bundleContext) { valueTypeByTag.put(tag, valueTypes); } else { // we found a tag that is not defined, we will define it automatically - logger.warn("Unknown tag {} used in property type definition {}", tag, predefinedPropertyURL); + LOGGER.warn("Unknown tag {} used in property type definition {}", tag, predefinedPropertyURL); } } } catch (Exception e) { - logger.error("Error while loading property type definition " + predefinedPropertyURL, e); + LOGGER.error("Error while loading property type definition {}", predefinedPropertyURL, e); } } @@ -411,7 +411,7 @@ private void loadPredefinedPropertyMergeStrategies(BundleContext bundleContext) ArrayList pluginTypeArrayList = (ArrayList) pluginTypes.get(bundleContext.getBundle().getBundleId()); while (predefinedPropertyMergeStrategyEntries.hasMoreElements()) { URL predefinedPropertyMergeStrategyURL = predefinedPropertyMergeStrategyEntries.nextElement(); - logger.debug("Found predefined property merge strategy type at " + predefinedPropertyMergeStrategyURL + ", loading... "); + LOGGER.debug("Found predefined property merge strategy type at " + predefinedPropertyMergeStrategyURL + ", loading... "); try { PropertyMergeStrategyType propertyMergeStrategyType = CustomObjectMapper.getObjectMapper().readValue(predefinedPropertyMergeStrategyURL, PropertyMergeStrategyType.class); @@ -419,7 +419,7 @@ private void loadPredefinedPropertyMergeStrategies(BundleContext bundleContext) propertyMergeStrategyTypeById.put(propertyMergeStrategyType.getId(), propertyMergeStrategyType); pluginTypeArrayList.add(propertyMergeStrategyType); } catch (Exception e) { - logger.error("Error while loading property type definition " + predefinedPropertyMergeStrategyURL, e); + LOGGER.error("Error while loading property type definition " + predefinedPropertyMergeStrategyURL, e); } } diff --git a/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java index a5d92232e..ec9c6f0b7 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/goals/GoalsServiceImpl.java @@ -51,7 +51,7 @@ public class GoalsServiceImpl implements GoalsService, SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(GoalsServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GoalsServiceImpl.class.getName()); private BundleContext bundleContext; @@ -78,7 +78,7 @@ public void setRulesService(RulesService rulesService) { } public void postConstruct() { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); loadPredefinedGoals(bundleContext); loadPredefinedCampaigns(bundleContext); @@ -89,12 +89,12 @@ public void postConstruct() { } } bundleContext.addBundleListener(this); - logger.info("Goal service initialized."); + LOGGER.info("Goal service initialized."); } public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("Goal service shutdown."); + LOGGER.info("Goal service shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -116,7 +116,7 @@ private void loadPredefinedGoals(BundleContext bundleContext) { while (predefinedRuleEntries.hasMoreElements()) { URL predefinedGoalURL = predefinedRuleEntries.nextElement(); - logger.debug("Found predefined goals at " + predefinedGoalURL + ", loading... "); + LOGGER.debug("Found predefined goals at {}, loading... ", predefinedGoalURL); try { Goal goal = CustomObjectMapper.getObjectMapper().readValue(predefinedGoalURL, Goal.class); @@ -125,9 +125,9 @@ private void loadPredefinedGoals(BundleContext bundleContext) { } setGoal(goal); - logger.info("Predefined goal with id {} registered", goal.getMetadata().getId()); + LOGGER.info("Predefined goal with id {} registered", goal.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading segment definition " + predefinedGoalURL, e); + LOGGER.error("Error while loading segment definition {}", predefinedGoalURL, e); } } } @@ -232,7 +232,7 @@ public void removeGoal(String goalId) { @Override public void setGoal(Goal goal) { if (goal == null) { - logger.warn("Trying to save null goal, aborting..."); + LOGGER.warn("Trying to save null goal, aborting..."); return; } ParserHelper.resolveConditionType(definitionsService, goal.getStartEvent(), "goal "+goal.getItemId()+" start event"); @@ -269,14 +269,14 @@ private void loadPredefinedCampaigns(BundleContext bundleContext) { while (predefinedRuleEntries.hasMoreElements()) { URL predefinedCampaignURL = predefinedRuleEntries.nextElement(); - logger.debug("Found predefined campaigns at " + predefinedCampaignURL + ", loading... "); + LOGGER.debug("Found predefined campaigns at {}, loading... ", predefinedCampaignURL); try { Campaign campaign = CustomObjectMapper.getObjectMapper().readValue(predefinedCampaignURL, Campaign.class); setCampaign(campaign); - logger.info("Predefined campaign with id {} registered", campaign.getMetadata().getId()); + LOGGER.info("Predefined campaign with id {} registered", campaign.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading segment definition " + predefinedCampaignURL, e); + LOGGER.error("Error while loading segment definition {}", predefinedCampaignURL, e); } } } diff --git a/services/src/main/java/org/apache/unomi/services/impl/lists/UserListServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/lists/UserListServiceImpl.java index e587ac8d3..b078ca7be 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/lists/UserListServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/lists/UserListServiceImpl.java @@ -35,7 +35,7 @@ */ public class UserListServiceImpl extends AbstractServiceImpl implements UserListService, SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(UserListServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(UserListServiceImpl.class.getName()); private BundleContext bundleContext; @@ -44,14 +44,14 @@ public void setBundleContext(BundleContext bundleContext) { } public void postConstruct() { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); bundleContext.addBundleListener(this); - logger.info("User list service initialized."); + LOGGER.info("User list service initialized."); } public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("User list service shutdown."); + LOGGER.info("User list service shutdown."); } public List getAllUserLists() { diff --git a/services/src/main/java/org/apache/unomi/services/impl/patches/PatchServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/patches/PatchServiceImpl.java index 104aa1b09..d0724ffcf 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/patches/PatchServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/patches/PatchServiceImpl.java @@ -37,7 +37,7 @@ public class PatchServiceImpl implements PatchService, SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(PatchServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(PatchServiceImpl.class.getName()); private BundleContext bundleContext; @@ -52,7 +52,7 @@ public void setPersistenceService(PersistenceService persistenceService) { } public void postConstruct() { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); processBundleStartup(bundleContext); for (Bundle bundle : bundleContext.getBundles()) { @@ -61,20 +61,18 @@ public void postConstruct() { } } bundleContext.addBundleListener(this); - logger.info("Patch service initialized."); + LOGGER.info("Patch service initialized."); } public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("Patch service shutdown."); + LOGGER.info("Patch service shutdown."); } @Override public void bundleChanged(BundleEvent event) { - switch (event.getType()) { - case BundleEvent.STARTED: - processBundleStartup(event.getBundle().getBundleContext()); - break; + if (event.getType() == BundleEvent.STARTED) { + processBundleStartup(event.getBundle().getBundleContext()); } } @@ -107,7 +105,7 @@ private void loadPredefinedPatches(BundleContext bundleContext) { patch(patch); } } catch (IOException e) { - logger.error("Error while loading patch " + patchUrl, e); + LOGGER.error("Error while loading patch {}", patchUrl, e); } } } @@ -128,7 +126,7 @@ public Item patch(Patch patch) { Item item = persistenceService.load(patch.getPatchedItemId(), type); if (item != null && patch.getOperation() != null) { - logger.info("Applying patch " + patch.getItemId()); + LOGGER.info("Applying patch {}", patch.getItemId()); switch (patch.getOperation()) { case "override": @@ -143,7 +141,7 @@ public Item patch(Patch patch) { item = CustomObjectMapper.getObjectMapper().convertValue(converted, type); persistenceService.save(item); } catch (JsonPatchException e) { - logger.error("Cannot apply patch",e); + LOGGER.error("Cannot apply patch",e); } break; case "remove": diff --git a/services/src/main/java/org/apache/unomi/services/impl/queries/QueryServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/queries/QueryServiceImpl.java index fa1799cd8..e2e8930ed 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/queries/QueryServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/queries/QueryServiceImpl.java @@ -30,7 +30,7 @@ import java.util.Map; public class QueryServiceImpl implements QueryService { - private static final Logger logger = LoggerFactory.getLogger(QueryServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(QueryServiceImpl.class.getName()); private PersistenceService persistenceService; @@ -45,11 +45,11 @@ public void setDefinitionsService(DefinitionsService definitionsService) { } public void postConstruct() { - logger.info("Query service initialized."); + LOGGER.info("Query service initialized."); } public void preDestroy() { - logger.info("Query service shutdown."); + LOGGER.info("Query service shutdown."); } @Override @@ -102,12 +102,15 @@ private Map getAggregate(String itemType, String property, Aggrega String interval = (String) query.getAggregate().getParameters().get("interval"); String format = (String) query.getAggregate().getParameters().get("format"); baseAggregate = new DateAggregate(property, interval, format); - } else if (aggregateType.equals("dateRange") && query.getAggregate().getDateRanges() != null && query.getAggregate().getDateRanges().size() > 0) { + } else if (aggregateType.equals("dateRange") && query.getAggregate().getDateRanges() != null && !query.getAggregate() + .getDateRanges().isEmpty()) { String format = (String) query.getAggregate().getParameters().get("format"); baseAggregate = new DateRangeAggregate(query.getAggregate().getProperty(), format, query.getAggregate().getDateRanges()); - } else if (aggregateType.equals("numericRange") && query.getAggregate().getNumericRanges() != null && query.getAggregate().getNumericRanges().size() > 0) { + } else if (aggregateType.equals("numericRange") && query.getAggregate().getNumericRanges() != null && !query.getAggregate() + .getNumericRanges().isEmpty()) { baseAggregate = new NumericRangeAggregate(query.getAggregate().getProperty(), query.getAggregate().getNumericRanges()); - } else if (aggregateType.equals("ipRange") && query.getAggregate().ipRanges() != null && query.getAggregate().ipRanges().size() > 0) { + } else if (aggregateType.equals("ipRange") && query.getAggregate().ipRanges() != null && !query.getAggregate() + .ipRanges().isEmpty()) { baseAggregate = new IpRangeAggregate(query.getAggregate().getProperty(), query.getAggregate().ipRanges()); } } @@ -128,4 +131,4 @@ private Map getAggregate(String itemType, String property, Aggrega return getAggregate(itemType, property); } -} \ No newline at end of file +} diff --git a/services/src/main/java/org/apache/unomi/services/impl/scheduler/SchedulerServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/scheduler/SchedulerServiceImpl.java index 89f5d3062..29e13b21e 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/scheduler/SchedulerServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/scheduler/SchedulerServiceImpl.java @@ -30,7 +30,7 @@ * @author dgaillard */ public class SchedulerServiceImpl implements SchedulerService { - private static final Logger logger = LoggerFactory.getLogger(SchedulerServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SchedulerServiceImpl.class.getName()); private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); private ScheduledExecutorService sharedScheduler; @@ -38,13 +38,13 @@ public class SchedulerServiceImpl implements SchedulerService { public void postConstruct() { sharedScheduler = Executors.newScheduledThreadPool(threadPoolSize); - logger.info("Scheduler service initialized."); + LOGGER.info("Scheduler service initialized."); } public void preDestroy() { sharedScheduler.shutdown(); scheduler.shutdown(); - logger.info("Scheduler service shutdown."); + LOGGER.info("Scheduler service shutdown."); } public void setThreadPoolSize(int threadPoolSize) { diff --git a/tools/pom.xml b/tools/pom.xml index b599d2799..4768ab711 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -34,4 +34,4 @@ shell-dev-commands - \ No newline at end of file + diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationContext.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationContext.java index 7f64b594b..4119a6c29 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationContext.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationContext.java @@ -49,7 +49,7 @@ * (not supported in case direct OSGI service usage) */ public class MigrationContext { - private static final Logger logger = LoggerFactory.getLogger(MigrationContext.class); + private static final Logger LOGGER = LoggerFactory.getLogger(MigrationContext.class); private static final Path MIGRATION_FS_HISTORY_FILE = Paths.get(System.getProperty( "karaf.data" ), MIGRATION_FS_ROOT_FOLDER, "history.json"); @@ -176,7 +176,7 @@ public String promptMessageToUser(String msg) { */ public void printMessage(String msg) { if (session == null) { - logger.info(msg); + LOGGER.info("{}: {}", new Date(), msg); } else { PrintStream writer = session.getConsole(); writer.printf("%s: %s%n",new Date(), msg); @@ -190,7 +190,7 @@ public void printMessage(String msg) { */ public void printException(String msg, Throwable t) { if (session == null) { - logger.error(msg, t); + LOGGER.error("{}", msg, t); } else { PrintStream writer = session.getConsole(); writer.println(msg); @@ -204,7 +204,7 @@ public void printException(String msg, Throwable t) { */ public void printException(String msg) { if (session == null) { - logger.error(msg); + LOGGER.error("{}", msg); } else { PrintStream writer = session.getConsole(); writer.println(msg); diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java index 795d9849a..503714a18 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java @@ -32,7 +32,6 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.util.EntityUtils; -import org.apache.karaf.shell.api.console.Session; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +49,7 @@ * @author dgaillard */ public class HttpUtils { - private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class); + private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class); public static CloseableHttpClient initHttpClient(boolean trustAllCertificates, CredentialsProvider credentialsProvider) throws IOException { long requestStartTime = System.currentTimeMillis(); @@ -85,7 +84,7 @@ public void checkServerTrusted(X509Certificate[] certs, .setConnectionManager(new PoolingHttpClientConnectionManager(socketFactoryRegistry)); } catch (NoSuchAlgorithmException | KeyManagementException e) { - logger.error("Error creating SSL Context", e); + LOGGER.error("Error creating SSL Context", e); } } else { httpClientBuilder.setConnectionManager(new PoolingHttpClientConnectionManager()); @@ -94,10 +93,7 @@ public void checkServerTrusted(X509Certificate[] certs, RequestConfig requestConfig = RequestConfig.custom().build(); httpClientBuilder.setDefaultRequestConfig(requestConfig); - if (logger.isDebugEnabled()) { - long totalRequestTime = System.currentTimeMillis() - requestStartTime; - logger.debug("Init HttpClient executed in " + totalRequestTime + "ms"); - } + if (LOGGER.isDebugEnabled()) LOGGER.debug("Init HttpClient executed in {}ms", (System.currentTimeMillis() - requestStartTime)); return httpClientBuilder.build(); } @@ -164,14 +160,12 @@ private static String getResponse(CloseableHttpClient httpClient, String url, Ma throw new HttpRequestException("Couldn't execute " + httpRequestBase + " response: " + ((entity != null) ? EntityUtils.toString(entity) : "n/a"), statusCode); } - if (logger.isDebugEnabled()) { + if (LOGGER.isDebugEnabled()) { if (entity !=null) { entity = new BufferedHttpEntity(response.getEntity()); } - logger.debug("Request " + httpRequestBase + " executed with code: " + statusCode + " and message: " + (entity!=null?EntityUtils.toString(entity):null)); - - long totalRequestTime = System.currentTimeMillis() - requestStartTime; - logger.debug("Request to Apache Unomi url: " + url + " executed in " + totalRequestTime + "ms"); + LOGGER.debug("Request {} executed with code: {} and message: {}", httpRequestBase, statusCode, entity != null ? EntityUtils.toString(entity) : null); + LOGGER.debug("Request to Apache Unomi url: {} executed in {}ms", url, (System.currentTimeMillis() - requestStartTime)); } if (entity == null) { @@ -180,8 +174,6 @@ private static String getResponse(CloseableHttpClient httpClient, String url, Ma String stringResponse = EntityUtils.toString(entity); EntityUtils.consumeQuietly(entity); - - return stringResponse; } } diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java index 2050d6ba5..2059f1dc8 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java @@ -28,6 +28,8 @@ import org.json.JSONObject; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.*; import java.net.URL; @@ -42,6 +44,8 @@ */ public class MigrationUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(MigrationUtils.class); + public static JSONObject queryWithScroll(CloseableHttpClient httpClient, String url) throws IOException { url += "?scroll=1m"; @@ -129,7 +133,7 @@ public static String extractMappingFromBundles(BundleContext bundleContext, Stri if (predefinedMappings == null) { continue; } - while (predefinedMappings.hasMoreElements()) { + if (predefinedMappings.hasMoreElements()) { URL predefinedMappingURL = predefinedMappings.nextElement(); return IOUtils.toString(predefinedMappingURL); } @@ -176,7 +180,10 @@ public static String buildRolloverPolicyCreationRequest(String baseRequest, Migr public static void moveToIndex(CloseableHttpClient httpClient, BundleContext bundleContext, String esAddress, String sourceIndexName, String targetIndexName, String painlessScript) throws Exception { String reIndexRequest = resourceAsString(bundleContext, "requestBody/2.2.0/base_reindex_request.json").replace("#source", sourceIndexName).replace("#dest", targetIndexName).replace("#painless", StringUtils.isNotEmpty(painlessScript) ? getScriptPart(painlessScript) : ""); - HttpUtils.executePostRequest(httpClient, esAddress + "/_reindex", reIndexRequest, null); + // Reindex + JSONObject task = new JSONObject(HttpUtils.executePostRequest(httpClient, esAddress + "/_reindex?wait_for_completion=false", reIndexRequest, null)); + //Wait for the reindex task to finish + waitForTaskToFinish(httpClient, esAddress, task.getString("task"), null); } public static void deleteIndex(CloseableHttpClient httpClient, String esAddress, String indexName) throws Exception { @@ -216,7 +223,9 @@ public static void reIndex(CloseableHttpClient httpClient, BundleContext bundleC // Recreate the original index with new mappings HttpUtils.executePutRequest(httpClient, esAddress + "/" + indexName, newIndexSettings, null); // Reindex data from clone - HttpUtils.executePostRequest(httpClient, esAddress + "/_reindex", reIndexRequest, null); + JSONObject task = new JSONObject(HttpUtils.executePostRequest(httpClient, esAddress + "/_reindex?wait_for_completion=false", reIndexRequest, null)); + //Wait for the reindex task to finish + waitForTaskToFinish(httpClient, esAddress, task.getString("task"), migrationContext); }); migrationContext.performMigrationStep("Reindex step for: " + indexName + " (delete clone)", () -> { @@ -249,7 +258,7 @@ public static void scrollQuery(CloseableHttpClient httpClient, String esAddress, } // no more results, delete scroll - if (hits.length() == 0) { + if (hits.isEmpty()) { if (scrollId != null) { HttpUtils.executeDeleteRequest(httpClient, esAddress + "/_search/scroll/" + scrollId, null); } @@ -281,6 +290,31 @@ public static void waitForYellowStatus(CloseableHttpClient httpClient, String es } + public static void waitForTaskToFinish(CloseableHttpClient httpClient, String esAddress, String taskId, MigrationContext migrationContext) throws IOException { + while (true) { + final JSONObject status = new JSONObject( + HttpUtils.executeGetRequest(httpClient, esAddress + "/_tasks/" + taskId + "?wait_for_completion=true&timeout=15s", + null)); + if (status.has("completed") && status.getBoolean("completed")) { + if (migrationContext != null) { + migrationContext.printMessage("Task is completed"); + } else { + LOGGER.info("Task is completed"); + } + break; + } + if (status.has("error")) { + final JSONObject error = status.getJSONObject("error"); + throw new IOException("Task error: " + error.getString("type") + " - " + error.getString("reason")); + } + if (migrationContext != null) { + migrationContext.printMessage("Waiting for Task " + taskId + " to complete"); + } else { + LOGGER.info("Waiting for Task {} to complete", taskId); + } + } + } + public interface ScrollCallback { void execute(String hits); } diff --git a/wab/src/main/java/org/apache/unomi/web/ClientServlet.java b/wab/src/main/java/org/apache/unomi/web/ClientServlet.java index 6a979f776..80a0a1910 100644 --- a/wab/src/main/java/org/apache/unomi/web/ClientServlet.java +++ b/wab/src/main/java/org/apache/unomi/web/ClientServlet.java @@ -35,7 +35,7 @@ @Deprecated public class ClientServlet extends HttpServlet { - private static final Logger logger = LoggerFactory.getLogger(ClientServlet.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ClientServlet.class.getName()); private static final long serialVersionUID = 2928875960103325238L; private String allowedProfileDownloadFormats; @@ -46,14 +46,14 @@ public class ClientServlet extends HttpServlet { public void init(ServletConfig config) throws ServletException { super.init(config); configSharingService.setProperty("allowedProfileDownloadFormats", allowedProfileDownloadFormats); - logger.info("ClientServlet initialized."); + LOGGER.info("ClientServlet initialized."); } @Override public void destroy() { super.destroy(); - logger.info("Client servlet shutdown."); + LOGGER.info("Client servlet shutdown."); } @Override diff --git a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java index bb28ac1a2..785a80a24 100644 --- a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java +++ b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java @@ -35,7 +35,7 @@ @Deprecated public class ContextServlet extends HttpServlet { private static final long serialVersionUID = 2928875830103325238L; - private static final Logger logger = LoggerFactory.getLogger(ContextServlet.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ContextServlet.class.getName()); private static final int MAX_COOKIE_AGE_IN_SECONDS = 60 * 60 * 24 * 365; // 1 year @@ -55,7 +55,7 @@ public void init(ServletConfig config) throws ServletException { configSharingService.setProperty("profileIdCookieMaxAgeInSeconds", profileIdCookieMaxAgeInSeconds); configSharingService.setProperty("profileIdCookieHttpOnly", profileIdCookieHttpOnly); configSharingService.setProperty("publicPostRequestBytesLimit", publicPostRequestBytesLimit); - logger.info("ContextServlet initialized."); + LOGGER.info("ContextServlet initialized."); } @Override @@ -65,7 +65,7 @@ public void service(HttpServletRequest request, HttpServletResponse response) th @Override public void destroy() { - logger.info("Context servlet shutdown."); + LOGGER.info("Context servlet shutdown."); } public void setProfileIdCookieDomain(String profileIdCookieDomain) { diff --git a/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java b/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java index ae623e8a0..14ca67c3c 100644 --- a/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java +++ b/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java @@ -33,18 +33,18 @@ @Deprecated public class EventsCollectorServlet extends HttpServlet { private static final long serialVersionUID = 2008054804885122957L; - private static final Logger logger = LoggerFactory.getLogger(EventsCollectorServlet.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(EventsCollectorServlet.class.getName()); @Override public void init(ServletConfig config) throws ServletException { super.init(config); - logger.info("Event collector servlet initialized."); + LOGGER.info("Event collector servlet initialized."); } @Override public void destroy() { super.destroy(); - logger.info("Event collector servlet shutdown."); + LOGGER.info("Event collector servlet shutdown."); } @Override diff --git a/wab/src/main/java/org/apache/unomi/web/HttpServletRequestForwardWrapper.java b/wab/src/main/java/org/apache/unomi/web/HttpServletRequestForwardWrapper.java index 5c93360c5..21399ddc4 100644 --- a/wab/src/main/java/org/apache/unomi/web/HttpServletRequestForwardWrapper.java +++ b/wab/src/main/java/org/apache/unomi/web/HttpServletRequestForwardWrapper.java @@ -32,7 +32,7 @@ */ class HttpServletRequestForwardWrapper extends HttpServletRequestWrapper { - private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestForwardWrapper.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(HttpServletRequestForwardWrapper.class.getName()); private static final String JSON_CONTENT_TYPE_UTF8 = "application/json;charset=UTF-8"; public HttpServletRequestForwardWrapper(HttpServletRequest request) { @@ -53,7 +53,7 @@ public static void forward(HttpServletRequest request, HttpServletResponse respo .getRequestDispatcher("/cxs" + request.getRequestURI()) .forward(requestWrapper, response); } catch (Throwable t) { // Here in order to return generic message instead of the whole stack trace in case of not caught exception - logger.error("HttpServletRequestForwardWrapper failed to forward the request", t); + LOGGER.error("HttpServletRequestForwardWrapper failed to forward the request", t); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal server error"); } } From b33711b860488b7e9f5dd132ff07c55a9e2ba2e0 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Thu, 5 Dec 2024 09:56:49 +0100 Subject: [PATCH 03/58] Additional remove commands for actions, conditions, sessions, rules to be able to fix problems with deployments --- .../unomi/api/services/EventService.java | 6 ++ .../unomi/api/services/ProfileService.java | 6 ++ .../rest/endpoints/EventServiceEndpoint.java | 16 +++- .../endpoints/ProfileServiceEndPoint.java | 21 +++- .../rest/endpoints/RulesServiceEndPoint.java | 4 +- .../endpoints/SegmentServiceEndPoint.java | 4 +- .../impl/events/EventServiceImpl.java | 29 ++++-- .../impl/profiles/ProfileServiceImpl.java | 96 ++++++++++--------- .../services/impl/rules/RulesServiceImpl.java | 34 ++++--- .../impl/segments/SegmentServiceImpl.java | 77 +++++++-------- .../unomi/shell/commands/ActionRemove.java | 45 +++++++++ .../unomi/shell/commands/ConditionRemove.java | 45 +++++++++ .../unomi/shell/commands/EventRemove.java | 45 +++++++++ .../unomi/shell/commands/ProfileRemove.java | 11 ++- .../shell/commands/RemoveCommandSupport.java | 56 +++++++++++ .../unomi/shell/commands/RuleRemove.java | 14 ++- .../unomi/shell/commands/SegmentRemove.java | 13 ++- .../unomi/shell/commands/SessionRemove.java | 45 +++++++++ 18 files changed, 427 insertions(+), 140 deletions(-) create mode 100644 tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/ActionRemove.java create mode 100644 tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/ConditionRemove.java create mode 100644 tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/EventRemove.java create mode 100644 tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/RemoveCommandSupport.java create mode 100644 tools/shell-dev-commands/src/main/java/org/apache/unomi/shell/commands/SessionRemove.java diff --git a/api/src/main/java/org/apache/unomi/api/services/EventService.java b/api/src/main/java/org/apache/unomi/api/services/EventService.java index 7c59b37fc..cd18de26e 100644 --- a/api/src/main/java/org/apache/unomi/api/services/EventService.java +++ b/api/src/main/java/org/apache/unomi/api/services/EventService.java @@ -161,4 +161,10 @@ public interface EventService { * @param profileId identifier of the profile that we want to remove it's events */ void removeProfileEvents(String profileId); + + /** + * Delete an event by specifying its event identifier + * @param eventIdentifier the unique identifier for the event + */ + void deleteEvent(String eventIdentifier); } diff --git a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java index 03da6ce9b..7da4d35b6 100644 --- a/api/src/main/java/org/apache/unomi/api/services/ProfileService.java +++ b/api/src/main/java/org/apache/unomi/api/services/ProfileService.java @@ -443,4 +443,10 @@ default Session loadSession(String sessionId) { */ @Deprecated void purgeMonthlyItems(int existsNumberOfMonths); + + /** + * Delete a session using its identifier + * @param sessionIdentifier the unique identifier for the session + */ + void deleteSession(String sessionIdentifier); } diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java index f1bac4d1f..e8d1d615f 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/EventServiceEndpoint.java @@ -26,11 +26,7 @@ import javax.jws.WebMethod; import javax.jws.WebService; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import java.util.Set; @@ -80,6 +76,16 @@ public Event getEvents(@PathParam("id") final String id) { return eventService.getEvent(id); } + /** + * Deletes an event by id. + * @param id the identifier for the event to delete + */ + @DELETE + @Path("/{id}") + public void deleteEvent(@PathParam("id") final String id) { + eventService.deleteEvent(id); + } + /** * Retrieves the list of event types identifiers that the server has processed. * @return a Set of strings that contain event type identifiers. diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java index e07f36df1..8828c16d4 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/ProfileServiceEndPoint.java @@ -58,7 +58,7 @@ @Component(service=ProfileServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class ProfileServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(ProfileServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileServiceEndPoint.class.getName()); @Reference private ProfileService profileService; @@ -73,7 +73,7 @@ public class ProfileServiceEndPoint { private LocalizationHelper localizationHelper; public ProfileServiceEndPoint() { - logger.info("Initializing profile service endpoint..."); + LOGGER.info("Initializing profile service endpoint..."); } @WebMethod(exclude = true) @@ -132,7 +132,7 @@ public Response getExportProfiles(@QueryParam("query") String query) { try { return exportProfiles(CustomObjectMapper.getObjectMapper().readValue(query, Query.class)); } catch (IOException e) { - logger.error(e.getMessage(), e); + LOGGER.error("{}", e.getMessage(), e); return Response.serverError().build(); } } @@ -151,7 +151,7 @@ public Response formExportProfiles(@FormParam("query") String query) { try { return exportProfiles(CustomObjectMapper.getObjectMapper().readValue(query, Query.class)); } catch (IOException e) { - logger.error(e.getMessage(), e); + LOGGER.error("{}", e.getMessage(), e); return Response.serverError().build(); } } @@ -399,7 +399,7 @@ public PartialList getPersonaSessions(@PathParam("personaId") String pe public Session loadSession(@PathParam("sessionId") String sessionId) throws ParseException { return profileService.loadSession(sessionId); } - + /** * Saves the specified session. * @@ -412,6 +412,17 @@ public Session saveSession(Session session) { return profileService.saveSession(session); } + /** + * Delete the session by specifying its unique identifier + * @param sessionId the session identifier for the session to delete + * @throws ParseException + */ + @DELETE + @Path("/sessions/{sessionId}") + public void deleteSession(@PathParam("sessionId") String sessionId) throws ParseException { + profileService.deleteSession(sessionId); + } + /** * Retrieves {@link Event}s for the {@link Session} identified by the provided session identifier, matching any of the provided event types, * ordered according to the specified {@code sortBy} String and paged: only {@code size} of them are retrieved, starting with the {@code offset}-th one. diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/RulesServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/RulesServiceEndPoint.java index 91298ee9e..3230e900c 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/RulesServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/RulesServiceEndPoint.java @@ -50,13 +50,13 @@ @Component(service=RulesServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class RulesServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(RulesServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(RulesServiceEndPoint.class.getName()); @Reference private RulesService rulesService; public RulesServiceEndPoint() { - logger.info("Initializing rule service endpoint..."); + LOGGER.info("Initializing rule service endpoint..."); } @WebMethod(exclude=true) diff --git a/rest/src/main/java/org/apache/unomi/rest/endpoints/SegmentServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/endpoints/SegmentServiceEndPoint.java index 3cd547598..d987f2b03 100644 --- a/rest/src/main/java/org/apache/unomi/rest/endpoints/SegmentServiceEndPoint.java +++ b/rest/src/main/java/org/apache/unomi/rest/endpoints/SegmentServiceEndPoint.java @@ -50,13 +50,13 @@ @Component(service=SegmentServiceEndPoint.class,property = "osgi.jaxrs.resource=true") public class SegmentServiceEndPoint { - private static final Logger logger = LoggerFactory.getLogger(SegmentServiceEndPoint.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SegmentServiceEndPoint.class.getName()); @Reference private SegmentService segmentService; public SegmentServiceEndPoint() { - logger.info("Initializing segment service endpoint..."); + LOGGER.info("Initializing segment service endpoint..."); } @WebMethod(exclude=true) diff --git a/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java index fe8faa70b..eff0f90bb 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java @@ -17,7 +17,6 @@ package org.apache.unomi.services.impl.events; -import com.fasterxml.jackson.databind.JsonNode; import inet.ipaddr.IPAddress; import inet.ipaddr.IPAddressString; import org.apache.commons.lang3.StringUtils; @@ -32,7 +31,6 @@ import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.query.Query; import org.apache.unomi.api.services.*; -import org.apache.unomi.persistence.spi.CustomObjectMapper; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; import org.apache.unomi.api.utils.ParserHelper; @@ -52,7 +50,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class EventServiceImpl implements EventService { - private static final Logger logger = LoggerFactory.getLogger(EventServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(EventServiceImpl.class.getName()); private static final int MAX_RECURSION_DEPTH = 10; private List eventListeners = new CopyOnWriteArrayList(); @@ -124,20 +122,26 @@ public boolean isEventAllowed(Event event, String thirdPartyId) { } public String authenticateThirdPartyServer(String key, String ip) { - logger.debug("Authenticating third party server with key: " + key + " and IP: " + ip); + LOGGER.debug("Authenticating third party server with key: {} and IP: {}", key, ip); if (key != null) { for (Map.Entry entry : thirdPartyServers.entrySet()) { ThirdPartyServer server = entry.getValue(); if (server.getKey().equals(key)) { - IPAddress ipAddress = new IPAddressString(ip).getAddress(); - for (IPAddress serverIpAddress : server.getIpAddresses()) { - if (serverIpAddress.contains(ipAddress)) { - return server.getId(); + if (ip != null) { + if (ip.startsWith("[") && ip.endsWith("]")) { + // This can happen with IPv6 addresses, we must remove the markers since our IPAddress library doesn't support them. + ip = ip.substring(1, ip.length() - 1); + } + IPAddress ipAddress = new IPAddressString(ip).getAddress(); + for (IPAddress serverIpAddress : server.getIpAddresses()) { + if (serverIpAddress.contains(ipAddress)) { + return server.getId(); + } } } } } - logger.warn("Could not authenticate any third party servers for key: {}", key); + LOGGER.warn("Could not authenticate any third party servers for key: {}", key); } return null; } @@ -148,7 +152,7 @@ public int send(Event event) { private int send(Event event, int depth) { if (depth > MAX_RECURSION_DEPTH) { - logger.warn("Max recursion depth reached"); + LOGGER.warn("Max recursion depth reached"); return NO_CHANGE; } @@ -407,4 +411,9 @@ public void removeProfileEvents(String profileId){ persistenceService.removeByQuery(profileCondition,Event.class); } + + @Override + public void deleteEvent(String eventIdentifier) { + persistenceService.remove(eventIdentifier, Event.class); + } } diff --git a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java index dd30ba863..2c34efa89 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java @@ -160,7 +160,7 @@ private void updateListMap(Map> listMap, PropertyType } - private static final Logger logger = LoggerFactory.getLogger(ProfileServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileServiceImpl.class.getName()); private BundleContext bundleContext; @@ -192,7 +192,7 @@ private void updateListMap(Map> listMap, PropertyType private boolean forceRefreshOnSave = false; public ProfileServiceImpl() { - logger.info("Initializing profile service..."); + LOGGER.info("Initializing profile service..."); } public void setBundleContext(BundleContext bundleContext) { @@ -224,7 +224,7 @@ public void setPropertiesRefreshInterval(long propertiesRefreshInterval) { } public void postConstruct() { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); loadPropertyTypesFromPersistence(); processBundleStartup(bundleContext); @@ -237,7 +237,7 @@ public void postConstruct() { initializeDefaultPurgeValuesIfNecessary(); initializePurge(); schedulePropertyTypeLoad(); - logger.info("Profile service initialized."); + LOGGER.info("Profile service initialized."); } public void preDestroy() { @@ -248,7 +248,7 @@ public void preDestroy() { propertyTypeLoadTask.cancel(); } bundleContext.removeBundleListener(this); - logger.info("Profile service shutdown."); + LOGGER.info("Profile service shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -311,7 +311,7 @@ public void run() { } }; schedulerService.getScheduleExecutorService().scheduleAtFixedRate(propertyTypeLoadTask, 10000, propertiesRefreshInterval, TimeUnit.MILLISECONDS); - logger.info("Scheduled task for property type loading each 10s"); + LOGGER.info("Scheduled task for property type loading each 10s"); } public void reloadPropertyTypes(boolean refresh) { @@ -321,7 +321,7 @@ public void reloadPropertyTypes(boolean refresh) { } loadPropertyTypesFromPersistence(); } catch (Throwable t) { - logger.error("Error loading property types from persistence back-end", t); + LOGGER.error("Error loading property types from persistence back-end", t); } } @@ -329,7 +329,7 @@ private void loadPropertyTypesFromPersistence() { try { this.propertyTypes = new PropertyTypes(persistenceService.getAllItems(PropertyType.class, 0, -1, "rank").getList()); } catch (Exception e) { - logger.error("Error loading property types from persistence service", e); + LOGGER.error("Error loading property types from persistence service", e); } } @@ -348,7 +348,7 @@ public void purgeProfiles(int inactiveNumberOfDays, int existsNumberOfDays) { List subConditions = new ArrayList<>(); if (inactiveNumberOfDays > 0) { - logger.info("Purging: Profile with no visits since {} days", inactiveNumberOfDays); + LOGGER.info("Purging: Profile with no visits since {} days", inactiveNumberOfDays); Condition inactiveTimeCondition = new Condition(profilePropertyConditionType); inactiveTimeCondition.setParameter("propertyName", "properties.lastVisit"); inactiveTimeCondition.setParameter("comparisonOperator", "lessThanOrEqualTo"); @@ -358,7 +358,7 @@ public void purgeProfiles(int inactiveNumberOfDays, int existsNumberOfDays) { if (existsNumberOfDays > 0) { Condition existTimeCondition = new Condition(profilePropertyConditionType); - logger.info("Purging: Profile created since more than {} days", existsNumberOfDays); + LOGGER.info("Purging: Profile created since more than {} days", existsNumberOfDays); existTimeCondition.setParameter("propertyName", "properties.firstVisit"); existTimeCondition.setParameter("comparisonOperator", "lessThanOrEqualTo"); existTimeCondition.setParameter("propertyValueDateExpr", "now-" + existsNumberOfDays + "d"); @@ -373,7 +373,7 @@ public void purgeProfiles(int inactiveNumberOfDays, int existsNumberOfDays) { @Override public void purgeSessionItems(int existsNumberOfDays) { if (existsNumberOfDays > 0) { - logger.info("Purging: Sessions created since more than {} days", existsNumberOfDays); + LOGGER.info("Purging: Sessions created since more than {} days", existsNumberOfDays); persistenceService.purgeTimeBasedItems(existsNumberOfDays, Session.class); } } @@ -381,7 +381,7 @@ public void purgeSessionItems(int existsNumberOfDays) { @Override public void purgeEventItems(int existsNumberOfDays) { if (existsNumberOfDays > 0) { - logger.info("Purging: Events created since more than {} days", existsNumberOfDays); + LOGGER.info("Purging: Events created since more than {} days", existsNumberOfDays); persistenceService.purgeTimeBasedItems(existsNumberOfDays, Event.class); } } @@ -393,21 +393,21 @@ public void purgeMonthlyItems(int existsNumberOfMonths) { } private void initializePurge() { - logger.info("Purge: Initializing"); + LOGGER.info("Purge: Initializing"); if (purgeProfileInactiveTime > 0 || purgeProfileExistTime > 0 || purgeSessionExistTime > 0 || purgeEventExistTime > 0) { if (purgeProfileInactiveTime > 0) { - logger.info("Purge: Profile with no visits since more than {} days, will be purged", purgeProfileInactiveTime); + LOGGER.info("Purge: Profile with no visits since more than {} days, will be purged", purgeProfileInactiveTime); } if (purgeProfileExistTime > 0) { - logger.info("Purge: Profile created since more than {} days, will be purged", purgeProfileExistTime); + LOGGER.info("Purge: Profile created since more than {} days, will be purged", purgeProfileExistTime); } if (purgeSessionExistTime > 0) { - logger.info("Purge: Session items created since more than {} days, will be purged", purgeSessionExistTime); + LOGGER.info("Purge: Session items created since more than {} days, will be purged", purgeSessionExistTime); } if (purgeEventExistTime > 0) { - logger.info("Purge: Event items created since more than {} days, will be purged", purgeEventExistTime); + LOGGER.info("Purge: Event items created since more than {} days, will be purged", purgeEventExistTime); } purgeTask = new TimerTask() { @@ -415,7 +415,7 @@ private void initializePurge() { public void run() { try { long purgeStartTime = System.currentTimeMillis(); - logger.info("Purge: triggered"); + LOGGER.info("Purge: triggered"); // Profile purge purgeProfiles(purgeProfileInactiveTime, purgeProfileExistTime); @@ -423,18 +423,18 @@ public void run() { // Monthly items purge purgeSessionItems(purgeSessionExistTime); purgeEventItems(purgeEventExistTime); - logger.info("Purge: executed in {} ms", System.currentTimeMillis() - purgeStartTime); + LOGGER.info("Purge: executed in {} ms", System.currentTimeMillis() - purgeStartTime); } catch (Throwable t) { - logger.error("Error while purging", t); + LOGGER.error("Error while purging", t); } } }; schedulerService.getScheduleExecutorService().scheduleAtFixedRate(purgeTask, 1, purgeProfileInterval, TimeUnit.DAYS); - logger.info("Purge: purge scheduled with an interval of {} days", purgeProfileInterval); + LOGGER.info("Purge: purge scheduled with an interval of {} days", purgeProfileInterval); } else { - logger.info("Purge: No purge scheduled"); + LOGGER.info("Purge: No purge scheduled"); } } @@ -552,8 +552,6 @@ public String exportProfilesPropertiesToCsv(Query query) { String propertyId = propertyIdAndType.getKey(); if (profile.getProperties().get(propertyId) != null) { handleExportProperty(sb, profile.getProperties().get(propertyId), propertyIdAndType.getValue()); - } else { - sb.append(""); } sb.append(";"); } @@ -769,7 +767,7 @@ public Profile mergeProfiles(Profile masterProfile, List profilesToMerg for (Profile profileToMerge : profilesToMerge) { profileIdsToMerge.add(profileToMerge.getItemId()); } - logger.info("Merging profiles " + profileIdsToMerge + " into profile " + masterProfile.getItemId()); + LOGGER.info("Merging profiles {} into profile {}", profileIdsToMerge, masterProfile.getItemId()); boolean masterProfileChanged = false; @@ -785,11 +783,12 @@ public Profile mergeProfiles(Profile masterProfile, List profilesToMerg if (propertyMergeStrategyType == null) { // we couldn't find the strategy if (propertyMergeStrategyId.equals("defaultMergeStrategy")) { - logger.warn("Couldn't resolve default strategy, ignoring property merge for property " + profileProperty); + LOGGER.warn("Couldn't resolve default strategy, ignoring property merge for property {}", profileProperty); continue; } else { // todo: improper algorithm… it is possible that the defaultMergeStrategy couldn't be resolved here - logger.warn("Couldn't resolve strategy " + propertyMergeStrategyId + " for property " + profileProperty + ", using default strategy instead"); + LOGGER.warn("Couldn't resolve strategy {} for property {}, using default strategy instead", propertyMergeStrategyId, + profileProperty); propertyMergeStrategyId = "defaultMergeStrategy"; propertyMergeStrategyType = definitionsService.getPropertyMergeStrategyType(propertyMergeStrategyId); } @@ -804,7 +803,7 @@ public Profile mergeProfiles(Profile masterProfile, List profilesToMerg masterProfileChanged |= propertyMergeStrategyExecutor.mergeProperty(profileProperty, propertyType, profilesToMerge, masterProfile); } } catch (InvalidSyntaxException e) { - logger.error("Error retrieving strategy implementation", e); + LOGGER.error("Error retrieving strategy implementation", e); } } @@ -816,7 +815,7 @@ public Profile mergeProfiles(Profile masterProfile, List profilesToMerg // we now have to merge the profile's segments for (Profile profile : profilesToMerge) { - if (profile.getSegments() != null && profile.getSegments().size() > 0) { + if (profile.getSegments() != null && !profile.getSegments().isEmpty()) { masterProfile.getSegments().addAll(profile.getSegments()); // TODO better segments diff calculation masterProfileChanged = true; @@ -825,7 +824,7 @@ public Profile mergeProfiles(Profile masterProfile, List profilesToMerg // we now have to merge the profile's consents for (Profile profile : profilesToMerge) { - if (profile.getConsents() != null && profile.getConsents().size() > 0) { + if (profile.getConsents() != null && !profile.getConsents().isEmpty()) { for (String consentId : profile.getConsents().keySet()) { if (masterProfile.getConsents().containsKey(consentId)) { if (masterProfile.getConsents().get(consentId).getRevokeDate().before(new Date())) { @@ -861,7 +860,7 @@ public PartialList getProfileSessions(String profileId, String query, i public String getPropertyTypeMapping(String fromPropertyTypeId) { Collection types = getPropertyTypeByMapping(fromPropertyTypeId); - if (types.size() > 0) { + if (!types.isEmpty()) { return types.iterator().next().getMetadata().getId(); } return null; @@ -892,17 +891,17 @@ public Session saveSession(Session session) { return persistenceService.save(session) ? session : null; } - private Map removePersonalIdentifiersFromSessionProfile(final Map profileProperties) { + private Map removePersonalIdentifiersFromSessionProfile(final Map profileProperties) { Set personalIdsProps = getPropertyTypeBySystemTag(PERSONAL_IDENTIFIER_TAG_NAME); - final List personalIdsPropsNames = new ArrayList(); + final List personalIdsPropsNames = new ArrayList<>(); personalIdsProps.forEach(propType -> personalIdsPropsNames.add(propType.getMetadata().getId())); - Set propsToRemove = new HashSet(); + Set propsToRemove = new HashSet<>(); profileProperties.keySet().forEach(propKey -> { if (personalIdsPropsNames.contains(propKey)) { propsToRemove.add(propKey); } }); - propsToRemove.forEach(propId -> profileProperties.remove(propId)); + propsToRemove.forEach(profileProperties::remove); return profileProperties; } @@ -935,7 +934,7 @@ public boolean matchCondition(Condition condition, Profile profile, Session sess return true; } } - return subConditions.size() > 0 && isAnd; + return !subConditions.isEmpty() && isAnd; } else { Condition profileCondition = definitionsService.extractConditionBySystemTag(condition, "profileCondition"); Condition sessionCondition = definitionsService.extractConditionBySystemTag(condition, "sessionCondition"); @@ -947,14 +946,14 @@ public boolean matchCondition(Condition condition, Profile profile, Session sess } public void batchProfilesUpdate(BatchUpdate update) { - logger.info("Starting batch profiles update"); + LOGGER.info("Starting batch profiles update"); long startTime = System.currentTimeMillis(); long updatedCount = 0; ParserHelper.resolveConditionType(definitionsService, update.getCondition(), "batch update on property " + update.getPropertyName()); PartialList profiles = persistenceService.query(update.getCondition(), null, Profile.class, 0,update.getScrollBatchSize(), update.getScrollTimeValidity()); - while (profiles != null && profiles.getList().size() > 0) { + while (profiles != null && !profiles.getList().isEmpty()) { for (Profile profile : profiles.getList()) { if (PropertyHelper.setProperty(profile, update.getPropertyName(), update.getPropertyValue(), update.getStrategy())) { save(profile); @@ -965,7 +964,7 @@ public void batchProfilesUpdate(BatchUpdate update) { } long totalTime = System.currentTimeMillis() - startTime; - logger.info("Batch profiles updated: {} profiles in {}ms", updatedCount, totalTime); + LOGGER.info("Batch profiles updated: {} profiles in {}ms", updatedCount, totalTime); } public Persona loadPersona(String personaId) { @@ -1103,7 +1102,7 @@ private void loadPredefinedPersonas(BundleContext bundleContext) { while (predefinedPersonaEntries.hasMoreElements()) { URL predefinedPersonaURL = predefinedPersonaEntries.nextElement(); - logger.debug("Found predefined persona at " + predefinedPersonaURL + ", loading... "); + LOGGER.debug("Found predefined persona at {}, loading... ", predefinedPersonaURL); try { PersonaWithSessions persona = getObjectMapper().readValue(predefinedPersonaURL, PersonaWithSessions.class); @@ -1116,9 +1115,9 @@ private void loadPredefinedPersonas(BundleContext bundleContext) { session.setProfile(persona.getPersona()); persistenceService.save(session); } - logger.info("Predefined persona with id {} registered", itemId); + LOGGER.info("Predefined persona with id {} registered", itemId); } catch (IOException e) { - logger.error("Error while loading persona " + predefinedPersonaURL, e); + LOGGER.error("Error while loading persona {}", predefinedPersonaURL, e); } } } @@ -1132,7 +1131,7 @@ private void loadPredefinedPropertyTypes(BundleContext bundleContext) { List bundlePropertyTypes = new ArrayList<>(); while (predefinedPropertyTypeEntries.hasMoreElements()) { URL predefinedPropertyTypeURL = predefinedPropertyTypeEntries.nextElement(); - logger.debug("Found predefined property type at " + predefinedPropertyTypeURL + ", loading... "); + LOGGER.debug("Found predefined property type at {}, loading... ", predefinedPropertyTypeURL); try { PropertyType propertyType = CustomObjectMapper.getObjectMapper().readValue(predefinedPropertyTypeURL, PropertyType.class); @@ -1141,9 +1140,9 @@ private void loadPredefinedPropertyTypes(BundleContext bundleContext) { persistenceService.save(propertyType); bundlePropertyTypes.add(propertyType); - logger.info("Predefined property type with id {} registered", propertyType.getMetadata().getId()); + LOGGER.info("Predefined property type with id {} registered", propertyType.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading properties " + predefinedPropertyTypeURL, e); + LOGGER.error("Error while loading properties {}", predefinedPropertyTypeURL, e); } } propertyTypes = propertyTypes.with(bundlePropertyTypes); @@ -1171,7 +1170,7 @@ private boolean merge(T target, T object) { return true; } } catch (ReflectiveOperationException e) { - logger.error("Cannot merge properties", e); + LOGGER.error("Cannot merge properties", e); } } return false; @@ -1286,4 +1285,9 @@ private boolean mergeSystemProperties(Map targetProperties, Map< public void refresh() { reloadPropertyTypes(true); } + + @Override + public void deleteSession(String sessionIdentifier) { + persistenceService.remove(sessionIdentifier, Session.class); + } } diff --git a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java index 79a1aa638..0861c53e3 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/rules/RulesServiceImpl.java @@ -24,7 +24,6 @@ import org.apache.unomi.api.PartialList; import org.apache.unomi.api.actions.Action; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.api.conditions.ConditionType; import org.apache.unomi.api.query.Query; import org.apache.unomi.api.rules.Rule; import org.apache.unomi.api.rules.RuleStatistics; @@ -43,12 +42,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; public class RulesServiceImpl implements RulesService, EventListenerService, SynchronousBundleListener { public static final String TRACKED_PARAMETER = "trackedConditionParameters"; - private static final Logger logger = LoggerFactory.getLogger(RulesServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(RulesServiceImpl.class.getName()); private BundleContext bundleContext; @@ -61,12 +59,12 @@ public class RulesServiceImpl implements RulesService, EventListenerService, Syn private List allRules; private final Set invalidRulesId = new HashSet<>(); - private Map allRuleStatistics = new ConcurrentHashMap<>(); + private final Map allRuleStatistics = new ConcurrentHashMap<>(); private Integer rulesRefreshInterval = 1000; private Integer rulesStatisticsRefreshInterval = 10000; - private List ruleListeners = new CopyOnWriteArrayList(); + private final List ruleListeners = new CopyOnWriteArrayList(); private Map> rulesByEventType = new HashMap<>(); private Boolean optimizedRulesActivated = true; @@ -108,7 +106,7 @@ public void setOptimizedRulesActivated(Boolean optimizedRulesActivated) { } public void postConstruct() { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); loadPredefinedRules(bundleContext); for (Bundle bundle : bundleContext.getBundles()) { @@ -120,12 +118,12 @@ public void postConstruct() { bundleContext.addBundleListener(this); initializeTimers(); - logger.info("Rule service initialized."); + LOGGER.info("Rule service initialized."); } public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("Rule service shutdown."); + LOGGER.info("Rule service shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -149,14 +147,14 @@ private void loadPredefinedRules(BundleContext bundleContext) { while (predefinedRuleEntries.hasMoreElements()) { URL predefinedRuleURL = predefinedRuleEntries.nextElement(); - logger.debug("Found predefined rule at " + predefinedRuleURL + ", loading... "); + LOGGER.debug("Found predefined rule at {}, loading... ", predefinedRuleURL); try { Rule rule = CustomObjectMapper.getObjectMapper().readValue(predefinedRuleURL, Rule.class); setRule(rule); - logger.info("Predefined rule with id {} registered", rule.getMetadata().getId()); + LOGGER.info("Predefined rule with id {} registered", rule.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading rule definition " + predefinedRuleURL, e); + LOGGER.error("Error while loading rule definition {}", predefinedRuleURL, e); } } } @@ -273,7 +271,7 @@ public void refreshRules() { this.rulesByEventType = getRulesByEventType(newAllRules); this.allRules = newAllRules; } catch (Throwable t) { - logger.error("Error loading rules from persistence back-end", t); + LOGGER.error("Error loading rules from persistence back-end", t); } } @@ -315,7 +313,7 @@ public int onEvent(Event event) { int changes = EventService.NO_CHANGE; for (Rule rule : rules) { - logger.debug("Fired rule " + rule.getMetadata().getId() + " for " + event.getEventType() + " - " + event.getItemId()); + LOGGER.debug("Fired rule {} for {} - {}", rule.getMetadata().getId(), event.getEventType(), event.getItemId()); fireExecuteActions(rule, event); long actionsStartTime = System.currentTimeMillis(); @@ -428,8 +426,8 @@ public Set getTrackedConditions(Item source) { } } else if ( trackedCondition.getConditionType() != null && - trackedCondition.getConditionType().getParameters() != null && - trackedCondition.getConditionType().getParameters().size() > 0 + trackedCondition.getConditionType().getParameters() != null && !trackedCondition.getConditionType() + .getParameters().isEmpty() ) { // lookup for track parameters Map trackedParameters = new HashMap<>(); @@ -442,10 +440,10 @@ public Set getTrackedConditions(Item source) { }); } } catch (Exception e) { - logger.warn("Unable to parse tracked parameter from {} for condition type {}", parameter, trackedCondition.getConditionType().getItemId()); + LOGGER.warn("Unable to parse tracked parameter from {} for condition type {}", parameter, trackedCondition.getConditionType().getItemId()); } }); - if (trackedParameters.size() > 0) { + if (!trackedParameters.isEmpty()) { evalCondition = new Condition(definitionsService.getConditionType("booleanCondition")); evalCondition.setParameter("operator", "and"); ArrayList conditions = new ArrayList<>(); @@ -488,7 +486,7 @@ public void run() { try { syncRuleStatistics(); } catch (Throwable t) { - logger.error("Error synching rule statistics between memory and persistence back-end", t); + LOGGER.error("Error synching rule statistics between memory and persistence back-end", t); } } }; diff --git a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java index fee5ef0fb..1bc8730f4 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/segments/SegmentServiceImpl.java @@ -58,7 +58,7 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentService, SynchronousBundleListener { - private static final Logger logger = LoggerFactory.getLogger(SegmentServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(SegmentServiceImpl.class.getName()); private static final String VALIDATION_PROFILE_ID = "validation-profile-id"; private static final String RESET_SCORING_SCRIPT = "resetScoringPlan"; @@ -85,7 +85,7 @@ public class SegmentServiceImpl extends AbstractServiceImpl implements SegmentSe private int dailyDateExprEvaluationHourUtc = 5; public SegmentServiceImpl() { - logger.info("Initializing segment service..."); + LOGGER.info("Initializing segment service..."); } public void setBundleContext(BundleContext bundleContext) { @@ -145,7 +145,7 @@ public void setDailyDateExprEvaluationHourUtc(int dailyDateExprEvaluationHourUtc } public void postConstruct() throws IOException { - logger.debug("postConstruct {" + bundleContext.getBundle() + "}"); + LOGGER.debug("postConstruct {{}}", bundleContext.getBundle()); loadPredefinedSegments(bundleContext); loadPredefinedScorings(bundleContext); for (Bundle bundle : bundleContext.getBundles()) { @@ -156,12 +156,12 @@ public void postConstruct() throws IOException { } bundleContext.addBundleListener(this); initializeTimer(); - logger.info("Segment service initialized."); + LOGGER.info("Segment service initialized."); } public void preDestroy() { bundleContext.removeBundleListener(this); - logger.info("Segment service shutdown."); + LOGGER.info("Segment service shutdown."); } private void processBundleStartup(BundleContext bundleContext) { @@ -186,7 +186,7 @@ private void loadPredefinedSegments(BundleContext bundleContext) { while (predefinedSegmentEntries.hasMoreElements()) { URL predefinedSegmentURL = predefinedSegmentEntries.nextElement(); - logger.debug("Found predefined segment at " + predefinedSegmentURL + ", loading... "); + LOGGER.debug("Found predefined segment at {}, loading... ", predefinedSegmentURL); try { Segment segment = CustomObjectMapper.getObjectMapper().readValue(predefinedSegmentURL, Segment.class); @@ -194,9 +194,9 @@ private void loadPredefinedSegments(BundleContext bundleContext) { segment.getMetadata().setScope("systemscope"); } setSegmentDefinition(segment); - logger.info("Predefined segment with id {} registered", segment.getMetadata().getId()); + LOGGER.info("Predefined segment with id {} registered", segment.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading segment definition " + predefinedSegmentURL, e); + LOGGER.error("Error while loading segment definition {}", predefinedSegmentURL, e); } } } @@ -209,7 +209,7 @@ private void loadPredefinedScorings(BundleContext bundleContext) { while (predefinedScoringEntries.hasMoreElements()) { URL predefinedScoringURL = predefinedScoringEntries.nextElement(); - logger.debug("Found predefined scoring at " + predefinedScoringURL + ", loading... "); + LOGGER.debug("Found predefined scoring at {}, loading... ", predefinedScoringURL); try { Scoring scoring = CustomObjectMapper.getObjectMapper().readValue(predefinedScoringURL, Scoring.class); @@ -217,9 +217,9 @@ private void loadPredefinedScorings(BundleContext bundleContext) { scoring.getMetadata().setScope("systemscope"); } setScoringDefinition(scoring); - logger.info("Predefined scoring with id {} registered", scoring.getMetadata().getId()); + LOGGER.info("Predefined scoring with id {} registered", scoring.getMetadata().getId()); } catch (IOException e) { - logger.error("Error while loading segment definition " + predefinedScoringURL, e); + LOGGER.error("Error while loading segment definition {}", predefinedScoringURL, e); } } } @@ -286,10 +286,7 @@ private boolean checkSegmentDeletionImpact(Condition condition, String segmentTo } } else if ("profileSegmentCondition".equals(condition.getConditionTypeId())) { @SuppressWarnings("unchecked") final List referencedSegmentIds = (List) condition.getParameter("segments"); - - if (referencedSegmentIds.indexOf(segmentToDeleteId) >= 0) { - return true; - } + return referencedSegmentIds.contains(segmentToDeleteId); } } return false; @@ -326,7 +323,7 @@ private Condition updateSegmentDependentCondition(Condition condition, String se } } else if ("profileSegmentCondition".equals(condition.getConditionTypeId())) { @SuppressWarnings("unchecked") final List referencedSegmentIds = (List) condition.getParameter("segments"); - if (referencedSegmentIds.indexOf(segmentId) >= 0) { + if (referencedSegmentIds.contains(segmentId)) { referencedSegmentIds.remove(segmentId); if (referencedSegmentIds.isEmpty()) { return null; @@ -758,8 +755,8 @@ private void getAutoGeneratedRules(Metadata metadata, Condition condition, Condi action.setActionType(definitionsService.getActionType("setEventOccurenceCountAction")); action.setParameter("pastEventCondition", parentCondition); - rule.setActions(Arrays.asList(action)); - rule.setLinkedItems(Arrays.asList(metadata.getId())); + rule.setActions(List.of(action)); + rule.setLinkedItems(List.of(metadata.getId())); // it's a new generated rules to keep track of the event count, we should update all the profile that match this past event // it will update the count of event occurrence on the profile directly @@ -868,7 +865,7 @@ private void recalculatePastEventOccurrencesOnProfiles(Condition eventCondition, persistenceService.refreshIndex(Profile.class); } - logger.info("{} profiles updated for past event condition in {}ms", updatedProfileCount, System.currentTimeMillis() - t); + LOGGER.info("{} profiles updated for past event condition in {}ms", updatedProfileCount, System.currentTimeMillis() - t); } /** @@ -918,7 +915,7 @@ public String getGeneratedPropertyKey(Condition condition, Condition parentCondi String key = CustomObjectMapper.getObjectMapper().writeValueAsString(m); return "eventTriggered" + getMD5(key); } catch (JsonProcessingException e) { - logger.error("Cannot generate key", e); + LOGGER.error("Cannot generate key", e); return null; } } @@ -928,13 +925,13 @@ public void recalculatePastEventConditions() { Set segmentOrScoringIdsToReevaluate = new HashSet<>(); // reevaluate auto generated rules used to store the event occurrence count on the profile for (Rule rule : rulesService.getAllRules()) { - if (rule.getActions() != null && rule.getActions().size() > 0) { + if (rule.getActions() != null && !rule.getActions().isEmpty()) { for (Action action : rule.getActions()) { if (action.getActionTypeId().equals("setEventOccurenceCountAction")) { Condition pastEventCondition = (Condition) action.getParameterValues().get("pastEventCondition"); if (pastEventCondition.containsParameter("numberOfDays")) { recalculatePastEventOccurrencesOnProfiles(rule.getCondition(), pastEventCondition, true, true); - logger.info("Event occurrence count on profiles updated for rule: {}", rule.getItemId()); + LOGGER.info("Event occurrence count on profiles updated for rule: {}", rule.getItemId()); if (rule.getLinkedItems() != null && rule.getLinkedItems().size() > 0) { segmentOrScoringIdsToReevaluate.addAll(rule.getLinkedItems()); } @@ -944,7 +941,7 @@ public void recalculatePastEventConditions() { } } int pastEventSegmentsAndScoringsSize = segmentOrScoringIdsToReevaluate.size(); - logger.info("Found {} segments or scoring plans containing pastEventCondition conditions", pastEventSegmentsAndScoringsSize); + LOGGER.info("Found {} segments or scoring plans containing pastEventCondition conditions", pastEventSegmentsAndScoringsSize); // get Segments and Scoring that contains relative date expressions segmentOrScoringIdsToReevaluate.addAll(allSegments.stream() @@ -953,26 +950,26 @@ public void recalculatePastEventConditions() { .collect(Collectors.toList())); segmentOrScoringIdsToReevaluate.addAll(allScoring.stream() - .filter(scoring -> scoring.getElements() != null && scoring.getElements().size() > 0 && scoring.getElements().stream() + .filter(scoring -> scoring.getElements() != null && !scoring.getElements().isEmpty() && scoring.getElements().stream() .anyMatch(scoringElement -> scoringElement != null && scoringElement.getCondition() != null && scoringElement.getCondition().toString().contains("propertyValueDateExpr"))) .map(Item::getItemId) .collect(Collectors.toList())); - logger.info("Found {} segments or scoring plans containing date relative expressions", segmentOrScoringIdsToReevaluate.size() - pastEventSegmentsAndScoringsSize); + LOGGER.info("Found {} segments or scoring plans containing date relative expressions", segmentOrScoringIdsToReevaluate.size() - pastEventSegmentsAndScoringsSize); // reevaluate segments and scoring. - if (segmentOrScoringIdsToReevaluate.size() > 0) { + if (!segmentOrScoringIdsToReevaluate.isEmpty()) { persistenceService.refreshIndex(Profile.class, null); for (String linkedItem : segmentOrScoringIdsToReevaluate) { Segment linkedSegment = getSegmentDefinition(linkedItem); if (linkedSegment != null) { - logger.info("Start segment recalculation for segment: {} - {}", linkedSegment.getItemId(), linkedSegment.getMetadata().getName()); + LOGGER.info("Start segment recalculation for segment: {} - {}", linkedSegment.getItemId(), linkedSegment.getMetadata().getName()); updateExistingProfilesForSegment(linkedSegment); continue; } Scoring linkedScoring = getScoringDefinition(linkedItem); if (linkedScoring != null) { - logger.info("Start scoring plan recalculation for scoring plan: {} - {}", linkedScoring.getItemId(), linkedScoring.getMetadata().getName()); + LOGGER.info("Start scoring plan recalculation for scoring plan: {} - {}", linkedScoring.getItemId(), linkedScoring.getMetadata().getName()); updateExistingProfilesForScoring(linkedScoring.getItemId(), linkedScoring.getElements(), linkedScoring.getMetadata().isEnabled()); } } @@ -1009,7 +1006,7 @@ private Set updatePastEventOccurrencesOnProfiles(Map event Condition profileIdCondition = definitionsService.getConditionBuilder().condition("idsCondition").parameter("ids", batchProfilesToUpdate).parameter("match", true).build(); persistenceService.updateWithQueryAndStoredScript(Profile.class, new String[]{"updatePastEventOccurences"}, new Map[]{paramPerProfile}, new Condition[]{profileIdCondition}); } catch (Exception e) { - logger.error("Error updating {} profiles for past event system properties", paramPerProfile.size(), e); + LOGGER.error("Error updating {} profiles for past event system properties", paramPerProfile.size(), e); } finally { paramPerProfile.clear(); batchProfilesToUpdate.clear(); @@ -1072,14 +1069,14 @@ private void updateExistingProfilesForSegment(Segment segment) { } else { updatedProfileCount += updateProfilesSegment(segmentCondition, segmentId, false, sendProfileUpdateEventForSegmentUpdate); } - logger.info("{} profiles updated in {}ms", updatedProfileCount, System.currentTimeMillis() - updateProfilesForSegmentStartTime); + LOGGER.info("{} profiles updated in {}ms", updatedProfileCount, System.currentTimeMillis() - updateProfilesForSegmentStartTime); } private long updateProfilesSegment(Condition profilesToUpdateCondition, String segmentId, boolean isAdd, boolean sendProfileUpdateEvent) { long updatedProfileCount = 0; PartialList profiles = persistenceService.query(profilesToUpdateCondition, null, Profile.class, 0, segmentUpdateBatchSize, "10m"); - while (profiles != null && profiles.getList().size() > 0) { + while (profiles != null && !profiles.getList().isEmpty()) { long startTime = System.currentTimeMillis(); if (batchSegmentProfileUpdate) { batchUpdateProfilesSegment(segmentId, profiles.getList(), isAdd); @@ -1093,7 +1090,7 @@ private long updateProfilesSegment(Condition profilesToUpdateCondition, String s sendProfileUpdatedEvent(profiles.getList()); updatedProfileCount += profiles.size(); - logger.info("{} profiles {} to segment {} in {}ms", profiles.size(), isAdd ? "added" : "removed", segmentId, System.currentTimeMillis() - startTime); + LOGGER.info("{} profiles {} to segment {} in {}ms", profiles.size(), isAdd ? "added" : "removed", segmentId, System.currentTimeMillis() - startTime); profiles = persistenceService.continueScrollQuery(Profile.class, profiles.getScrollIdentifier(), profiles.getScrollTimeValidity()); } @@ -1120,11 +1117,11 @@ private void retryFailedSegmentUpdate(String profileId, String segmentId, boolea Failsafe.with(retryPolicy). run(executionContext -> { - logger.warn("retry updating profile segment {}, profile {}, time {}", segmentId, profileId, new Date()); + LOGGER.warn("retry updating profile segment {}, profile {}, time {}", segmentId, profileId, new Date()); Profile profileToAddUpdated = persistenceService.load(profileId, Profile.class); Map sourceMapToUpdate = buildPropertiesMapForUpdateSegment(profileToAddUpdated, segmentId, isAdd); boolean isUpdated = persistenceService.update(profileToAddUpdated, Profile.class, sourceMapToUpdate); - if (isUpdated == false) + if (!isUpdated) throw new Exception(String.format("failed retry update profile segment {}, profile {}, time {}", segmentId, profileId, new Date())); }); } @@ -1184,7 +1181,7 @@ private void updateExistingProfilesForScoring(String scoringId, List Date: Thu, 5 Dec 2024 09:57:46 +0100 Subject: [PATCH 04/58] Initial working OpenSearch implementation. Basic functionality is working, work on automated tests is still in progress. --- .github/workflows/unomi-ci-build-tests.yml | 29 +- .github/workflows/unomi-ci-docs-deploy.yml | 4 +- extensions/privacy-extension/rest/pom.xml | 2 + .../META-INF/cxs/rules/cdpSessionEvent.json | 24 - itests/README.md | 14 + itests/pom.xml | 255 +- .../java/org/apache/unomi/itests/BaseIT.java | 58 +- .../resources/org.apache.unomi.router.cfg | 8 +- kar/pom.xml | 10 + kar/src/main/feature/feature.xml | 8 +- .../OSGI-INF/blueprint/blueprint.xml | 2 +- metrics/pom.xml | 7 - package/pom.xml | 14 + .../resources/etc/custom.system.properties | 91 +- .../ElasticSearchPersistenceServiceImpl.java | 202 +- .../ConditionESQueryBuilderDispatcher.java | 15 +- .../OSGI-INF/blueprint/blueprint.xml | 6 +- .../ElasticsearchPersistenceTest.java | 175 - persistence-opensearch/conditions/pom.xml | 191 + .../BooleanConditionOSQueryBuilder.java | 82 + ...ByPointSessionConditionOSQueryBuilder.java | 66 + .../IdsConditionOSQueryBuilder.java | 53 + .../MatchAllConditionOSQueryBuilder.java | 33 + .../NestedConditionOSQueryBuilder.java | 45 + .../NotConditionOSQueryBuilder.java | 36 + .../PastEventConditionOSQueryBuilder.java | 257 ++ .../PropertyConditionOSQueryBuilder.java | 250 ++ ...eEventPropertyConditionOSQueryBuilder.java | 62 + .../OSGI-INF/blueprint/blueprint.xml | 135 + persistence-opensearch/core/pom.xml | 194 + .../opensearch/OSCustomObjectMapper.java | 45 + .../persistence/opensearch/OSEventMixIn.java | 17 +- .../persistence/opensearch/OSItemMixIn.java | 30 + .../OpenSearchPersistenceServiceImpl.java | 2641 ++++++++++++ .../conditions/ConditionOSQueryBuilder.java | 32 + .../ConditionOSQueryBuilderDispatcher.java | 131 + .../META-INF/cxs/mappings/event.json | 64 + .../META-INF/cxs/mappings/personaSession.json | 41 + .../META-INF/cxs/mappings/profile.json | 54 + .../META-INF/cxs/mappings/profileAlias.json | 28 + .../META-INF/cxs/mappings/session.json | 73 + .../META-INF/cxs/mappings/systemItems.json | 141 + .../OSGI-INF/blueprint/blueprint.xml | 179 + .../core/src/main/resources/log4j2.xml | 29 + ...rg.apache.unomi.persistence.opensearch.cfg | 116 + persistence-opensearch/pom.xml | 56 + persistence-spi/pom.xml | 123 + .../conditions/ConditionContextHelper.java | 22 +- .../spi}/conditions/ConditionEvaluator.java | 2 +- .../ConditionEvaluatorDispatcher.java | 32 + .../ConditionEvaluatorDispatcherImpl.java | 12 +- .../OSGI-INF/blueprint/blueprint.xml | 46 + .../main/resources/mapping-FoldToASCII.txt | 3813 +++++++++++++++++ .../MergeProfilesOnPropertyAction.java | 8 +- .../conditions/BooleanConditionEvaluator.java | 4 +- ...ationByPointSessionConditionEvaluator.java | 16 +- .../conditions/IdsConditionEvaluator.java | 4 +- .../MatchAllConditionEvaluator.java | 4 +- .../conditions/NestedConditionEvaluator.java | 8 +- .../conditions/NotConditionEvaluator.java | 4 +- .../PastEventConditionESQueryBuilder.java | 70 +- .../PastEventConditionEvaluator.java | 4 +- .../PropertyConditionESQueryBuilder.java | 2 +- .../PropertyConditionEvaluator.java | 64 +- ...SourceEventPropertyConditionEvaluator.java | 6 +- .../OSGI-INF/blueprint/blueprint.xml | 18 +- pom.xml | 19 +- rest/pom.xml | 20 + .../service/impl/RestServiceUtilsImpl.java | 60 +- .../sorts/FilterPersonalizationStrategy.java | 8 +- .../org/apache/unomi/shell/actions/Start.java | 12 +- .../services/UnomiManagementService.java | 2 +- .../internal/UnomiManagementServiceImpl.java | 44 +- 73 files changed, 9803 insertions(+), 629 deletions(-) delete mode 100644 graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json delete mode 100644 persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/ElasticsearchPersistenceTest.java create mode 100644 persistence-opensearch/conditions/pom.xml create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 persistence-opensearch/core/pom.xml create mode 100644 persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSCustomObjectMapper.java rename tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless => persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSEventMixIn.java (70%) create mode 100644 persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSItemMixIn.java create mode 100644 persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java create mode 100644 persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java create mode 100644 persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java create mode 100644 persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/event.json create mode 100644 persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/personaSession.json create mode 100644 persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profile.json create mode 100644 persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json create mode 100644 persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/session.json create mode 100644 persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/systemItems.json create mode 100644 persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 persistence-opensearch/core/src/main/resources/log4j2.xml create mode 100644 persistence-opensearch/core/src/main/resources/org.apache.unomi.persistence.opensearch.cfg create mode 100644 persistence-opensearch/pom.xml rename {persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch => persistence-spi/src/main/java/org/apache/unomi/persistence/spi}/conditions/ConditionContextHelper.java (90%) rename {persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch => persistence-spi/src/main/java/org/apache/unomi/persistence/spi}/conditions/ConditionEvaluator.java (94%) create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcher.java rename persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluatorDispatcher.java => persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcherImpl.java (90%) create mode 100644 persistence-spi/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 persistence-spi/src/main/resources/mapping-FoldToASCII.txt diff --git a/.github/workflows/unomi-ci-build-tests.yml b/.github/workflows/unomi-ci-build-tests.yml index 1c3d95b92..aaafa2d79 100644 --- a/.github/workflows/unomi-ci-build-tests.yml +++ b/.github/workflows/unomi-ci-build-tests.yml @@ -14,38 +14,43 @@ jobs: name: Execute unit tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - cache: maven - - name: Build and Unit tests - run: mvn -U -ntp -e clean install + - uses: actions/checkout@v4 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + cache: maven + - name: Build and Unit tests + run: mvn -U -ntp -e clean install integration-tests: name: Execute integration tests + needs: unit-tests runs-on: ubuntu-latest + strategy: + matrix: + search-engine: [elasticsearch, opensearch] + fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: 11 cache: maven - name: Integration tests - run: mvn -ntp clean install -Pintegration-tests + run: mvn -ntp clean install -Pintegration-tests,${{ matrix.search-engine }} - name: Archive code coverage logs uses: actions/upload-artifact@v3 if: false # UNOMI-746 Reactivate if necessary with: - name: unomi-code-coverage-jdk11-${{ github.run_number }} + name: unomi-code-coverage-jdk11-${{ matrix.search-engine }}-${{ github.run_number }} path: itests/target/site/jacoco - name: Archive unomi logs uses: actions/upload-artifact@v3 if: failure() with: - name: unomi-log-jdk11-${{ github.run_number }} + name: unomi-log-jdk11-${{ matrix.search-engine }}-${{ github.run_number }} path: | itests/target/exam/**/data/log itests/target/elasticsearch0/data diff --git a/.github/workflows/unomi-ci-docs-deploy.yml b/.github/workflows/unomi-ci-docs-deploy.yml index 081b68006..856750220 100644 --- a/.github/workflows/unomi-ci-docs-deploy.yml +++ b/.github/workflows/unomi-ci-docs-deploy.yml @@ -12,7 +12,7 @@ jobs: name: Publish Javadoc and snapshots runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v1 with: @@ -32,7 +32,7 @@ jobs: name: Push Docker image snapshot runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up JDK 11 uses: actions/setup-java@v1 with: diff --git a/extensions/privacy-extension/rest/pom.xml b/extensions/privacy-extension/rest/pom.xml index 40944542c..7cd66c70c 100644 --- a/extensions/privacy-extension/rest/pom.xml +++ b/extensions/privacy-extension/rest/pom.xml @@ -88,6 +88,7 @@ + diff --git a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json deleted file mode 100644 index 664c4641b..000000000 --- a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "metadata" : { - "id": "cdp_sessionEvent", - "name": "Update session", - "description" : "Update session", - "readOnly":true - }, - - "condition" : { - "type": "cdpSessionEventCondition", - "parameterValues": { - } - }, - - "actions" : [ - { - "type": "cdpSessionEventAction", - "parameterValues": { - - } - } - ] - -} diff --git a/itests/README.md b/itests/README.md index b49831889..85e5aca2d 100644 --- a/itests/README.md +++ b/itests/README.md @@ -56,6 +56,20 @@ You can run the integration tests along with the build by doing: from the project's root directory +### Search Engine Selection + +The integration tests can be run against either ElasticSearch (default) or OpenSearch: + +```bash +# Run with ElasticSearch (default) +mvn clean install -P integration-tests -Duse.opensearch=false + +# Run with OpenSearch +mvn clean install -P integration-tests -Duse.opensearch=true +``` + +## Debugging integration tests + If you want to run the tests with a debugger, you can use the `it.karaf.debug` system property. Here's an example: diff --git a/itests/pom.xml b/itests/pom.xml index 38e9c51c3..ecb75133c 100644 --- a/itests/pom.xml +++ b/itests/pom.xml @@ -27,6 +27,11 @@ Apache Unomi :: Integration Tests Apache Unomi Context Server integration tests + + elasticsearch + false + + @@ -145,64 +150,153 @@ - + + + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.3.0 + + + + pre-integration-test + + wget + + + + https://search.maven.org/remotecontent?filepath=org/jacoco/jacoco/0.8.8/jacoco-0.8.8.zip + + jacoco.zip + true + ${project.build.directory}/jacoco/ + false + + + + + + + org.apache.servicemix.tooling + depends-maven-plugin + + + generate-depends-file + generate-resources + + generate-depends-file + + + + + + maven-antrun-plugin + 1.8 + + + generate-resources + + + + + + + run + + + + + + + - run-tests + jacoco-report-exec - true + false - com.googlecode.maven-download-plugin - download-maven-plugin - 1.3.0 + exec-maven-plugin + org.codehaus.mojo - - pre-integration-test + Generate code coverage report + verify - wget + exec - - https://search.maven.org/remotecontent?filepath=org/jacoco/jacoco/0.8.8/jacoco-0.8.8.zip - - jacoco.zip - true - ${project.build.directory}/jacoco/ - false + ${basedir}/jacoco-report.sh - + + + + + itest-code-coverage + + + it.code.coverage + true + + + + - org.apache.servicemix.tooling - depends-maven-plugin + org.jacoco + jacoco-maven-plugin + 0.7.7.201606060606 - generate-depends-file + post-site + report - generate-depends-file + report + + + + + elasticsearch + + true + + !use.opensearch + + + + - maven-antrun-plugin - 1.8 + org.apache.maven.plugins + maven-failsafe-plugin + 3.0.0-M4 + + + **/*AllITs.java + + + foo + elasticsearch + + - generate-resources - - - - - + integration-test - run + integration-test + + + + verify + + verify @@ -210,7 +304,6 @@ com.github.alexcojocaru elasticsearch-maven-plugin - 6.23 contextElasticSearchITests @@ -218,7 +311,6 @@ 9400 ${elasticsearch.test.version} true - 120 -Xms4g -Xmx4g @@ -234,10 +326,6 @@ - start-elasticsearch pre-integration-test @@ -254,6 +342,18 @@ + + + + + opensearch + + + use.opensearch + + + + org.apache.maven.plugins maven-failsafe-plugin @@ -264,6 +364,7 @@ foo + opensearch @@ -281,55 +382,59 @@ - - - - - jacoco-report-exec - - false - - - - exec-maven-plugin - org.codehaus.mojo + io.fabric8 + docker-maven-plugin + 0.45.1 + + + + opensearchproject/opensearch:${opensearch.version} + opensearch + + + 9400:9200 + + + single-node + -Xms4g -Xmx4g + /tmp/snapshots_repository + true + Unomi.1ntegrat10n.Tests + + + + ${project.build.directory}/snapshots_repository:/tmp/snapshots_repository + + + + + http://localhost:9400 + GET + 200 + + + + + + + - Generate code coverage report - verify + start-opensearch + pre-integration-test - exec + start - ${basedir}/jacoco-report.sh + true - - - - - - - itest-code-coverage - - - it.code.coverage - true - - - - - - org.jacoco - jacoco-maven-plugin - 0.7.7.201606060606 - - post-site - report + stop-opensearch + post-integration-test - report + stop diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java index 28cf43c7b..cfa2b274d 100644 --- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; import org.apache.commons.io.IOUtils; @@ -122,8 +123,13 @@ public abstract class BaseIT extends KarafTestSupport { protected static final int DEFAULT_TRYING_TIMEOUT = 2000; protected static final int DEFAULT_TRYING_TRIES = 30; + protected static final String SEARCH_ENGINE_PROPERTY = "unomi.search.engine"; + protected static final String SEARCH_ENGINE_ELASTICSEARCH = "elasticsearch"; + protected static final String SEARCH_ENGINE_OPENSEARCH = "opensearch"; + protected final static ObjectMapper objectMapper; protected static boolean unomiStarted = false; + protected static String searchEngine = SEARCH_ENGINE_ELASTICSEARCH; static { objectMapper = new ObjectMapper(); @@ -166,7 +172,11 @@ public void waitForStartup() throws InterruptedException { // Start Unomi if not already done if (!unomiStarted) { - executeCommand("unomi:start"); + if (SEARCH_ENGINE_ELASTICSEARCH.equals(searchEngine)) { + executeCommand("unomi:start"); + } else { + executeCommand("unomi:start opensearch"); + } unomiStarted = true; } @@ -196,7 +206,7 @@ public void waitForStartup() throws InterruptedException { routerCamelContext = getOsgiService(IRouterCamelContext.class, 600000); // init httpClient - httpClient = initHttpClient(); + httpClient = initHttpClient(getHttpClientCredentialProvider()); } @After @@ -259,6 +269,7 @@ public Option[] config() { systemProperty("org.apache.unomi.hazelcast.network.port").value("5701"), systemProperty("org.apache.unomi.hazelcast.tcp-ip.members").value("127.0.0.1"), systemProperty("org.apache.unomi.hazelcast.tcp-ip.interface").value("127.0.0.1"), + systemProperty("org.apache.unomi.healthcheck.enabled").value("true"), logLevel(LogLevel.INFO), keepRuntimeFolder(), @@ -307,6 +318,9 @@ public Option[] config() { karafOptions.add(editConfigurationFilePut("etc/org.ops4j.pax.logging.cfg", "log4j2.logger.customLogging.level", customLoggingParts[1])); } + searchEngine = System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH); + System.out.println("Search Engine: " + searchEngine); + return Stream.of(super.config(), karafOptions.toArray(new Option[karafOptions.size()])).flatMap(Stream::of).toArray(Option[]::new); } @@ -546,18 +560,17 @@ protected CloseableHttpResponse executeHttpRequest(HttpUriRequest request) throw protected String resourceAsString(final String resource) { final java.net.URL url = bundleContext.getBundle().getResource(resource); try (InputStream stream = url.openStream()) { - return objectMapper.writeValueAsString(objectMapper.readTree(stream)); + JsonNode node = objectMapper.readTree(stream); + String value = objectMapper.writeValueAsString(node); + return value; } catch (final Exception e) { throw new RuntimeException(e); } } - public static CloseableHttpClient initHttpClient() { + public static CloseableHttpClient initHttpClient(BasicCredentialsProvider credentialsProvider) { long requestStartTime = System.currentTimeMillis(); - BasicCredentialsProvider credsProvider = null; - credsProvider = new BasicCredentialsProvider(); - credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(BASIC_AUTH_USER_NAME, BASIC_AUTH_PASSWORD)); - HttpClientBuilder httpClientBuilder = HttpClients.custom().useSystemProperties().setDefaultCredentialsProvider(credsProvider); + HttpClientBuilder httpClientBuilder = HttpClients.custom().useSystemProperties().setDefaultCredentialsProvider(credentialsProvider); try { SSLContext sslContext = SSLContext.getInstance("SSL"); @@ -610,4 +623,33 @@ public static void closeHttpClient(CloseableHttpClient httpClient) { LOGGER.error("Could not close httpClient: " + httpClient, e); } } + + public BasicCredentialsProvider getHttpClientCredentialProvider() { + BasicCredentialsProvider credsProvider = new BasicCredentialsProvider(); + credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(BASIC_AUTH_USER_NAME, BASIC_AUTH_PASSWORD)); + return credsProvider; + } + + /** + * @return true if ElasticSearch is the current search engine + */ + protected boolean isElasticSearch() { + String searchEngine = System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH); + return SEARCH_ENGINE_ELASTICSEARCH.equals(searchEngine); + } + + /** + * @return true if OpenSearch is the current search engine + */ + protected boolean isOpenSearch() { + String searchEngine = System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH); + return SEARCH_ENGINE_OPENSEARCH.equals(searchEngine); + } + + /** + * @return the current search engine name + */ + protected String getCurrentSearchEngine() { + return System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH); + } } diff --git a/itests/src/test/resources/org.apache.unomi.router.cfg b/itests/src/test/resources/org.apache.unomi.router.cfg index 6d5f985bb..6d121a402 100644 --- a/itests/src/test/resources/org.apache.unomi.router.cfg +++ b/itests/src/test/resources/org.apache.unomi.router.cfg @@ -40,4 +40,10 @@ executionsHistory.size=5 executions.error.report.size=200 #Allowed source endpoints -config.allowedEndpoints=file,ftp,sftp,ftps \ No newline at end of file +config.allowedEndpoints=file,ftp,sftp,ftps + +# ElasticSearch configuration +-elasticsearch.cluster.name=contextElasticSearchITests +-elasticsearch.addresses=localhost:9400 ++search.engine.cluster.name=${env:SEARCH_ENGINE_CLUSTER_NAME:-contextElasticSearchITests} ++search.engine.addresses=localhost:9400 \ No newline at end of file diff --git a/kar/pom.xml b/kar/pom.xml index b3b678f3a..aa71063f9 100644 --- a/kar/pom.xml +++ b/kar/pom.xml @@ -69,6 +69,16 @@ unomi-persistence-elasticsearch-core ${project.version} + + org.apache.unomi + unomi-persistence-opensearch-core + ${project.version} + + + org.apache.unomi + unomi-persistence-opensearch-conditions + ${project.version} + org.apache.unomi unomi-plugins-base diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml index e16b43e0e..8dfa504ae 100644 --- a/kar/src/main/feature/feature.xml +++ b/kar/src/main/feature/feature.xml @@ -21,8 +21,7 @@ mvn:org.apache.cxf.karaf/apache-cxf/${cxf.version}/xml/features mvn:org.apache.karaf.cellar/apache-karaf-cellar/${version.karaf.cellar}/xml/features - + wrap aries-blueprint war @@ -36,6 +35,7 @@ shell-compat mvn:org.apache.unomi/unomi-wab/${project.version}/cfg/unomicfg mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/cfg/elasticsearchcfg + mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version}/cfg/opensearchcfg mvn:org.apache.unomi/unomi-plugins-request/${project.version}/cfg/requestcfg mvn:org.apache.unomi/unomi-plugins-base/${project.version}/cfg/pluginsbasecfg mvn:org.apache.unomi/unomi-services/${project.version}/cfg/servicescfg @@ -72,6 +72,8 @@ mvn:org.apache.unomi/unomi-metrics/${project.version} mvn:org.apache.unomi/unomi-persistence-spi/${project.version} mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version} + mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version} + mvn:org.apache.unomi/unomi-persistence-opensearch-conditions/${project.version} mvn:org.apache.unomi/unomi-services/${project.version} mvn:org.apache.unomi/unomi-json-schema-services/${project.version} mvn:org.apache.unomi/unomi-json-schema-rest/${project.version} @@ -93,6 +95,8 @@ mvn:org.apache.unomi/shell-commands/${project.version}/cfg/migration mvn:org.apache.unomi/shell-commands/${project.version} + mvn:org.apache.unomi/healthcheck/${project.version}/cfg/healthcheck + mvn:org.apache.unomi/healthcheck/${project.version} diff --git a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml index d2ae880bb..015e5edbd 100644 --- a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -28,7 +28,7 @@ update-strategy="reload" placeholder-prefix="${lifecycle."> - + diff --git a/metrics/pom.xml b/metrics/pom.xml index e9b33376f..dd55cc91b 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -45,13 +45,6 @@ provided - - org.apache.unomi - unomi-persistence-spi - ${project.version} - provided - - com.fasterxml.jackson.core jackson-core diff --git a/package/pom.xml b/package/pom.xml index c66d2f6ec..0a5b1ac02 100644 --- a/package/pom.xml +++ b/package/pom.xml @@ -192,6 +192,17 @@ org.apache.unomi.persistence.elasticsearch.cfg + + org.apache.unomi + unomi-persistence-opensearch-core + ${project.version} + opensearchcfg + cfg + + ${project.build.directory}/assembly/etc + + org.apache.unomi.persistence.opensearch.cfg + org.apache.unomi unomi-services @@ -333,6 +344,9 @@ + + mvn:org.apache.unomi/log4j-extension/2.6.0-SNAPSHOT + wrapper cxf-commands diff --git a/package/src/main/resources/etc/custom.system.properties b/package/src/main/resources/etc/custom.system.properties index 72f42330e..50a5e1014 100644 --- a/package/src/main/resources/etc/custom.system.properties +++ b/package/src/main/resources/etc/custom.system.properties @@ -165,6 +165,79 @@ org.apache.unomi.elasticsearch.password=${env:UNOMI_ELASTICSEARCH_PASSWORD:-} org.apache.unomi.elasticsearch.sslEnable=${env:UNOMI_ELASTICSEARCH_SSL_ENABLE:-false} org.apache.unomi.elasticsearch.sslTrustAllCertificates=${env:UNOMI_ELASTICSEARCH_SSL_TRUST_ALL_CERTIFICATES:-false} +####################################################################################################################### +## OpenSearch settings ## +####################################################################################################################### +org.apache.unomi.opensearch.cluster.name=${env:UNOMI_OPENSEARCH_CLUSTERNAME:-opensearch-cluster} +# The opensearch.addresses may be a comma seperated list of host names and ports such as +# hostA:9200,hostB:9200 +# Note: the port number must be repeated for each host. +org.apache.unomi.opensearch.addresses=${env:UNOMI_OPENSEARCH_ADDRESSES:-localhost:9200} +# refresh policy per item type in Json. +# Valid values are WAIT_UNTIL/IMMEDIATE/NONE. The default refresh policy is NONE. +# Example: "{"event":"WAIT_UNTIL","rule":"NONE"} +org.apache.unomi.opensearch.itemTypeToRefreshPolicy=${env:UNOMI_OPENSEARCH_REFRESH_POLICY_PER_ITEM_TYPE:-} +org.apache.unomi.opensearch.fatalIllegalStateErrors=${env:UNOMI_OPENSEARCH_FATAL_STATE_ERRORS:-} +org.apache.unomi.opensearch.index.prefix=${env:UNOMI_OPENSEARCH_INDEXPREFIX:-context} + +# These monthlyIndex properties are now deprecated, please use rollover equivalent. +org.apache.unomi.opensearch.monthlyIndex.nbShards=${env:UNOMI_OPENSEARCH_MONTHLYINDEX_SHARDS:-5} +org.apache.unomi.opensearch.monthlyIndex.nbReplicas=${env:UNOMI_OPENSEARCH_MONTHLYINDEX_REPLICAS:-0} +org.apache.unomi.opensearch.monthlyIndex.indexMappingTotalFieldsLimit=${env:UNOMI_OPENSEARCH_MONTHLYINDEX_MAPPINGTOTALFIELDSLIMIT:-1000} +org.apache.unomi.opensearch.monthlyIndex.indexMaxDocValueFieldsSearch=${env:UNOMI_OPENSEARCH_MONTHLYINDEX_MAXDOCVALUEFIELDSSEARCH:-1000} +org.apache.unomi.opensearch.monthlyIndex.itemsMonthlyIndexedOverride=${env:UNOMI_OPENSEARCH_MONTHLYINDEX_ITEMSMONTHLYINDEXED:-event,session} +# New rollover properties (it overrides monthlyIndex values) +org.apache.unomi.opensearch.rollover.nbShards=${env:UNOMI_OPENSEARCH_ROLLOVER_SHARDS} +org.apache.unomi.opensearch.rollover.nbReplicas=${env:UNOMI_OPENSEARCH_ROLLOVER_REPLICAS} +org.apache.unomi.opensearch.rollover.indexMappingTotalFieldsLimit=${env:UNOMI_OPENSEARCH_ROLLOVER_MAPPINGTOTALFIELDSLIMIT} +org.apache.unomi.opensearch.rollover.indexMaxDocValueFieldsSearch=${env:UNOMI_OPENSEARCH_ROLLOVER_MAXDOCVALUEFIELDSSEARCH} +org.apache.unomi.opensearch.rollover.indices=${env:UNOMI_OPENSEARCH_ROLLOVER_INDICES} + +# Rollover configuration +org.apache.unomi.opensearch.rollover.maxSize=${env:UNOMI_OPENSEARCH_ROLLOVER_MAXSIZE:-30gb} +org.apache.unomi.opensearch.rollover.maxAge=${env:UNOMI_OPENSEARCH_ROLLOVER_MAXAGE:-} +org.apache.unomi.opensearch.rollover.maxDocs=${env:UNOMI_OPENSEARCH_ROLLOVER_MAXDOCS:-} + +org.apache.unomi.opensearch.defaultIndex.nbShards=${env:UNOMI_OPENSEARCH_DEFAULTINDEX_SHARDS:-5} +org.apache.unomi.opensearch.defaultIndex.nbReplicas=${env:UNOMI_OPENSEARCH_DEFAULTINDEX_REPLICAS:-0} +org.apache.unomi.opensearch.defaultIndex.indexMappingTotalFieldsLimit=${env:UNOMI_OPENSEARCH_DEFAULTINDEX_MAPPINGTOTALFIELDSLIMIT:-1000} +org.apache.unomi.opensearch.defaultIndex.indexMaxDocValueFieldsSearch=${env:UNOMI_OPENSEARCH_DEFAULTINDEX_MAXDOCVALUEFIELDSSEARCH:-1000} +org.apache.unomi.opensearch.defaultQueryLimit=${env:UNOMI_OPENSEARCH_DEFAULTQUERYLIMIT:-10} +org.apache.unomi.opensearch.aggregateQueryBucketSize=${env:UNOMI_OPENSEARCH_AGGREGATEBUCKETSIZE:-5000} +org.apache.unomi.opensearch.maximumIdsQueryCount=${env:UNOMI_OPENSEARCH_MAXIMUMIDSQUERYCOUNT:-5000} +# Defines the socket timeout (SO_TIMEOUT) in milliseconds, which is the timeout for waiting for data or, put differently, a maximum period inactivity between two consecutive data packets). +# A timeout value of zero is interpreted as an infinite timeout. A negative value is interpreted as undefined (system default). +# Default: -1 (System default) +org.apache.unomi.opensearch.clientSocketTimeout=${env:UNOMI_OPENSEARCH_CLIENT_SOCKET_TIMEOUT:--1} +# Defines the waiting for task completion timeout in milliseconds. +# Some operations like update_by_query and delete_by_query are delegated to ElasticSearch using tasks +# For consistency the thread that trigger one of those operations will wait for the task to be completed on ElasticSearch side. +# This timeout configuration is here to ensure not blocking the thread infinitely, in case of very long running tasks. +# A timeout value of zero or negative is interpreted as an infinite timeout. +# Default: 3600000 (one hour) +org.apache.unomi.opensearch.taskWaitingTimeout=${env:UNOMI_OPENSEARCH_TASK_WAITING_TIMEOUT:-3600000} +# Defines the polling interval in milliseconds, which is used to check if task is completed on ElasticSearch side +# Default: 1000 (1 second) +org.apache.unomi.opensearch.taskWaitingPollingInterval=${env:UNOMI_OPENSEARCH_TASK_WAITING_POLLING_INTERVAL:-1000} +org.apache.unomi.opensearch.pastEventsDisablePartitions=${env:UNOMI_OPENSEARCH_PAST_EVENTS_DISABLE_PARTITIONS:-false} +org.apache.unomi.opensearch.aggQueryThrowOnMissingDocs=${env:UNOMI_OPENSEARCH_AGG_QUERY_THROW_ON_MISSING_DOCS:-false} +org.apache.unomi.opensearch.aggQueryMaxResponseSizeHttp=${env:UNOMI_OPENSEARCH_AGG_QUERY_MAX_RESPONSE_SIZE_HTTP:-} +# The following settings control the behavior of the BulkProcessor API. You can find more information about these +# settings and their behavior here : https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.4/java-docs-bulk-processor.html +# The values used here are the default values of the API +org.apache.unomi.opensearch.bulkProcessor.concurrentRequests=${env:UNOMI_OPENSEARCH_BULK_CONCURRENTREQUESTS:-1} +org.apache.unomi.opensearch.bulkProcessor.bulkActions=${env:UNOMI_OPENSEARCH_BULK_ACTIONS:-1000} +org.apache.unomi.opensearch.bulkProcessor.bulkSize=${env:UNOMI_OPENSEARCH_BULK_SIZE:-5MB} +org.apache.unomi.opensearch.bulkProcessor.flushInterval=${env:UNOMI_OPENSEARCH_BULK_FLUSHINTERVAL:-5s} +org.apache.unomi.opensearch.bulkProcessor.backoffPolicy=${env:UNOMI_OPENSEARCH_BULK_BACKOFFPOLICY:-exponential} +# Errors +org.apache.unomi.opensearch.throwExceptions=${env:UNOMI_OPENSEARCH_THROW_EXCEPTIONS:-false} +# Authentication +org.apache.unomi.opensearch.username=${env:UNOMI_OPENSEARCH_USERNAME:-admin} +org.apache.unomi.opensearch.password=${env:UNOMI_OPENSEARCH_PASSWORD:-} +org.apache.unomi.opensearch.sslEnable=${env:UNOMI_OPENSEARCH_SSL_ENABLE:-true} +org.apache.unomi.opensearch.sslTrustAllCertificates=${env:UNOMI_OPENSEARCH_SSL_TRUST_ALL_CERTIFICATES:-true} + ####################################################################################################################### ## Service settings ## ####################################################################################################################### @@ -443,4 +516,20 @@ org.apache.unomi.graphql.feature.activated=${env:UNOMI_GRAPHQL_FEATURE_ACTIVATED ####################################################################################################################### ## Settings for migration ## ####################################################################################################################### -org.apache.unomi.migration.recoverFromHistory=${env:UNOMI_MIGRATION_RECOVER_FROM_HISTORY:-true} \ No newline at end of file +org.apache.unomi.migration.recoverFromHistory=${env:UNOMI_MIGRATION_RECOVER_FROM_HISTORY:-true} + +####################################################################################################################### +## HealthCheck Settings ## +####################################################################################################################### +org.apache.unomi.healthcheck.enabled:${env:UNOMI_HEALTHCHECK_ENABLED:-true} +org.apache.unomi.healthcheck.password=${env:UNOMI_HEALTHCHECK_PASSWORD:-health} +# +# Specify the list of health check providers (name) to use. The list is comma separated. Other providers will be ignored. +# As Karaf provider is the one needed by healthcheck (always LIVE), it cannot be ignored. +# +org.apache.unomi.healthcheck.providers:${env:UNOMI_HEALTHCHECK_PROVIDERS:-cluster,elasticsearch,unomi,persistence} +# +# Specify the timeout in milliseconds for each healthcheck provider call. The default value is 400ms. +# If timeout is raised, the provider is marked in ERROR. +# +org.apache.unomi.healthcheck.timeout:${env:UNOMI_HEALTHCHECK_TIMEOUT:-400} diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java index d2a11ed52..a691cf0ae 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java +++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java @@ -40,6 +40,9 @@ import org.apache.unomi.persistence.elasticsearch.conditions.*; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.*; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.Version; import org.elasticsearch.action.DocWriteRequest; @@ -142,7 +145,7 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService, public static final String SEQ_NO = "seq_no"; public static final String PRIMARY_TERM = "primary_term"; - private static final Logger logger = LoggerFactory.getLogger(ElasticSearchPersistenceServiceImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ElasticSearchPersistenceServiceImpl.class.getName()); private static final String ROLLOVER_LIFECYCLE_NAME = "unomi-rollover-policy"; private boolean throwExceptions = false; @@ -495,18 +498,18 @@ public Object execute(Object... args) throws Exception { } // Wait for green - logger.info("Waiting for GREEN cluster status..."); + LOGGER.info("Waiting for GREEN cluster status..."); client.cluster().health(new ClusterHealthRequest().waitForGreenStatus(), RequestOptions.DEFAULT); - logger.info("Cluster status is GREEN"); + LOGGER.info("Cluster status is GREEN"); // We keep in memory the latest available session index to be able to load session using direct GET access on ES if (isItemTypeRollingOver(Session.ITEM_TYPE)) { - logger.info("Sessions are using rollover indices, loading latest session index available ..."); + LOGGER.info("Sessions are using rollover indices, loading latest session index available ..."); GetAliasesResponse sessionAliasResponse = client.indices().getAlias(new GetAliasesRequest(getIndex(Session.ITEM_TYPE)), RequestOptions.DEFAULT); Map> aliases = sessionAliasResponse.getAliases(); if (!aliases.isEmpty()) { sessionLatestIndex = new TreeSet<>(aliases.keySet()).last(); - logger.info("Latest available session index found is: {}", sessionLatestIndex); + LOGGER.info("Latest available session index found is: {}", sessionLatestIndex); } else { throw new IllegalStateException("No index found for sessions"); } @@ -518,7 +521,7 @@ public Object execute(Object... args) throws Exception { bundleContext.addBundleListener(this); - logger.info(this.getClass().getName() + " service started successfully."); + LOGGER.info("{} service started successfully.", this.getClass().getName()); } private void buildClient() throws NoSuchFieldException, IllegalAccessException { @@ -561,7 +564,7 @@ public void checkServerTrusted(X509Certificate[] certs, httpClientBuilder.setSSLContext(sslContext).setSSLHostnameVerifier(new NoopHostnameVerifier()); } catch (NoSuchAlgorithmException | KeyManagementException e) { - logger.error("Error creating SSL Context for trust all certificates", e); + LOGGER.error("Error creating SSL Context for trust all certificates", e); } } @@ -575,7 +578,7 @@ public void checkServerTrusted(X509Certificate[] certs, return httpClientBuilder; }); - logger.info("Connecting to ElasticSearch persistence backend using cluster name " + clusterName + " and index prefix " + indexPrefix + "..."); + LOGGER.info("Connecting to ElasticSearch persistence backend using cluster name {} and index prefix {}...", clusterName, indexPrefix); client = new CustomRestHighLevelClient(clientBuilder); } @@ -587,21 +590,21 @@ public BulkProcessor getBulkProcessor() { @Override public void beforeBulk(long executionId, BulkRequest request) { - logger.debug("Before Bulk"); + LOGGER.debug("Before Bulk"); } @Override public void afterBulk(long executionId, BulkRequest request, BulkResponse response) { - logger.debug("After Bulk"); + LOGGER.debug("After Bulk"); } @Override public void afterBulk(long executionId, BulkRequest request, Throwable failure) { - logger.error("After Bulk (failure)", failure); + LOGGER.error("After Bulk (failure)", failure); } }; BulkProcessor.Builder bulkProcessorBuilder = BulkProcessor.builder( @@ -665,12 +668,12 @@ public void stop() { new InClassLoaderExecute(null, null, this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { protected Object execute(Object... args) throws IOException { - logger.info("Closing ElasticSearch persistence backend..."); + LOGGER.info("Closing ElasticSearch persistence backend..."); if (bulkProcessor != null) { try { bulkProcessor.awaitClose(2, TimeUnit.MINUTES); } catch (InterruptedException e) { - logger.error("Error waiting for bulk operations to flush !", e); + LOGGER.error("Error waiting for bulk operations to flush !", e); } } if (client != null) { @@ -724,7 +727,7 @@ private void loadPredefinedMappings(BundleContext bundleContext, boolean forceUp } while (predefinedMappings.hasMoreElements()) { URL predefinedMappingURL = predefinedMappings.nextElement(); - logger.info("Found mapping at " + predefinedMappingURL + ", loading... "); + LOGGER.info("Found mapping at {}, loading... ", predefinedMappingURL); try { final String path = predefinedMappingURL.getPath(); String name = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.')); @@ -733,14 +736,14 @@ private void loadPredefinedMappings(BundleContext bundleContext, boolean forceUp mappings.put(name, mappingSource); if (!createIndex(name)) { - logger.info("Found index for type {}", name); + LOGGER.info("Found index for type {}", name); if (forceUpdateMapping) { - logger.info("Updating mapping for {}", name); + LOGGER.info("Updating mapping for {}", name); createMapping(name, mappingSource); } } } catch (Exception e) { - logger.error("Error while loading mapping definition " + predefinedMappingURL, e); + LOGGER.error("Error while loading mapping definition {}", predefinedMappingURL, e); } } } @@ -754,13 +757,13 @@ private void loadPainlessScripts(BundleContext bundleContext) { Map scriptsById = new HashMap<>(); while (scriptsURL.hasMoreElements()) { URL scriptURL = scriptsURL.nextElement(); - logger.info("Found painless script at " + scriptURL + ", loading... "); + LOGGER.info("Found painless script at {}, loading... ", scriptURL); try (InputStream in = scriptURL.openStream()) { String script = IOUtils.toString(in, StandardCharsets.UTF_8); String scriptId = FilenameUtils.getBaseName(scriptURL.getPath()); scriptsById.put(scriptId, script); } catch (Exception e) { - logger.error("Error while loading painless script " + scriptURL, e); + LOGGER.error("Error while loading painless script {}", scriptURL, e); } } @@ -972,7 +975,7 @@ protected Boolean execute(Object... args) throws Exception { } logMetadataItemOperation("saved", item); } catch (IndexNotFoundException e) { - logger.error("Could not find index {}, could not register item type {} with id {} ", index, itemType, item.getItemId(), e); + LOGGER.error("Could not find index {}, could not register item type {} with id {} ", index, itemType, item.getItemId(), e); return false; } return true; @@ -1034,11 +1037,7 @@ protected Boolean execute(Object... args) throws Exception { } } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } private UpdateRequest createUpdateRequest(Class clazz, Item item, Map source, boolean alwaysOverwrite) { @@ -1077,7 +1076,7 @@ protected List execute(Object... args) throws Exception { }); BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT); - logger.debug("{} profiles updated with bulk segment in {}ms", bulkRequest.numberOfActions(), System.currentTimeMillis() - batchRequestStartTime); + LOGGER.debug("{} profiles updated with bulk segment in {}ms", bulkRequest.numberOfActions(), System.currentTimeMillis() - batchRequestStartTime); List failedItemsIds = new ArrayList<>(); @@ -1148,18 +1147,18 @@ protected Boolean execute(Object... args) throws Exception { TaskSubmissionResponse taskResponse = client.submitUpdateByQuery(updateByQueryRequest, RequestOptions.DEFAULT); if (taskResponse == null) { - logger.error("update with query and script: no response returned for query: {}", queryBuilder); + LOGGER.error("update with query and script: no response returned for query: {}", queryBuilder); } else if (waitForComplete) { waitForTaskComplete(updateByQueryRequest, taskResponse); } else { - logger.debug("ES task started {}", taskResponse.getTask()); + LOGGER.debug("ES task started {}", taskResponse.getTask()); } } return true; } catch (IndexNotFoundException e) { throw new Exception("No index found for itemTypes=" + String.join(",", itemTypes), e); } catch (ScriptException e) { - logger.error("Error in the update script : {}\n{}\n{}", e.getScript(), e.getDetailedMessage(), e.getScriptStack()); + LOGGER.error("Error in the update script : {}\n{}\n{}", e.getScript(), e.getDetailedMessage(), e.getScriptStack()); throw new Exception("Error in the update script"); } } @@ -1172,8 +1171,8 @@ protected Boolean execute(Object... args) throws Exception { } private void waitForTaskComplete(AbstractBulkByScrollRequest request, TaskSubmissionResponse response) { - if (logger.isDebugEnabled()) { - logger.debug("Waiting task [{}]: [{}] using query: [{}], polling every {}ms with a timeout configured to {}ms", + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Waiting task [{}]: [{}] using query: [{}], polling every {}ms with a timeout configured to {}ms", response.getTask(), request.toString(), request.getSearchRequest().source().query(), taskWaitingPollingInterval, taskWaitingTimeout); } long start = System.currentTimeMillis(); @@ -1186,18 +1185,17 @@ protected Void execute(Object... args) throws Exception { if (getTaskResponseOptional.isPresent()) { GetTaskResponse getTaskResponse = getTaskResponseOptional.get(); if (getTaskResponse.isCompleted()) { - if (logger.isDebugEnabled()) { + if (LOGGER.isDebugEnabled()) { long millis = getTaskResponse.getTaskInfo().getRunningTimeNanos() / 1_000_000; long seconds = millis / 1000; - - logger.debug("Waiting task [{}]: Finished in {} {}", taskId, + LOGGER.debug("Waiting task [{}]: Finished in {} {}", taskId, seconds >= 1 ? seconds : millis, seconds >= 1 ? "seconds" : "milliseconds"); } break; } else { if ((start + taskWaitingTimeout) < System.currentTimeMillis()) { - logger.error("Waiting task [{}]: Exceeded configured timeout ({}ms), aborting wait process", taskId, taskWaitingTimeout); + LOGGER.error("Waiting task [{}]: Exceeded configured timeout ({}ms), aborting wait process", taskId, taskWaitingTimeout); break; } @@ -1205,11 +1203,11 @@ protected Void execute(Object... args) throws Exception { Thread.sleep(taskWaitingPollingInterval); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new IllegalStateException("Waiting task [{}]: interrupted"); + throw new IllegalStateException("Waiting task [" + taskId + "]: interrupted"); } } } else { - logger.error("Waiting task [{}]: No task found", taskId); + LOGGER.error("Waiting task [{}]: No task found", taskId); break; } } @@ -1241,19 +1239,15 @@ protected Boolean execute(Object... args) throws Exception { AcknowledgedResponse response = client.putScript(putStoredScriptRequest, RequestOptions.DEFAULT); executedSuccessfully &= response.isAcknowledged(); if (response.isAcknowledged()) { - logger.info("Successfully stored painless script: {}", script.getKey()); + LOGGER.info("Successfully stored painless script: {}", script.getKey()); } else { - logger.error("Failed to store painless script: {}", script.getKey()); + LOGGER.error("Failed to store painless script: {}", script.getKey()); } } return executedSuccessfully; } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean updateWithScript(final Item item, final Date dateHint, final Class clazz, final String script, final Map scriptParams) { @@ -1294,11 +1288,7 @@ protected Boolean execute(Object... args) throws Exception { } } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } @Override @@ -1320,12 +1310,12 @@ protected Boolean execute(Object... args) throws Exception { itemType = customItemType; } String documentId = getDocumentIDForItemType(itemId, itemType); - String index = getIndexNameForQuery(itemType); + String index = getIndex(itemType); DeleteRequest deleteRequest = new DeleteRequest(index, documentId); client.delete(deleteRequest, RequestOptions.DEFAULT); if (MetadataItem.class.isAssignableFrom(clazz)) { - logger.info("Item of type {} with ID {} has been removed", customItemType != null ? customItemType : clazz.getSimpleName(), itemId); + LOGGER.info("Item of type {} with ID {} has been removed", customItemType != null ? customItemType : clazz.getSimpleName(), itemId); } return true; } catch (Exception e) { @@ -1333,11 +1323,7 @@ protected Boolean execute(Object... args) throws Exception { } } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean removeByQuery(final Condition query, final Class clazz) { @@ -1347,17 +1333,13 @@ protected Boolean execute(Object... args) throws Exception { return removeByQuery(queryBuilder, clazz); } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean removeByQuery(QueryBuilder queryBuilder, final Class clazz) throws Exception { try { String itemType = Item.getItemType(clazz); - logger.debug("Remove item of type {} using a query", itemType); + LOGGER.debug("Remove item of type {} using a query", itemType); final DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(getIndexNameForQuery(itemType)) .setQuery(wrapWithItemTypeQuery(itemType, queryBuilder)) // Setting slices to auto will let Elasticsearch choose the number of slices to use. @@ -1376,7 +1358,7 @@ public boolean removeByQuery(QueryBuilder queryBuilder, final C TaskSubmissionResponse taskResponse = client.submitDeleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT); if (taskResponse == null) { - logger.error("Remove by query: no response returned for query: {}", queryBuilder); + LOGGER.error("Remove by query: no response returned for query: {}", queryBuilder); return false; } @@ -1395,11 +1377,7 @@ protected Boolean execute(Object... args) throws IOException { return client.indices().existsTemplate(indexTemplatesExistRequest, RequestOptions.DEFAULT); } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean removeIndexTemplate(final String templateName) { @@ -1410,11 +1388,7 @@ protected Boolean execute(Object... args) throws IOException { return deleteIndexTemplateResponse.isAcknowledged(); } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean registerRolloverLifecyclePolicy() { @@ -1440,15 +1414,11 @@ protected Boolean execute(Object... args) throws IOException { return putLifecyclePolicy.isAcknowledged(); } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean createIndex(final String itemType) { - logger.debug("Create index {}", itemType); + LOGGER.debug("Create index {}", itemType); Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".createIndex", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { protected Boolean execute(Object... args) throws IOException { String index = getIndex(itemType); @@ -1467,12 +1437,7 @@ protected Boolean execute(Object... args) throws IOException { return !indexExists; } }.catchingExecuteInClassLoader(true); - - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } public boolean removeIndex(final String itemType) { @@ -1489,12 +1454,7 @@ protected Boolean execute(Object... args) throws IOException { return indexExists; } }.catchingExecuteInClassLoader(true); - - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } private void internalCreateRolloverTemplate(String itemName) throws IOException { @@ -1523,7 +1483,7 @@ private void internalCreateRolloverTemplate(String itemName) throws IOException " }\n" + "}\n", XContentType.JSON); if (mappings.get(itemName) == null) { - logger.warn("Couldn't find mapping for item {}, won't create monthly index template", itemName); + LOGGER.warn("Couldn't find mapping for item {}, won't create monthly index template", itemName); return; } putIndexTemplateRequest.mapping(mappings.get(itemName), XContentType.JSON); @@ -1534,7 +1494,7 @@ private void internalCreateRolloverIndex(String indexName) throws IOException { CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName + "-000001") .alias(new Alias(indexName).writeIndex(true)); CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT); - logger.info("Index created: [{}], acknowledge: [{}], shards acknowledge: [{}]", createIndexResponse.index(), + LOGGER.info("Index created: [{}], acknowledge: [{}], shards acknowledge: [{}]", createIndexResponse.index(), createIndexResponse.isAcknowledged(), createIndexResponse.isShardsAcknowledged()); } @@ -1562,7 +1522,7 @@ private void internalCreateIndex(String indexName, String mappingSource) throws createIndexRequest.mapping(mappingSource, XContentType.JSON); } CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT); - logger.info("Index created: [{}], acknowledge: [{}], shards acknowledge: [{}]", createIndexResponse.index(), + LOGGER.info("Index created: [{}], acknowledge: [{}], shards acknowledge: [{}]", createIndexResponse.index(), createIndexResponse.isAcknowledged(), createIndexResponse.isShardsAcknowledged()); } @@ -1571,7 +1531,7 @@ public void createMapping(String type, String source) { try { putMapping(source, getIndex(type)); } catch (IOException ioe) { - logger.error("Error while creating mapping for type " + type + " and source " + source, ioe); + LOGGER.error("Error while creating mapping for type {} and source {}", type, source, ioe); } } @@ -1585,7 +1545,7 @@ public void setPropertyMapping(final PropertyType property, final String itemTyp Map subSubMappings = (Map) subMappings.computeIfAbsent("properties", k -> new HashMap<>()); if (subSubMappings.containsKey(property.getItemId())) { - logger.warn("Mapping already exists for type " + itemType + " and property " + property.getItemId()); + LOGGER.warn("Mapping already exists for type {} and property {}", itemType, property.getItemId()); return; } @@ -1602,7 +1562,7 @@ public void setPropertyMapping(final PropertyType property, final String itemTyp putMapping(mappingsSource, getIndex(itemType)); } catch (IOException ioe) { - logger.error("Error while creating mapping for type " + itemType + " and property " + property.getValueTypeId(), ioe); + LOGGER.error("Error while creating mapping for type {} and property {}", itemType, property.getValueTypeId(), ioe); } } @@ -1611,7 +1571,7 @@ private Map createPropertyMapping(final PropertyType property) { final HashMap definition = new HashMap<>(); if (esType == null) { - logger.warn("No predefined type found for property[{}], no mapping will be created", property.getValueTypeId()); + LOGGER.warn("No predefined type found for property[{}], no mapping will be created", property.getValueTypeId()); return Collections.emptyMap(); } else { definition.put("type", esType); @@ -1679,11 +1639,7 @@ protected Boolean execute(Object... args) throws Exception { } } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } @Override @@ -1778,8 +1734,7 @@ private String getPropertyNameWithData(String name, String itemType) { if (propertyMapping == null) { return null; } - if (propertyMapping != null - && "text".equals(propertyMapping.get("type")) + if ("text".equals(propertyMapping.get("type")) && propertyMapping.containsKey("fields") && ((Map) propertyMapping.get("fields")).containsKey("keyword")) { name += ".keyword"; @@ -1792,7 +1747,7 @@ public boolean saveQuery(final String queryName, final String query) { protected Boolean execute(Object... args) throws Exception { //Index the query = register it in the percolator try { - logger.info("Saving query : " + queryName); + LOGGER.info("Saving query : {}", queryName); String index = getIndex(".percolator"); IndexRequest indexRequest = new IndexRequest(index); indexRequest.id(queryName); @@ -1805,11 +1760,7 @@ protected Boolean execute(Object... args) throws Exception { } } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } @Override @@ -1837,11 +1788,7 @@ protected Boolean execute(Object... args) throws Exception { } } }.catchingExecuteInClassLoader(true); - if (result == null) { - return false; - } else { - return result; - } + return Objects.requireNonNullElse(result, false); } @Override @@ -1852,11 +1799,8 @@ public boolean isValidCondition(Condition condition, Item item) { .must(QueryBuilders.idsQuery().addIds(item.getItemId())) .must(conditionESQueryBuilderDispatcher.buildFilter(condition)); } catch (Exception e) { - logger.error("Failed to validate condition. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Failed to validate condition, condition={}", condition, e); - } - + LOGGER.error("Failed to validate condition. See debug log level for more information"); + LOGGER.debug("Failed to validate condition, condition={}", condition, e); return false; } return true; @@ -1868,7 +1812,7 @@ public boolean testMatch(Condition query, Item item) { try { return conditionEvaluatorDispatcher.eval(query, item); } catch (UnsupportedOperationException e) { - logger.error("Eval not supported, continue with query", e); + LOGGER.error("Eval not supported, continue with query", e); } finally { if (metricsService != null && metricsService.isActivated()) { metricsService.updateTimer(this.getClass().getName() + ".testMatchLocally", startTime); @@ -2417,7 +2361,7 @@ protected Boolean execute(Object... args) { try { client.indices().refresh(Requests.refreshRequest(), RequestOptions.DEFAULT); } catch (IOException e) { - e.printStackTrace();//TODO manage ES7 + e.printStackTrace(); //TODO manage ES7 } return true; } @@ -2433,7 +2377,7 @@ protected Boolean execute(Object... args) { String index = getIndex(itemType); client.indices().refresh(Requests.refreshRequest(index), RequestOptions.DEFAULT); } catch (IOException e) { - e.printStackTrace();//TODO manage ES7 + e.printStackTrace(); //TODO manage ES7 } return true; } @@ -2483,7 +2427,7 @@ protected Boolean execute(Object... args) throws Exception { @Override public void purge(final String scope) { - logger.debug("Purge scope {}", scope); + LOGGER.debug("Purge scope {}", scope); new InClassLoaderExecute(metricsService, this.getClass().getName() + ".purgeWithScope", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { @Override protected Void execute(Object... args) throws IOException { @@ -2526,7 +2470,7 @@ protected Void execute(Object... args) throws IOException { final BulkResponse deleteResponse = client.bulk(deleteByScopeBulkRequest, RequestOptions.DEFAULT); if (deleteResponse.hasFailures()) { // do something - logger.warn("Couldn't delete from scope " + scope + ":\n{}", deleteResponse.buildFailureMessage()); + LOGGER.warn("Couldn't delete from scope {}:\n{}", scope, deleteResponse.buildFailureMessage()); } } return null; @@ -2655,7 +2599,7 @@ public T catchingExecuteInClassLoader(boolean logError, Object... args) { private void handleError(Throwable t, boolean logError) { if (logError) { - logger.error("Error while executing in class loader", t); + LOGGER.error("Error while executing in class loader", t); } if (throwExceptions) { throw new RuntimeException(t); @@ -2663,7 +2607,7 @@ private void handleError(Throwable t, boolean logError) { } private void handleFatalStateError() { - logger.error("Fatal state error occurred - stopping application"); + LOGGER.error("Fatal state error occurred - stopping application"); try { this.bundleContext.getBundle(0).stop(); } catch (Throwable tInner) { // Stopping system bundle failed - force exit @@ -2747,7 +2691,7 @@ private WriteRequest.RefreshPolicy getRefreshPolicy(String itemType) { private void logMetadataItemOperation (String operation, Item item) { if (item instanceof MetadataItem) { - logger.info("Item of type {} with ID {} has been {}", item.getItemType(), item.getItemId(), operation); + LOGGER.info("Item of type {} with ID {} has been {}", item.getItemType(), item.getItemId(), operation); } } } diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java index 6bc8b5062..bed2cb5bc 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java +++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java @@ -18,6 +18,7 @@ package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.apache.unomi.scripting.ScriptExecutor; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; @@ -29,7 +30,7 @@ import java.util.concurrent.ConcurrentHashMap; public class ConditionESQueryBuilderDispatcher { - private static final Logger logger = LoggerFactory.getLogger(ConditionESQueryBuilderDispatcher.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(ConditionESQueryBuilderDispatcher.class.getName()); private Map queryBuilders = new ConcurrentHashMap<>(); private ScriptExecutor scriptExecutor; @@ -85,10 +86,8 @@ public QueryBuilder buildFilter(Condition condition, Map context } } else { // if no matching - logger.warn("No matching query builder. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("No matching query builder for condition {} and context {}", condition, context); - } + LOGGER.warn("No matching query builder. See debug log level for more information"); + LOGGER.debug("No matching query builder for condition {} and context {}", condition, context); } return QueryBuilders.matchAllQuery(); @@ -122,10 +121,8 @@ public long count(Condition condition, Map context) { } // if no matching - logger.warn("No matching query builder. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("No matching query builder for condition {} and context {}", condition, context); - } + LOGGER.warn("No matching query builder. See debug log level for more information"); + LOGGER.debug("No matching query builder for condition {} and context {}", condition, context); throw new UnsupportedOperationException(); } } diff --git a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml index d14235171..87fbfdb29 100644 --- a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -93,11 +93,7 @@ - - - - + >> Create index :: ok :: name = " + response.index()); - } else { - logger.info(">>> Create index :: not acknowledged"); - } - -// ClusterHealthResponse actionGet = restHighLevelClient.cluster() -// .health(Requests.clusterHealthRequest("unomi-index-1").waitForGreenStatus().waitForEvents(Priority.LANGUID) -// .waitForNoRelocatingShards(true), RequestOptions.DEFAULT); -// Assert.assertNotNull(actionGet); -// -// switch (actionGet.getStatus()) { -// case GREEN: -// logger.info(">>> Cluster State :: GREEN"); -// break; -// case YELLOW: -// logger.info(">>> Cluster State :: YELLOW"); -// break; -// case RED: -// logger.info(">>> Cluster State :: RED"); -// break; -// } -// Assert.assertNotEquals(actionGet.getStatus(), ClusterHealthStatus.RED); - - IndexRequest indexRequest = new IndexRequest(indexName); - indexRequest.id(UUID.randomUUID().toString()); - String type = "{\"type\":\"unomi-type\"}"; - String source = "{\"name\":\"unomi-name\"}"; - indexRequest.source(XContentType.JSON, type, source); - ActionRequestValidationException exception = indexRequest.validate(); - Assert.assertNull(exception); - - IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT); - Assert.assertNotNull(indexResponse); - if (indexResponse.status() == RestStatus.CREATED) { - logger.info(">>> Insert data created"); - } else { - logger.info(">>> Insert data ko :: " + indexResponse.status().name()); - } - Assert.assertEquals(indexResponse.status(), RestStatus.CREATED); - } - -} diff --git a/persistence-opensearch/conditions/pom.xml b/persistence-opensearch/conditions/pom.xml new file mode 100644 index 000000000..7512f8f04 --- /dev/null +++ b/persistence-opensearch/conditions/pom.xml @@ -0,0 +1,191 @@ + + + + + 4.0.0 + + + org.apache.unomi + unomi-persistence-opensearch + 2.6.0-SNAPSHOT + + + unomi-persistence-opensearch-conditions + Apache Unomi :: Persistence :: OpenSearch :: Conditions + Conditions OpenSearch persistence implementation for the Apache Unomi Context Server + bundle + + + + org.osgi + osgi.core + provided + + + org.osgi + osgi.cmpn + provided + + + + org.apache.unomi + unomi-api + ${project.version} + provided + + + org.apache.unomi + unomi-common + ${project.version} + provided + + + org.apache.unomi + unomi-persistence-spi + ${project.version} + provided + + + com.google.guava + guava + ${guava.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.apache.commons + commons-lang3 + + + commons-collections + commons-collections + + + commons-io + commons-io + + + + org.apache.unomi + unomi-metrics + ${project.version} + provided + + + + junit + junit + test + + + com.hazelcast + hazelcast-all + 3.12.8 + provided + + + + org.apache.unomi + unomi-scripting + ${project.version} + provided + + + + org.opensearch.client + opensearch-java + ${opensearch.version} + provided + + + + org.apache.unomi + unomi-persistence-opensearch-core + ${project.version} + provided + + + + joda-time + joda-time + 2.12.7 + + + + org.apache.unomi + unomi-plugins-base + ${project.version} + provided + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + android.os;resolution:=optional, + com.conversantmedia.util.concurrent;resolution:=optional, + com.google.appengine.api;resolution:=optional, + com.google.appengine.api.utils;resolution:=optional, + com.google.apphosting.api;resolution:=optional, + jakarta.enterprise.context.spi;resolution:=optional, + jakarta.enterprise.inject.spi;resolution:=optional, + jdk.net;resolution:=optional, + org.apache.avalon.framework.logger;resolution:=optional, + org.apache.log;resolution:=optional, + org.apache.log4j, + org.brotli.dec;resolution:=optional, + org.conscrypt;resolution:=optional, + org.glassfish.hk2.osgiresourcelocator;resolution:=optional, + org.ietf.jgss;resolution:=optional, + org.joda.convert;resolution:=optional, + org.reactivestreams;resolution:=optional, + software.amazon.awssdk.auth.credentials;resolution:=optional, + software.amazon.awssdk.core.async;resolution:=optional, + software.amazon.awssdk.http;resolution:=optional, + software.amazon.awssdk.http.async;resolution:=optional, + software.amazon.awssdk.http.auth.aws.signer;resolution:=optional, + software.amazon.awssdk.http.auth.spi.signer;resolution:=optional, + software.amazon.awssdk.identity.spi;resolution:=optional, + software.amazon.awssdk.regions;resolution:=optional, + software.amazon.awssdk.utils;resolution:=optional, + software.amazon.awssdk.utils.builder;resolution:=optional, + sun.misc;resolution:=optional, + sun.nio.ch;resolution:=optional, + * + + *;scope=compile|runtime + true + + + + + + + + diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java new file mode 100644 index 000000000..287391f87 --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.BoolQuery; +import org.opensearch.client.opensearch._types.query_dsl.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +/** + * OpenSearch query builder for boolean conditions. + */ +public class BooleanConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + private static final Logger LOGGER = LoggerFactory.getLogger(BooleanConditionOSQueryBuilder.class.getName()); + + @Override + public Query buildQuery(Condition condition, Map context, + ConditionOSQueryBuilderDispatcher dispatcher) { + boolean isAndOperator = "and".equalsIgnoreCase((String) condition.getParameter("operator")); + @SuppressWarnings("unchecked") + List conditions = (List) condition.getParameter("subConditions"); + + int conditionCount = conditions.size(); + + if (conditionCount == 1) { + return dispatcher.buildFilter(conditions.get(0), context); + } + + BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder(); + for (int i = 0; i < conditionCount; i++) { + if (isAndOperator) { + Query andFilter = dispatcher.buildFilter(conditions.get(i), context); + if (andFilter != null) { + if (andFilter.isRange()) { + boolQueryBuilder.filter(andFilter); + } else { + boolQueryBuilder.must(andFilter); + } + } else { + LOGGER.warn("Null filter for boolean AND sub condition. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Null filter for boolean AND sub condition {}", conditions.get(i)); + } + } + } else { + Query orFilter = dispatcher.buildFilter(conditions.get(i), context); + if (orFilter != null) { + boolQueryBuilder.should(orFilter); + } else { + LOGGER.warn("Null filter for boolean OR sub condition. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Null filter for boolean OR sub condition {}", conditions.get(i)); + } + } + } + } + + return Query.of(q->q.bool(boolQueryBuilder.build())); + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java new file mode 100644 index 000000000..ddc61643a --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.Map; + +public class GeoLocationByPointSessionConditionOSQueryBuilder implements ConditionOSQueryBuilder { + @Override + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + String type = (String) condition.getParameter("type"); + String name = condition.getParameter("name") == null ? "location" : (String) condition.getParameter("name"); + + if("circle".equals(type)) { + Double circleLatitude = ((Number) condition.getParameter("circleLatitude")).doubleValue(); + Double circleLongitude = ((Number) condition.getParameter("circleLongitude")).doubleValue(); + String distance = condition.getParameter("distance").toString(); + + if(circleLatitude != null && circleLongitude != null && distance != null) { + return Query.of(q -> q.geoDistance(g -> g.field(name).location(l -> l.latlon(latlong -> latlong.lat(circleLatitude).lon(circleLongitude))).distance(distance))); + } + } else if("rectangle".equals(type)) { + Double rectLatitudeNE = (Double) condition.getParameter("rectLatitudeNE"); + Double rectLongitudeNE = (Double) condition.getParameter("rectLongitudeNE"); + Double rectLatitudeSW = (Double) condition.getParameter("rectLatitudeSW"); + Double rectLongitudeSW = (Double) condition.getParameter("rectLongitudeSW"); + + if(rectLatitudeNE != null && rectLongitudeNE != null && rectLatitudeSW != null && rectLongitudeSW != null) { + return Query.of(q -> q.geoBoundingBox(g -> g + .field(name) + .boundingBox(b -> b + .coords(c -> c + .top(rectLatitudeNE) + .left(rectLongitudeNE) + .bottom(rectLatitudeSW) + .right(rectLongitudeSW) + ) + ) + ) + ); + } + } + + return null; + } + +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java new file mode 100644 index 000000000..5697e9a4f --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +public class IdsConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + private int maximumIdsQueryCount = 5000; + + public void setMaximumIdsQueryCount(int maximumIdsQueryCount) { + this.maximumIdsQueryCount = maximumIdsQueryCount; + } + + @Override + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + Collection ids = (Collection) condition.getParameter("ids"); + Boolean match = (Boolean) condition.getParameter("match"); + + if (ids.size() > maximumIdsQueryCount) { + // Avoid building too big ids query - throw exception instead + throw new UnsupportedOperationException("Too many profiles"); + } + + Query idsQuery = Query.of(q->q.ids(i->i.values(new ArrayList(ids)))); + if (match) { + return idsQuery; + } else { + return Query.of(q->q.bool(b->b.mustNot(idsQuery))); + } + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java new file mode 100644 index 000000000..7dfdaf35a --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.Map; + +public class MatchAllConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + @Override + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + return Query.of(q->q.matchAll(m->m)); + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java new file mode 100644 index 000000000..85b839d17 --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.ChildScoreMode; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.Map; + +public class NestedConditionOSQueryBuilder implements ConditionOSQueryBuilder { + @Override + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + String path = (String) condition.getParameter("path"); + Condition subCondition = (Condition) condition.getParameter("subCondition"); + + if (subCondition == null || path == null) { + throw new IllegalArgumentException("Impossible to build Nested query, subCondition and path properties should be provided"); + } + + Query nestedQuery = dispatcher.buildFilter(subCondition, context); + if (nestedQuery != null) { + return Query.of(q->q.nested(n->n.path(path).query(nestedQuery).scoreMode(ChildScoreMode.Avg))); + } else { + throw new IllegalArgumentException("Impossible to build Nested query due to subCondition filter null"); + } + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java new file mode 100644 index 000000000..cb1f52187 --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.Map; + +/** + * Builder for NOT condition. + */ +public class NotConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + Condition subCondition = (Condition) condition.getParameter("subCondition"); + return Query.of(q->q.bool(b->b.mustNot(dispatcher.buildFilter(subCondition, context)))); + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java new file mode 100644 index 000000000..2eaaffbd5 --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java @@ -0,0 +1,257 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.Event; +import org.apache.unomi.api.Profile; +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.api.conditions.ConditionType; +import org.apache.unomi.api.services.DefinitionsService; +import org.apache.unomi.api.services.SegmentService; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.spi.PersistenceService; +import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.scripting.ScriptExecutor; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.*; +import java.util.stream.Collectors; + +public class PastEventConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + private DefinitionsService definitionsService; + private PersistenceService persistenceService; + private SegmentService segmentService; + private ScriptExecutor scriptExecutor; + + private int maximumIdsQueryCount = 5000; + private int aggregateQueryBucketSize = 5000; + private boolean pastEventsDisablePartitions = false; + + public void setDefinitionsService(DefinitionsService definitionsService) { + this.definitionsService = definitionsService; + } + + public void setPersistenceService(PersistenceService persistenceService) { + this.persistenceService = persistenceService; + } + + public void setScriptExecutor(ScriptExecutor scriptExecutor) { + this.scriptExecutor = scriptExecutor; + } + + public void setMaximumIdsQueryCount(int maximumIdsQueryCount) { + this.maximumIdsQueryCount = maximumIdsQueryCount; + } + + public void setAggregateQueryBucketSize(int aggregateQueryBucketSize) { + this.aggregateQueryBucketSize = aggregateQueryBucketSize; + } + + public void setPastEventsDisablePartitions(boolean pastEventsDisablePartitions) { + this.pastEventsDisablePartitions = pastEventsDisablePartitions; + } + + public void setSegmentService(SegmentService segmentService) { + this.segmentService = segmentService; + } + + @Override + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + boolean eventsOccurred = getStrategyFromOperator((String) condition.getParameter("operator")); + int minimumEventCount = !eventsOccurred || condition.getParameter("minimumEventCount") == null ? 1 : (Integer) condition.getParameter("minimumEventCount"); + int maximumEventCount = !eventsOccurred || condition.getParameter("maximumEventCount") == null ? Integer.MAX_VALUE : (Integer) condition.getParameter("maximumEventCount"); + String generatedPropertyKey = (String) condition.getParameter("generatedPropertyKey"); + + if (generatedPropertyKey != null && generatedPropertyKey.equals(segmentService.getGeneratedPropertyKey((Condition) condition.getParameter("eventCondition"), condition))) { + // A property is already set on profiles matching the past event condition, use it to check the numbers of occurrences + return dispatcher.buildFilter(getProfileConditionForCounter(generatedPropertyKey, minimumEventCount, maximumEventCount, eventsOccurred), context); + } else { + // No property set - tries to build an idsQuery + // TODO see for deprecation, this should not happen anymore each past event condition should have a generatedPropertyKey + Condition eventCondition = getEventCondition(condition, context, null, definitionsService, scriptExecutor); + Set ids = getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, maximumEventCount); + return dispatcher.buildFilter(getProfileIdsCondition(ids, eventsOccurred), context); + } + } + + @Override + public long count(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + boolean eventsOccurred = getStrategyFromOperator((String) condition.getParameter("operator")); + int minimumEventCount = !eventsOccurred || condition.getParameter("minimumEventCount") == null ? 1 : (Integer) condition.getParameter("minimumEventCount"); + int maximumEventCount = !eventsOccurred || condition.getParameter("maximumEventCount") == null ? Integer.MAX_VALUE : (Integer) condition.getParameter("maximumEventCount"); + String generatedPropertyKey = (String) condition.getParameter("generatedPropertyKey"); + + if (generatedPropertyKey != null && generatedPropertyKey.equals(segmentService.getGeneratedPropertyKey((Condition) condition.getParameter("eventCondition"), condition))) { + // query profiles directly + return persistenceService.queryCount(getProfileConditionForCounter(generatedPropertyKey, minimumEventCount, maximumEventCount, eventsOccurred), Profile.ITEM_TYPE); + } else { + // No count filter - simply get the full number of distinct profiles + // TODO see for deprecation, this should not happen anymore each past event condition should have a generatedPropertyKey + Condition eventCondition = getEventCondition(condition, context, null, definitionsService, scriptExecutor); + if (eventsOccurred && minimumEventCount == 1 && maximumEventCount == Integer.MAX_VALUE) { + return persistenceService.getSingleValuesMetrics(eventCondition, new String[]{"card"}, "profileId.keyword", Event.ITEM_TYPE).get("_card").longValue(); + } + + Set profileIds = getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, maximumEventCount); + return eventsOccurred ? profileIds.size() : persistenceService.queryCount(getProfileIdsCondition(profileIds, false), Profile.ITEM_TYPE); + } + } + + protected static boolean getStrategyFromOperator(String operator) { + if (operator != null && !operator.equals("eventsOccurred") && !operator.equals("eventsNotOccurred")) { + throw new UnsupportedOperationException("Unsupported operator: " + operator + ", please use either 'eventsOccurred' or 'eventsNotOccurred'"); + } + return operator == null || operator.equals("eventsOccurred"); + } + + private Condition getProfileIdsCondition(Set ids, boolean shouldMatch) { + Condition idsCondition = new Condition(); + idsCondition.setConditionType(definitionsService.getConditionType("idsCondition")); + idsCondition.setParameter("ids", ids); + idsCondition.setParameter("match", shouldMatch); + return idsCondition; + } + + private Condition getProfileConditionForCounter(String generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount, boolean eventsOccurred) { + String generatedPropertyName = "systemProperties.pastEvents." + generatedPropertyKey; + ConditionType profilePropertyConditionType = definitionsService.getConditionType("profilePropertyCondition"); + if (eventsOccurred) { + Condition counterIsBetweenBoundaries = new Condition(); + counterIsBetweenBoundaries.setConditionType(profilePropertyConditionType); + counterIsBetweenBoundaries.setParameter("propertyName", generatedPropertyName); + counterIsBetweenBoundaries.setParameter("comparisonOperator", "between"); + counterIsBetweenBoundaries.setParameter("propertyValuesInteger", Arrays.asList(minimumEventCount, maximumEventCount)); + return counterIsBetweenBoundaries; + } else { + Condition counterMissing = new Condition(); + counterMissing.setConditionType(profilePropertyConditionType); + counterMissing.setParameter("propertyName", generatedPropertyName); + counterMissing.setParameter("comparisonOperator", "missing"); + + Condition counterZero = new Condition(); + counterZero.setConditionType(profilePropertyConditionType); + counterZero.setParameter("propertyName", generatedPropertyName); + counterZero.setParameter("comparisonOperator", "equals"); + counterZero.setParameter("propertyValueInteger", 0); + + Condition counterCondition = new Condition(); + counterCondition.setConditionType(definitionsService.getConditionType("booleanCondition")); + counterCondition.setParameter("operator", "or"); + counterCondition.setParameter("subConditions", Arrays.asList(counterMissing, counterZero)); + return counterCondition; + } + } + + private Set getProfileIdsMatchingEventCount(Condition eventCondition, int minimumEventCount, int maximumEventCount) { + boolean noBoundaries = minimumEventCount == 1 && maximumEventCount == Integer.MAX_VALUE; + if (pastEventsDisablePartitions) { + Map eventCountByProfile = persistenceService.aggregateWithOptimizedQuery(eventCondition, new TermsAggregate("profileId"), Event.ITEM_TYPE, maximumIdsQueryCount); + eventCountByProfile.remove("_filtered"); + return noBoundaries ? + eventCountByProfile.keySet() : + eventCountByProfile.entrySet() + .stream() + .filter(eventCountPerProfile -> (eventCountPerProfile.getValue() >= minimumEventCount && eventCountPerProfile.getValue() <= maximumEventCount)) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + } else { + Set result = new HashSet<>(); + // Get full cardinality to partition the terms aggregation + Map m = persistenceService.getSingleValuesMetrics(eventCondition, new String[]{"card"}, "profileId.keyword", Event.ITEM_TYPE); + long card = m.get("_card").longValue(); + + int numParts = (int) (card / aggregateQueryBucketSize) + 2; + for (int i = 0; i < numParts; i++) { + Map eventCountByProfile = persistenceService.aggregateWithOptimizedQuery(eventCondition, new TermsAggregate("profileId", i, numParts), Event.ITEM_TYPE); + if (eventCountByProfile != null) { + eventCountByProfile.remove("_filtered"); + if (noBoundaries) { + result.addAll(eventCountByProfile.keySet()); + } else { + for (Map.Entry entry : eventCountByProfile.entrySet()) { + if (entry.getValue() < minimumEventCount) { + // No more interesting buckets in this partition + break; + } else if (entry.getValue() <= maximumEventCount) { + result.add(entry.getKey()); + } + } + } + } + } + + return result; + } + } + + protected static Condition getEventCondition(Condition condition, Map context, String profileId, + DefinitionsService definitionsService, ScriptExecutor scriptExecutor) { + Condition eventCondition; + try { + eventCondition = (Condition) condition.getParameter("eventCondition"); + } catch (ClassCastException e) { + throw new IllegalArgumentException("Empty eventCondition"); + } + if (eventCondition == null) { + throw new IllegalArgumentException("No eventCondition"); + } + List l = new ArrayList(); + Condition andCondition = new Condition(); + andCondition.setConditionType(definitionsService.getConditionType("booleanCondition")); + andCondition.setParameter("operator", "and"); + andCondition.setParameter("subConditions", l); + + l.add(ConditionContextHelper.getContextualCondition(eventCondition, context, scriptExecutor)); + + if (profileId != null) { + Condition profileCondition = new Condition(); + profileCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + profileCondition.setParameter("propertyName", "profileId"); + profileCondition.setParameter("comparisonOperator", "equals"); + profileCondition.setParameter("propertyValue", profileId); + l.add(profileCondition); + } + + Integer numberOfDays = (Integer) condition.getParameter("numberOfDays"); + String fromDate = (String) condition.getParameter("fromDate"); + String toDate = (String) condition.getParameter("toDate"); + + if (numberOfDays != null) { + l.add(getTimeStampCondition("greaterThan", "propertyValueDateExpr", "now-" + numberOfDays + "d", definitionsService)); + } + if (fromDate != null) { + l.add(getTimeStampCondition("greaterThanOrEqualTo", "propertyValueDate", fromDate, definitionsService)); + } + if (toDate != null) { + l.add(getTimeStampCondition("lessThanOrEqualTo", "propertyValueDate", toDate, definitionsService)); + } + return andCondition; + } + + private static Condition getTimeStampCondition(String operator, String propertyValueParameter, Object propertyValue, DefinitionsService definitionsService) { + Condition endDateCondition = new Condition(); + endDateCondition.setConditionType(definitionsService.getConditionType("sessionPropertyCondition")); + endDateCondition.setParameter("propertyName", "timeStamp"); + endDateCondition.setParameter("comparisonOperator", operator); + endDateCondition.setParameter(propertyValueParameter, propertyValue); + return endDateCondition; + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java new file mode 100644 index 000000000..55b27bf8b --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java @@ -0,0 +1,250 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.commons.lang3.ObjectUtils; +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; +import org.opensearch.client.json.JsonData; +import org.opensearch.client.opensearch._types.GeoDistanceType; +import org.opensearch.client.opensearch._types.query_dsl.BoolQuery; +import org.opensearch.client.opensearch._types.query_dsl.Query; +import org.opensearch.client.opensearch._types.FieldValue; +import org.opensearch.client.util.ObjectBuilder; + +import java.util.*; + +import static org.apache.unomi.plugins.baseplugin.conditions.PropertyConditionEvaluator.getDate; + +public class PropertyConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + DateTimeFormatter dateTimeFormatter; + + public PropertyConditionOSQueryBuilder() { + dateTimeFormatter = ISODateTimeFormat.dateTime(); + } + + @Override + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + String comparisonOperator = (String) condition.getParameter("comparisonOperator"); + String name = (String) condition.getParameter("propertyName"); + + if (comparisonOperator == null || name == null) { + throw new IllegalArgumentException("Impossible to build ES filter, condition is not valid, comparisonOperator and propertyName properties should be provided"); + } + + String expectedValue = ConditionContextHelper.foldToASCII((String) condition.getParameter("propertyValue")); + Object expectedValueInteger = condition.getParameter("propertyValueInteger"); + Object expectedValueDouble = condition.getParameter("propertyValueDouble"); + Object expectedValueDate = convertDateToISO(condition.getParameter("propertyValueDate")); + Object expectedValueDateExpr = condition.getParameter("propertyValueDateExpr"); + + Collection expectedValues = ConditionContextHelper.foldToASCII((Collection) condition.getParameter("propertyValues")); + Collection expectedValuesInteger = (Collection) condition.getParameter("propertyValuesInteger"); + Collection expectedValuesDouble = (Collection) condition.getParameter("propertyValuesDouble"); + Collection expectedValuesDate = convertDatesToISO((Collection) condition.getParameter("propertyValuesDate")); + Collection expectedValuesDateExpr = (Collection) condition.getParameter("propertyValuesDateExpr"); + + Object value = ObjectUtils.firstNonNull(expectedValue, expectedValueInteger, expectedValueDouble, expectedValueDate, expectedValueDateExpr); + @SuppressWarnings("unchecked") + Collection values = ObjectUtils.firstNonNull(expectedValues, expectedValuesInteger, expectedValuesDouble, expectedValuesDate, expectedValuesDateExpr); + + switch (comparisonOperator) { + case "equals": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.term(t->t.field(name).value(v->getValue(value)))); + case "notEquals": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.bool(b->b.mustNot(m->m.term(t->t.field(name).value(v->getValue(value)))))); + case "greaterThan": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.range(r->r.field(name).gt(JsonData.of(value)))); + case "greaterThanOrEqualTo": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.range(r->r.field(name).gte(JsonData.of(value)))); + case "lessThan": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.range(r->r.field(name).lt(JsonData.of(value)))); + case "lessThanOrEqualTo": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.range(r->r.field(name).lte(JsonData.of(value)))); + case "between": + checkRequiredValuesSize(values, name, comparisonOperator, 2); + Iterator iterator = values.iterator(); + return Query.of(q->q.range(r->r.field(name).gte(JsonData.of(iterator.next())).lte(JsonData.of(iterator.next())))); + case "exists": + return Query.of(q->q.exists(e->e.field(name))); + case "missing": + return Query.of(q->q.bool(b->b.mustNot(m->m.exists(e->e.field(name))))); + case "contains": + checkRequiredValue(expectedValue, name, comparisonOperator, false); + return Query.of(q->q.regexp(r->r.field(name).value(".*" + expectedValue + ".*"))); + case "notContains": + checkRequiredValue(expectedValue, name, comparisonOperator, false); + return Query.of(q->q.bool(b->b.mustNot(m->m.regexp(r->r.field(name).value(".*" + expectedValue + ".*"))))); + case "startsWith": + checkRequiredValue(expectedValue, name, comparisonOperator, false); + return Query.of(q->q.prefix(p->p.field(name).value(expectedValue))); + case "endsWith": + checkRequiredValue(expectedValue, name, comparisonOperator, false); + return Query.of(q->q.regexp(r->r.field(name).value(".*" + expectedValue))); + case "matchesRegex": + checkRequiredValue(expectedValue, name, comparisonOperator, false); + return Query.of(q->q.regexp(r->r.field(name).value(expectedValue))); + case "in": + checkRequiredValue(values, name, comparisonOperator, true); + return Query.of(q->q.terms(t->t.field(name).terms(t2->t2.value(getValues(values))))); + case "notIn": + checkRequiredValue(values, name, comparisonOperator, true); + return Query.of(q->q.bool(b->b.mustNot(m->m.terms(t->t.field(name).terms(t2->t2.value(getValues(values))))))); + case "all": + checkRequiredValue(values, name, comparisonOperator, true); + BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder(); + for (Object curValue : values) { + boolQueryBuilder.must(Query.of(q->q.term(t->t.field(name).value(getValue(curValue).build())))); + } + return Query.of(q->q.bool(boolQueryBuilder.build())); + case "inContains": + checkRequiredValue(values, name, comparisonOperator, true); + BoolQuery.Builder boolQueryBuilderInContains = new BoolQuery.Builder(); + for (Object curValue : values) { + boolQueryBuilderInContains.must(Query.of(q->q.regexp(r->r.field(name).value(".*" + curValue + ".*")))); + } + return Query.of(q->q.bool(boolQueryBuilderInContains.build())); + case "hasSomeOf": + checkRequiredValue(values, name, comparisonOperator, true); + boolQueryBuilder = new BoolQuery.Builder(); + for (Object curValue : values) { + boolQueryBuilder.should(Query.of(q->q.term(t->t.field(name).value(getValue(curValue).build())))); + } + return Query.of(q->q.bool(boolQueryBuilder.build())); + case "hasNoneOf": + checkRequiredValue(values, name, comparisonOperator, true); + boolQueryBuilder = new BoolQuery.Builder(); + for (Object curValue : values) { + boolQueryBuilder.mustNot(Query.of(q->q.term(t->t.field(name).value(getValue(curValue).build())))); + } + return Query.of(q->q.bool(boolQueryBuilder.build())); + case "isDay": + checkRequiredValue(value, name, comparisonOperator, false); + return getIsSameDayRange(getDate(value), name); + case "isNotDay": + checkRequiredValue(value, name, comparisonOperator, false); + return Query.of(q->q.bool(b->b.mustNot(getIsSameDayRange(getDate(value), name)))); + case "distance": + final String unitString = (String) condition.getParameter("unit"); + final Object centerObj = condition.getParameter("center"); + final Double distance = (Double) condition.getParameter("distance"); + + if (centerObj != null && distance != null) { + String centerString; + if (centerObj instanceof org.apache.unomi.api.GeoPoint) { + centerString = ((org.apache.unomi.api.GeoPoint) centerObj).asString(); + } else if (centerObj instanceof String) { + centerString = (String) centerObj; + } else { + centerString = centerObj.toString(); + } + GeoDistanceType unit = unitString != null ? GeoDistanceType.valueOf(unitString) : GeoDistanceType.Plane; + + return Query.of(q->q.geoDistance(g->g.field(name).distance(distance + "").distanceType(unit).location(l->l.text(centerString)))); + } + } + return null; + } + + private void checkRequiredValuesSize(Collection values, String name, String operator, int expectedSize) { + if (values == null || values.size() != expectedSize) { + throw new IllegalArgumentException("Impossible to build ES filter, missing " + expectedSize + " values for a condition using comparisonOperator: " + operator + ", and propertyName: " + name); + } + } + + private void checkRequiredValue(Object value, String name, String operator, boolean multiple) { + if (value == null) { + throw new IllegalArgumentException("Impossible to build ES filter, missing value" + (multiple ? "s" : "") + " for condition using comparisonOperator: " + operator + ", and propertyName: " + name); + } + } + + private Query getIsSameDayRange(Object value, String name) { + DateTime date = new DateTime(value); + DateTime dayStart = date.withTimeAtStartOfDay(); + DateTime dayAfterStart = date.plusDays(1).withTimeAtStartOfDay(); + return Query.of(q->q.range(r->r + .field(name) + .gte(JsonData.of(convertDateToISO(dayStart.toDate()))) + .lte(JsonData.of(convertDateToISO(dayAfterStart.toDate()))))); + } + + private Object convertDateToISO(Object dateValue) { + if (dateValue == null) { + return dateValue; + } + if (dateValue instanceof Date) { + return dateTimeFormatter.print(new DateTime(dateValue)); + } else { + return dateValue; + } + } + + private Collection convertDatesToISO(Collection datesValues) { + List results = new ArrayList<>(); + if (datesValues == null) { + return null; + } + for (Object dateValue : datesValues) { + if (dateValue != null) { + results.add(convertDateToISO(dateValue)); + } + } + return results; + } + + private ObjectBuilder getValue(Object fieldValue) { + FieldValue.Builder fieldValueBuilder = new FieldValue.Builder(); + if (fieldValue instanceof String) { + return fieldValueBuilder.stringValue((String) fieldValue); + } else if (fieldValue instanceof Integer) { + return fieldValueBuilder.longValue((Integer) fieldValue); + } else if (fieldValue instanceof Long) { + return fieldValueBuilder.longValue((Long) fieldValue); + } else if (fieldValue instanceof Double) { + return fieldValueBuilder.doubleValue((Double) fieldValue); + } else if (fieldValue instanceof Float) { + return fieldValueBuilder.doubleValue((Float) fieldValue); + } else if (fieldValue instanceof Boolean) { + return fieldValueBuilder.booleanValue((Boolean) fieldValue); + } else if (fieldValue instanceof Date) { + return fieldValueBuilder.stringValue(convertDateToISO((Date) fieldValue).toString()); + } else { + throw new IllegalArgumentException("Impossible to build ES filter, unsupported value type: " + fieldValue.getClass().getName()); + } + } + + private List getValues(Collection fieldValues) { + List values = new ArrayList<>(); + for (Object fieldValue : fieldValues) { + values.add(getValue(fieldValue).build()); + } + return values; + } +} diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java new file mode 100644 index 000000000..d2745f29f --- /dev/null +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.opensearch.client.opensearch._types.query_dsl.BoolQuery; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class SourceEventPropertyConditionOSQueryBuilder implements ConditionOSQueryBuilder { + + public SourceEventPropertyConditionOSQueryBuilder() { + } + + private void appendFilderIfPropExist(List queryBuilders, Condition condition, String prop){ + final Object parameter = condition.getParameter(prop); + if (parameter != null && !"".equals(parameter)) { + queryBuilders.add(Query.of(q->q.term(t->t.field("source." + prop).value(v->v.stringValue((String) parameter))))); + } + } + + public Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + List queryBuilders = new ArrayList(); + for (String prop : new String[]{"id", "path", "scope", "type"}){ + appendFilderIfPropExist(queryBuilders, condition, prop); + } + + if (queryBuilders.size() >= 1) { + if (queryBuilders.size() == 1) { + return queryBuilders.get(0); + } else { + BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder(); + for (Query queryBuilder : queryBuilders) { + boolQueryBuilder.must(queryBuilder); + } + return Query.of(q->q.bool(boolQueryBuilder.build())); + } + } else { + return null; + } + } +} diff --git a/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..48e4c400b --- /dev/null +++ b/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/persistence-opensearch/core/pom.xml b/persistence-opensearch/core/pom.xml new file mode 100644 index 000000000..8e5eb2fa8 --- /dev/null +++ b/persistence-opensearch/core/pom.xml @@ -0,0 +1,194 @@ + + + + + 4.0.0 + + + org.apache.unomi + unomi-persistence-opensearch + 2.6.0-SNAPSHOT + + + unomi-persistence-opensearch-core + Apache Unomi :: Persistence :: OpenSearch :: Core + Core OpenSearch persistence implementation for the Apache Unomi Context Server + bundle + + + + org.osgi + osgi.core + provided + + + org.osgi + osgi.cmpn + provided + + + + org.apache.unomi + unomi-api + ${project.version} + provided + + + org.apache.unomi + unomi-common + ${project.version} + provided + + + org.apache.unomi + unomi-persistence-spi + ${project.version} + provided + + + com.google.guava + guava + ${guava.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.apache.commons + commons-lang3 + + + commons-collections + commons-collections + + + commons-io + commons-io + + + + org.apache.unomi + unomi-metrics + ${project.version} + provided + + + + junit + junit + test + + + com.hazelcast + hazelcast-all + 3.12.8 + provided + + + + org.apache.unomi + unomi-scripting + ${project.version} + provided + + + + org.opensearch.client + opensearch-rest-client + ${opensearch.version} + + + + org.opensearch.client + opensearch-java + ${opensearch.version} + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + android.os;resolution:=optional, + com.google.appengine.*;resolution:=optional, + com.google.apphosting.*;resolution:=optional, + io.micrometer.*;resolution:=optional, + jakarta.enterprise.*;resolution:=optional, + jdk.net;resolution:=optional, + org.apache.avalon.framework.logger;resolution:=optional, + org.apache.log;resolution:=optional, + org.brotli.dec;resolution:=optional, + org.conscrypt;resolution:=optional, + org.glassfish.hk2.osgiresourcelocator;resolution:=optional, + org.ietf.jgss;resolution:=optional, + org.reactivestreams;resolution:=optional, + reactor.blockhound.*;resolution:=optional, + software.amazon.awssdk.*;resolution:=optional, + sun.misc;resolution:=optional, + sun.nio.ch;resolution:=optional, + * + + + org.opensearch.*;version="${opensearch.version}", + org.opensearch.index.query.*;version="${opensearch.version}", + org.apache.lucene.search.join.*;version="${lucene.version}", + org.apache.unomi.persistence.opensearch.conditions;version="${project.version}" + + *;scope=compile|runtime + true + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + + src/main/resources/org.apache.unomi.persistence.opensearch.cfg + + cfg + opensearchcfg + + + + + + + + + + + diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSCustomObjectMapper.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSCustomObjectMapper.java new file mode 100644 index 000000000..9d9ab0ac5 --- /dev/null +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSCustomObjectMapper.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.opensearch; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.unomi.api.Event; +import org.apache.unomi.api.Item; +import org.apache.unomi.persistence.spi.CustomObjectMapper; + +/** + * This CustomObjectMapper is used to avoid the version parameter to be registered in ES + * @author dgaillard + */ +public class OSCustomObjectMapper extends CustomObjectMapper { + + private static final long serialVersionUID = -5017620674440085575L; + + public OSCustomObjectMapper() { + super(); + this.addMixIn(Item.class, OSItemMixIn.class); + this.addMixIn(Event.class, OSEventMixIn.class); + } + + public static ObjectMapper getObjectMapper() { + return OSCustomObjectMapper.Holder.INSTANCE; + } + + private static class Holder { + static final OSCustomObjectMapper INSTANCE = new OSCustomObjectMapper(); + } +} diff --git a/tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSEventMixIn.java similarity index 70% rename from tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless rename to persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSEventMixIn.java index 837103fe1..28dd28cf4 100644 --- a/tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSEventMixIn.java @@ -14,13 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package org.apache.unomi.persistence.opensearch; -/* Handle login events */ +import com.fasterxml.jackson.annotation.JsonIgnore; -ctx._source.put('scope', 'systemsite'); -if (ctx._source.source != null) { - ctx._source.source.put('scope', 'systemsite'); -} -if (ctx._source.target != null) { - ctx._source.target.put('scope', 'systemsite'); +/** + * This mixin is used in OSCustomObjectMapper to prevent the persistent parameter from being registered in ES + */ +public abstract class OSEventMixIn { + + public OSEventMixIn() { } + + @JsonIgnore abstract boolean isPersistent(); } diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSItemMixIn.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSItemMixIn.java new file mode 100644 index 000000000..dc00e5d01 --- /dev/null +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OSItemMixIn.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.opensearch; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +/** + * This mixin is used in OSCustomObjectMapper to avoid the version parameter to be registered in ES + * @author dgaillard + */ +public abstract class OSItemMixIn { + + public OSItemMixIn() { } + + @JsonIgnore abstract Long getVersion(); +} diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java new file mode 100644 index 000000000..71269433c --- /dev/null +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java @@ -0,0 +1,2641 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.persistence.opensearch; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.json.stream.JsonParser; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.util.EntityUtils; +import org.apache.unomi.api.*; +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.api.query.DateRange; +import org.apache.unomi.api.query.IpRange; +import org.apache.unomi.api.query.NumericRange; +import org.apache.unomi.metrics.MetricAdapter; +import org.apache.unomi.metrics.MetricsService; +import org.apache.unomi.persistence.opensearch.conditions.*; +import org.apache.unomi.persistence.spi.CustomObjectMapper; +import org.apache.unomi.persistence.spi.PersistenceService; +import org.apache.unomi.persistence.spi.aggregate.*; +import org.apache.unomi.persistence.spi.aggregate.DateRangeAggregate; +import org.apache.unomi.persistence.spi.aggregate.IpRangeAggregate; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; +import org.opensearch.client.*; +import org.opensearch.client.json.JsonData; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.json.jackson.JacksonJsonpMapper; +import org.opensearch.client.opensearch.OpenSearchClient; +import org.opensearch.client.opensearch._types.*; +import org.opensearch.client.opensearch._types.aggregations.*; +import org.opensearch.client.opensearch._types.mapping.TypeMapping; +import org.opensearch.client.opensearch._types.query_dsl.Query; +import org.opensearch.client.opensearch.cluster.HealthRequest; +import org.opensearch.client.opensearch.core.*; +import org.opensearch.client.opensearch.core.bulk.BulkOperation; +import org.opensearch.client.opensearch.core.bulk.UpdateOperation; +import org.opensearch.client.opensearch.core.search.Hit; +import org.opensearch.client.opensearch.core.search.HitsMetadata; +import org.opensearch.client.opensearch.core.search.TotalHits; +import org.opensearch.client.opensearch.core.search.TotalHitsRelation; +import org.opensearch.client.opensearch.indices.*; +import org.opensearch.client.opensearch.indices.get_alias.IndexAliases; +import org.opensearch.client.opensearch.tasks.GetTasksResponse; +import org.opensearch.client.transport.OpenSearchTransport; +import org.opensearch.client.transport.rest_client.RestClientTransport; +import org.osgi.framework.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.io.*; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.util.*; +import java.util.stream.Collectors; + +@SuppressWarnings("rawtypes") +public class OpenSearchPersistenceServiceImpl implements PersistenceService, SynchronousBundleListener { + + public static final String SEQ_NO = "seq_no"; + public static final String PRIMARY_TERM = "primary_term"; + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenSearchPersistenceServiceImpl.class.getName()); + private static final String ROLLOVER_LIFECYCLE_NAME = "unomi-rollover-policy"; + + private boolean throwExceptions = false; + + private OpenSearchClient client; + private RestClient restClient; + + private final List openSearchAddressList = new ArrayList<>(); + private String clusterName; + private String indexPrefix; + private String monthlyIndexNumberOfShards; + private String monthlyIndexNumberOfReplicas; + private String monthlyIndexMappingTotalFieldsLimit; + private String monthlyIndexMaxDocValueFieldsSearch; + private String numberOfShards; + private String numberOfReplicas; + private String indexMappingTotalFieldsLimit; + private String indexMaxDocValueFieldsSearch; + private String[] fatalIllegalStateErrors; + private BundleContext bundleContext; + private final Map mappings = new HashMap<>(); + private ConditionEvaluatorDispatcher conditionEvaluatorDispatcher; + private ConditionOSQueryBuilderDispatcher conditionOSQueryBuilderDispatcher; + private List itemsMonthlyIndexed; + private Map routingByType; + + private Integer defaultQueryLimit = 10; + private Integer removeByQueryTimeoutInMinutes = 10; + private Integer taskWaitingTimeout = 3600000; + private Integer taskWaitingPollingInterval = 1000; + + // Rollover configuration + private String sessionLatestIndex; + private List rolloverIndices; + private String rolloverMaxSize; + private String rolloverMaxAge; + private String rolloverMaxDocs; + private String rolloverIndexNumberOfShards; + private String rolloverIndexNumberOfReplicas; + private String rolloverIndexMappingTotalFieldsLimit; + private String rolloverIndexMaxDocValueFieldsSearch; + + private String minimalOpenSearchVersion = "2.1.0"; + private String maximalOpenSearchVersion = "3.0.0"; + + // authentication props + private String username; + private String password; + private boolean sslEnable = false; + private boolean sslTrustAllCertificates = false; + + private int aggregateQueryBucketSize = 5000; + + private MetricsService metricsService; + private boolean useBatchingForSave = false; + private boolean useBatchingForUpdate = true; + private String logLevelRestClient = "ERROR"; + private boolean alwaysOverwrite = true; + private boolean aggQueryThrowOnMissingDocs = false; + private Integer aggQueryMaxResponseSizeHttp = null; + private Integer clientSocketTimeout = null; + private Map itemTypeToRefreshPolicy = new HashMap<>(); + + private final Map>> knownMappings = new HashMap<>(); + + private static final Map itemTypeIndexNameMap = new HashMap<>(); + private static final Collection systemItems = Arrays.asList("actionType", "campaign", "campaignevent", "goal", + "userList", "propertyType", "scope", "conditionType", "rule", "scoring", "segment", "groovyAction", "topic", + "patch", "jsonSchema", "importConfig", "exportConfig", "rulestats"); + static { + for (String systemItem : systemItems) { + itemTypeIndexNameMap.put(systemItem, "systemItems"); + } + + itemTypeIndexNameMap.put("profile", "profile"); + itemTypeIndexNameMap.put("persona", "profile"); + } + + private final JsonpMapper jsonpMapper = new JacksonJsonpMapper(); + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public void setOpenSearchAddresses(String openSearchAddresses) { + String[] openSearchAddressesArray = openSearchAddresses.split(","); + openSearchAddressList.clear(); + for (String openSearchAddress : openSearchAddressesArray) { + openSearchAddressList.add(openSearchAddress.trim()); + } + } + + public void setItemTypeToRefreshPolicy(String itemTypeToRefreshPolicy) throws IOException { + if (!itemTypeToRefreshPolicy.isEmpty()) { + this.itemTypeToRefreshPolicy = new ObjectMapper().readValue(itemTypeToRefreshPolicy, + new TypeReference>() { + }); + } + } + + public void setFatalIllegalStateErrors(String fatalIllegalStateErrors) { + this.fatalIllegalStateErrors = Arrays.stream(fatalIllegalStateErrors.split(",")) + .map(String::trim).filter(i -> !i.isEmpty()).toArray(String[]::new); + } + + public void setAggQueryMaxResponseSizeHttp(String aggQueryMaxResponseSizeHttp) { + if (StringUtils.isNumeric(aggQueryMaxResponseSizeHttp)) { + this.aggQueryMaxResponseSizeHttp = Integer.parseInt(aggQueryMaxResponseSizeHttp); + } + } + + public void setIndexPrefix(String indexPrefix) { + this.indexPrefix = indexPrefix; + } + + @Deprecated + public void setMonthlyIndexNumberOfShards(String monthlyIndexNumberOfShards) { + this.monthlyIndexNumberOfShards = monthlyIndexNumberOfShards; + } + + @Deprecated + public void setMonthlyIndexNumberOfReplicas(String monthlyIndexNumberOfReplicas) { + this.monthlyIndexNumberOfReplicas = monthlyIndexNumberOfReplicas; + } + + @Deprecated + public void setMonthlyIndexMappingTotalFieldsLimit(String monthlyIndexMappingTotalFieldsLimit) { + this.monthlyIndexMappingTotalFieldsLimit = monthlyIndexMappingTotalFieldsLimit; + } + + @Deprecated + public void setMonthlyIndexMaxDocValueFieldsSearch(String monthlyIndexMaxDocValueFieldsSearch) { + this.monthlyIndexMaxDocValueFieldsSearch = monthlyIndexMaxDocValueFieldsSearch; + } + + @Deprecated + public void setItemsMonthlyIndexedOverride(String itemsMonthlyIndexedOverride) { + this.itemsMonthlyIndexed = StringUtils.isNotEmpty(itemsMonthlyIndexedOverride) ? Arrays.asList(itemsMonthlyIndexedOverride.split(",").clone()) : Collections.emptyList(); + } + + public void setNumberOfShards(String numberOfShards) { + this.numberOfShards = numberOfShards; + } + + public void setNumberOfReplicas(String numberOfReplicas) { + this.numberOfReplicas = numberOfReplicas; + } + + public void setIndexMappingTotalFieldsLimit(String indexMappingTotalFieldsLimit) { + this.indexMappingTotalFieldsLimit = indexMappingTotalFieldsLimit; + } + + public void setIndexMaxDocValueFieldsSearch(String indexMaxDocValueFieldsSearch) { + this.indexMaxDocValueFieldsSearch = indexMaxDocValueFieldsSearch; + } + + public void setDefaultQueryLimit(Integer defaultQueryLimit) { + this.defaultQueryLimit = defaultQueryLimit; + } + + public void setRoutingByType(Map routingByType) { + this.routingByType = routingByType; + } + + public void setConditionEvaluatorDispatcher(ConditionEvaluatorDispatcher conditionEvaluatorDispatcher) { + this.conditionEvaluatorDispatcher = conditionEvaluatorDispatcher; + } + + public void setConditionOSQueryBuilderDispatcher(ConditionOSQueryBuilderDispatcher conditionOSQueryBuilderDispatcher) { + this.conditionOSQueryBuilderDispatcher = conditionOSQueryBuilderDispatcher; + } + + public void setRolloverIndices(String rolloverIndices) { + this.rolloverIndices = StringUtils.isNotEmpty(rolloverIndices) ? Arrays.asList(rolloverIndices.split(",").clone()) : null; + } + + public void setRolloverMaxSize(String rolloverMaxSize) { + this.rolloverMaxSize = rolloverMaxSize; + } + + public void setRolloverMaxAge(String rolloverMaxAge) { + this.rolloverMaxAge = rolloverMaxAge; + } + + public void setRolloverMaxDocs(String rolloverMaxDocs) { + this.rolloverMaxDocs = rolloverMaxDocs; + } + + public void setRolloverIndexNumberOfShards(String rolloverIndexNumberOfShards) { + this.rolloverIndexNumberOfShards = rolloverIndexNumberOfShards; + } + + public void setRolloverIndexNumberOfReplicas(String rolloverIndexNumberOfReplicas) { + this.rolloverIndexNumberOfReplicas = rolloverIndexNumberOfReplicas; + } + + public void setRolloverIndexMappingTotalFieldsLimit(String rolloverIndexMappingTotalFieldsLimit) { + this.rolloverIndexMappingTotalFieldsLimit = rolloverIndexMappingTotalFieldsLimit; + } + + public void setRolloverIndexMaxDocValueFieldsSearch(String rolloverIndexMaxDocValueFieldsSearch) { + this.rolloverIndexMaxDocValueFieldsSearch = rolloverIndexMaxDocValueFieldsSearch; + } + + public void setMinimalOpenSearchVersion(String minimalOpenSearchVersion) { + this.minimalOpenSearchVersion = minimalOpenSearchVersion; + } + + public void setMaximalOpenSearchVersion(String maximalOpenSearchVersion) { + this.maximalOpenSearchVersion = maximalOpenSearchVersion; + } + + public void setAggregateQueryBucketSize(int aggregateQueryBucketSize) { + this.aggregateQueryBucketSize = aggregateQueryBucketSize; + } + + public void setClientSocketTimeout(String clientSocketTimeout) { + if (StringUtils.isNumeric(clientSocketTimeout)) { + this.clientSocketTimeout = Integer.parseInt(clientSocketTimeout); + } + } + + public void setMetricsService(MetricsService metricsService) { + this.metricsService = metricsService; + } + + public void setUseBatchingForSave(boolean useBatchingForSave) { + this.useBatchingForSave = useBatchingForSave; + } + + public void setUseBatchingForUpdate(boolean useBatchingForUpdate) { + this.useBatchingForUpdate = useBatchingForUpdate; + } + + public void setUsername(String username) { + this.username = username; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setSslEnable(boolean sslEnable) { + this.sslEnable = sslEnable; + } + + public void setSslTrustAllCertificates(boolean sslTrustAllCertificates) { + this.sslTrustAllCertificates = sslTrustAllCertificates; + } + + + public void setAggQueryThrowOnMissingDocs(boolean aggQueryThrowOnMissingDocs) { + this.aggQueryThrowOnMissingDocs = aggQueryThrowOnMissingDocs; + } + + public void setThrowExceptions(boolean throwExceptions) { + this.throwExceptions = throwExceptions; + } + + public void setAlwaysOverwrite(boolean alwaysOverwrite) { + this.alwaysOverwrite = alwaysOverwrite; + } + + public void setLogLevelRestClient(String logLevelRestClient) { + this.logLevelRestClient = logLevelRestClient; + } + + public void setTaskWaitingTimeout(String taskWaitingTimeout) { + if (StringUtils.isNumeric(taskWaitingTimeout)) { + this.taskWaitingTimeout = Integer.parseInt(taskWaitingTimeout); + } + } + + public void setTaskWaitingPollingInterval(String taskWaitingPollingInterval) { + if (StringUtils.isNumeric(taskWaitingPollingInterval)) { + this.taskWaitingPollingInterval = Integer.parseInt(taskWaitingPollingInterval); + } + } + + public void start() throws Exception { + + // on startup + new InClassLoaderExecute<>(null, null, this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + public Object execute(Object... args) throws Exception { + + buildClient(); + + InfoResponse response = client.info(); + OpenSearchVersionInfo version = response.version(); + Version clusterVersion = Version.parseVersion(version.number()); + Version minimalVersion = Version.parseVersion(minimalOpenSearchVersion); + Version maximalVersion = Version.parseVersion(maximalOpenSearchVersion); + if (clusterVersion.compareTo(minimalVersion) < 0 || + clusterVersion.equals(maximalVersion) || + clusterVersion.compareTo(maximalVersion) > 0) { + throw new Exception("OpenSearch version is not within [" + minimalVersion + "," + maximalVersion + "), aborting startup !"); + } + + registerRolloverLifecyclePolicy(); + + loadPredefinedMappings(bundleContext, false); + loadPainlessScripts(bundleContext); + + // load predefined mappings and condition dispatchers of any bundles that were started before this one. + for (Bundle existingBundle : bundleContext.getBundles()) { + if (existingBundle.getBundleContext() != null) { + loadPredefinedMappings(existingBundle.getBundleContext(), false); + loadPainlessScripts(existingBundle.getBundleContext()); + } + } + + // Wait for green + LOGGER.info("Waiting for GREEN cluster status..."); + client.cluster().health(new HealthRequest.Builder().waitForStatus(HealthStatus.Green).build()); + LOGGER.info("Cluster status is GREEN"); + + // We keep in memory the latest available session index to be able to load session using direct GET access on ES + if (isItemTypeRollingOver(Session.ITEM_TYPE)) { + LOGGER.info("Sessions are using rollover indices, loading latest session index available ..."); + GetAliasResponse sessionAliasResponse = client.indices().getAlias(new GetAliasRequest.Builder().index(getIndex(Session.ITEM_TYPE)).build()); + Map aliases = sessionAliasResponse.result(); + if (!aliases.isEmpty()) { + sessionLatestIndex = new TreeSet<>(aliases.keySet()).last(); + LOGGER.info("Latest available session index found is: {}", sessionLatestIndex); + } else { + throw new IllegalStateException("No index found for sessions"); + } + } + + return true; + } + }.executeInClassLoader(); + + bundleContext.addBundleListener(this); + + LOGGER.info(this.getClass().getName() + " service started successfully."); + } + + private void buildClient() throws NoSuchFieldException, IllegalAccessException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException { + + List nodeList = new ArrayList<>(); + for (String openSearchAddress : openSearchAddressList) { + String[] openSearchAddressParts = openSearchAddress.split(":"); + String openSearchHostName = openSearchAddressParts[0]; + int openSearchPort = Integer.parseInt(openSearchAddressParts[1]); + + // configure authentication + nodeList.add(new Node(new HttpHost(openSearchHostName, openSearchPort, sslEnable ? "https" : "http"))); + } + + RestClientBuilder clientBuilder = RestClient.builder(nodeList.toArray(new Node[nodeList.size()])); + + if (clientSocketTimeout != null) { + clientBuilder.setRequestConfigCallback(requestConfigBuilder -> { + requestConfigBuilder.setSocketTimeout(clientSocketTimeout); + return requestConfigBuilder; + }); + } + + clientBuilder.setHttpClientConfigCallback(httpClientBuilder -> { + if (sslTrustAllCertificates) { + try { + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, new TrustManager[]{new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted(X509Certificate[] certs, + String authType) { + } + + public void checkServerTrusted(X509Certificate[] certs, + String authType) { + } + }}, new SecureRandom()); + + httpClientBuilder.setSSLContext(sslContext).setSSLHostnameVerifier(new NoopHostnameVerifier()); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + LOGGER.error("Error creating SSL Context for trust all certificates", e); + } + } + + if (StringUtils.isNotBlank(username)) { + final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); + + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + } + + return httpClientBuilder; + }); + + restClient = clientBuilder.build(); + OpenSearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper(CustomObjectMapper.getObjectMapper())); + client = new OpenSearchClient(transport); + + LOGGER.info("Connecting to OpenSearch persistence backend using cluster name " + clusterName + " and index prefix " + indexPrefix + "..."); + } + + + public void stop() { + + new InClassLoaderExecute<>(null, null, this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Object execute(Object... args) throws IOException { + LOGGER.info("Closing OpenSearch persistence backend..."); + if (client != null) { + client.shutdown(); + } + return null; + } + }.catchingExecuteInClassLoader(true); + + bundleContext.removeBundleListener(this); + } + + public void bindConditionEvaluator(ServiceReference conditionEvaluatorServiceReference) { + ConditionEvaluator conditionEvaluator = bundleContext.getService(conditionEvaluatorServiceReference); + conditionEvaluatorDispatcher.addEvaluator(conditionEvaluatorServiceReference.getProperty("conditionEvaluatorId").toString(), conditionEvaluator); + } + + public void unbindConditionEvaluator(ServiceReference conditionEvaluatorServiceReference) { + if (conditionEvaluatorServiceReference == null) { + return; + } + conditionEvaluatorDispatcher.removeEvaluator(conditionEvaluatorServiceReference.getProperty("conditionEvaluatorId").toString()); + } + + public void bindConditionOSQueryBuilder(ServiceReference conditionESQueryBuilderServiceReference) { + ConditionOSQueryBuilder conditionOSQueryBuilder = bundleContext.getService(conditionESQueryBuilderServiceReference); + conditionOSQueryBuilderDispatcher.addQueryBuilder(conditionESQueryBuilderServiceReference.getProperty("queryBuilderId").toString(), conditionOSQueryBuilder); + } + + public void unbindConditionOSQueryBuilder(ServiceReference conditionESQueryBuilderServiceReference) { + if (conditionESQueryBuilderServiceReference == null) { + return; + } + conditionOSQueryBuilderDispatcher.removeQueryBuilder(conditionESQueryBuilderServiceReference.getProperty("queryBuilderId").toString()); + } + + @Override + public void bundleChanged(BundleEvent event) { + if (event.getType() == BundleEvent.STARTING) { + loadPredefinedMappings(event.getBundle().getBundleContext(), true); + loadPainlessScripts(event.getBundle().getBundleContext()); + } + } + + private void loadPredefinedMappings(BundleContext bundleContext, boolean forceUpdateMapping) { + Enumeration predefinedMappings = bundleContext.getBundle().findEntries("META-INF/cxs/mappings", "*.json", true); + if (predefinedMappings == null) { + return; + } + while (predefinedMappings.hasMoreElements()) { + URL predefinedMappingURL = predefinedMappings.nextElement(); + LOGGER.info("Found mapping at " + predefinedMappingURL + ", loading... "); + try { + final String path = predefinedMappingURL.getPath(); + String name = path.substring(path.lastIndexOf('/') + 1, path.lastIndexOf('.')); + String mappingSource = loadMappingFile(predefinedMappingURL); + + mappings.put(name, mappingSource); + + if (!createIndex(name)) { + LOGGER.info("Found index for type {}", name); + if (forceUpdateMapping) { + LOGGER.info("Updating mapping for {}", name); + createMapping(name, mappingSource); + } + } + } catch (Exception e) { + LOGGER.error("Error while loading mapping definition " + predefinedMappingURL, e); + } + } + } + + private TypeMapping getTypeMapping(String mappingSource) { + JsonpMapper mapper = client._transport().jsonpMapper(); + JsonParser parser = mapper + .jsonProvider() + .createParser(new StringReader(mappingSource)); + return TypeMapping._DESERIALIZER.deserialize(parser, mapper); + } + + private void loadPainlessScripts(BundleContext bundleContext) { + Enumeration scriptsURL = bundleContext.getBundle().findEntries("META-INF/cxs/painless", "*.painless", true); + if (scriptsURL == null) { + return; + } + + Map scriptsById = new HashMap<>(); + while (scriptsURL.hasMoreElements()) { + URL scriptURL = scriptsURL.nextElement(); + LOGGER.info("Found painless script at " + scriptURL + ", loading... "); + try (InputStream in = scriptURL.openStream()) { + String script = IOUtils.toString(in, StandardCharsets.UTF_8); + String scriptId = FilenameUtils.getBaseName(scriptURL.getPath()); + scriptsById.put(scriptId, script); + } catch (Exception e) { + LOGGER.error("Error while loading painless script " + scriptURL, e); + } + + } + + storeScripts(scriptsById); + } + + private String loadMappingFile(URL predefinedMappingURL) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader(predefinedMappingURL.openStream())); + + StringBuilder content = new StringBuilder(); + String l; + while ((l = reader.readLine()) != null) { + content.append(l); + } + return content.toString(); + } + + @Override + public List getAllItems(final Class clazz) { + return getAllItems(clazz, 0, -1, null).getList(); + } + + @Override + public long getAllItemsCount(String itemType) { + return queryCount(Query.of(q -> q.matchAll(t -> t)), itemType); + } + + @Override + public PartialList getAllItems(final Class clazz, int offset, int size, String sortBy) { + return getAllItems(clazz, offset, size, sortBy, null); + } + + @Override + public PartialList getAllItems(final Class clazz, int offset, int size, String sortBy, String scrollTimeValidity) { + long startTime = System.currentTimeMillis(); + try { + return query(Query.of(q -> q.matchAll(t -> t)), sortBy, clazz, offset, size, null, scrollTimeValidity); + } finally { + if (metricsService != null && metricsService.isActivated()) { + metricsService.updateTimer(this.getClass().getName() + ".getAllItems", startTime); + } + } + } + + @Override + public T load(final String itemId, final Class clazz) { + return load(itemId, clazz, null); + } + + @Override + @Deprecated + public T load(final String itemId, final Date dateHint, final Class clazz) { + return load(itemId, clazz, null); + } + + @Override + @Deprecated + public CustomItem loadCustomItem(final String itemId, final Date dateHint, String customItemType) { + return load(itemId, CustomItem.class, customItemType); + } + + @Override + public CustomItem loadCustomItem(final String itemId, String customItemType) { + return load(itemId, CustomItem.class, customItemType); + } + + private T load(final String itemId, final Class clazz, final String customItemType) { + if (StringUtils.isEmpty(itemId)) { + return null; + } + + return new InClassLoaderExecute(metricsService, this.getClass().getName() + ".loadItem", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected T execute(Object... args) throws Exception { + try { + String itemType = Item.getItemType(clazz); + if (customItemType != null) { + itemType = customItemType; + } + String documentId = getDocumentIDForItemType(itemId, itemType); + + boolean sessionSpecialDirectAccess = sessionLatestIndex != null && Session.ITEM_TYPE.equals(itemType) ; + if (!sessionSpecialDirectAccess && isItemTypeRollingOver(itemType)) { + return new MetricAdapter(metricsService, ".loadItemWithQuery") { + @Override + public T execute(Object... args) throws Exception { + if (customItemType == null) { + PartialList r = query(Query.of(q -> q.ids(i -> i.values(documentId))), null, clazz, 0, 1, null, null); + if (r.size() > 0) { + return r.get(0); + } + } else { + PartialList r = query(Query.of(q -> q.ids(i -> i.values(documentId))), null, customItemType, 0, 1, null, null); + if (r.size() > 0) { + return (T) r.get(0); + } + } + return null; + } + }.execute(); + } else { + // Special handling for session we check the latest available index directly to speed up session loading + GetRequest.Builder getRequest = new GetRequest.Builder().index(sessionSpecialDirectAccess ? sessionLatestIndex : getIndex(itemType)).id(documentId); + GetResponse response = client.get(getRequest.build(), clazz); + if (response.found()) { + T value = response.source(); + setMetadata(value, response.id(), response.version(), response.seqNo(), response.primaryTerm(), response.index()); + return value; + } else { + return null; + } + } + } catch (OpenSearchException ose) { + if (ose.status() == 404) { + // this can happen if we are just testing the existence of the item, it is not always an error. + return null; + } + if ("IndexNotFound".equals(ose.error().type())) { + // this can happen if we are just testing the existence of the item, it is not always an error. + return null; + } + throw new Exception("Error loading itemType=" + clazz.getName() + " customItemType=" + customItemType + " itemId=" + itemId, ose); + } catch (Exception ex) { + throw new Exception("Error loading itemType=" + clazz.getName() + " customItemType=" + customItemType + " itemId=" + itemId, ex); + } + } + }.catchingExecuteInClassLoader(true); + + } + + private void setMetadata(Item item, String itemId, long version, long seqNo, long primaryTerm, String index) { + if (!systemItems.contains(item.getItemType()) && item.getItemId() == null) { + item.setItemId(itemId); + } + item.setVersion(version); + item.setSystemMetadata(SEQ_NO, seqNo); + item.setSystemMetadata(PRIMARY_TERM, primaryTerm); + item.setSystemMetadata("index", index); + } + + @Override + public boolean isConsistent(Item item) { + return getRefreshPolicy(item.getItemType()) != Refresh.False; + } + + @Override + public boolean save(final Item item) { + return save(item, useBatchingForSave, alwaysOverwrite); + } + + @Override + public boolean save(final Item item, final boolean useBatching) { + return save(item, useBatching, alwaysOverwrite); + } + + @Override + public boolean save(final Item item, final Boolean useBatchingOption, final Boolean alwaysOverwriteOption) { + final boolean useBatching = useBatchingOption == null ? this.useBatchingForSave : useBatchingOption; + final boolean alwaysOverwrite = alwaysOverwriteOption == null ? this.alwaysOverwrite : alwaysOverwriteOption; + + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".saveItem", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + try { + String itemType = item.getItemType(); + if (item instanceof CustomItem) { + itemType = ((CustomItem) item).getCustomItemType(); + } + String documentId = getDocumentIDForItemType(item.getItemId(), itemType); + String index = item.getSystemMetadata("index") != null ? (String) item.getSystemMetadata("index") : getIndex(itemType); + + IndexRequest.Builder indexRequest = new IndexRequest.Builder().index(index); + indexRequest.id(documentId); + indexRequest.document(item); + + if (!alwaysOverwrite) { + Long seqNo = (Long) item.getSystemMetadata(SEQ_NO); + Long primaryTerm = (Long) item.getSystemMetadata(PRIMARY_TERM); + + if (seqNo != null && primaryTerm != null) { + indexRequest.ifSeqNo(seqNo); + indexRequest.ifPrimaryTerm(primaryTerm); + } else { + indexRequest.opType(OpType.Create); + } + } + + if (routingByType.containsKey(itemType)) { + indexRequest.routing(routingByType.get(itemType)); + } + + try { + indexRequest.refresh(getRefreshPolicy(itemType)); + IndexResponse response = client.index(indexRequest.build()); + String responseIndex = response.index(); + String itemId = response.id(); + setMetadata(item, itemId, response.version(), response.seqNo(), response.primaryTerm(), responseIndex); + + // Special handling for session, in case of new session we check that a rollover happen or not to update the latest available index + if (Session.ITEM_TYPE.equals(itemType) && + sessionLatestIndex != null && + response.result().equals(Result.Created) && + !responseIndex.equals(sessionLatestIndex)) { + sessionLatestIndex = responseIndex; + } + logMetadataItemOperation("saved", item); + } catch (OpenSearchException ose) { + LOGGER.error("Could not find index {}, could not register item type {} with id {} ", index, itemType, item.getItemId(), ose); + return false; + } + return true; + } catch (IOException e) { + throw new Exception("Error saving item " + item, e); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + @Override + public boolean update(final Item item, final Date dateHint, final Class clazz, final String propertyName, final Object propertyValue) { + return update(item, clazz, propertyName, propertyValue); + } + + @Override + public boolean update(final Item item, final Date dateHint, final Class clazz, final Map source) { + return update(item, clazz, source); + } + + @Override + public boolean update(final Item item, final Date dateHint, final Class clazz, final Map source, final boolean alwaysOverwrite) { + return update(item, clazz, source, alwaysOverwrite); + } + + @Override + public boolean update(final Item item, final Class clazz, final String propertyName, final Object propertyValue) { + return update(item, clazz, Collections.singletonMap(propertyName, propertyValue), alwaysOverwrite); + } + + + @Override + public boolean update(final Item item, final Class clazz, final Map source) { + return update(item, clazz, source, alwaysOverwrite); + } + + @Override + public boolean update(final Item item, final Class clazz, final Map source, final boolean alwaysOverwrite) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".updateItem", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + try { + UpdateRequest updateRequest = createUpdateRequest(clazz, item, source, alwaysOverwrite); + + UpdateResponse response = client.update(updateRequest, String.class); + setMetadata(item, response.id(), response.version(), response.seqNo(), response.primaryTerm(), response.index()); + logMetadataItemOperation("updated", item); + return true; + } catch (OpenSearchException ose) { + throw new Exception("No index found for itemType=" + clazz.getName() + "itemId=" + item.getItemId(), ose); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + private UpdateRequest createUpdateRequest(Class clazz, Item item, Map source, boolean alwaysOverwrite) { + String itemType = Item.getItemType(clazz); + String documentId = getDocumentIDForItemType(item.getItemId(), itemType); + String index = item.getSystemMetadata("index") != null ? (String) item.getSystemMetadata("index") : getIndex(itemType); + + UpdateRequest.Builder updateRequest = new UpdateRequest.Builder().index(index).id(documentId); + updateRequest.doc(source); + + if (!alwaysOverwrite) { + Long seqNo = (Long) item.getSystemMetadata(SEQ_NO); + Long primaryTerm = (Long) item.getSystemMetadata(PRIMARY_TERM); + + if (seqNo != null && primaryTerm != null) { + updateRequest.ifSeqNo(seqNo); + updateRequest.ifPrimaryTerm(primaryTerm); + } + } + return updateRequest.build(); + } + + private UpdateOperation createUpdateOperation(Class clazz, Item item, Map source, boolean alwaysOverwrite) { + String itemType = Item.getItemType(clazz); + String documentId = getDocumentIDForItemType(item.getItemId(), itemType); + String index = item.getSystemMetadata("index") != null ? (String) item.getSystemMetadata("index") : getIndex(itemType); + + UpdateOperation.Builder updateOperation = new UpdateOperation.Builder().index(index).id(documentId); + updateOperation.document(source); + + if (!alwaysOverwrite) { + Long seqNo = (Long) item.getSystemMetadata(SEQ_NO); + Long primaryTerm = (Long) item.getSystemMetadata(PRIMARY_TERM); + + if (seqNo != null && primaryTerm != null) { + updateOperation.ifSeqNo(seqNo); + updateOperation.ifPrimaryTerm(primaryTerm); + } + } + return updateOperation.build(); + } + + @Override + public List update(final Map items, final Date dateHint, final Class clazz) { + if (items.isEmpty()) + return new ArrayList<>(); + + return new InClassLoaderExecute>(metricsService, OpenSearchPersistenceServiceImpl.this.getClass().getName() + ".updateItems", OpenSearchPersistenceServiceImpl.this.bundleContext, OpenSearchPersistenceServiceImpl.this.fatalIllegalStateErrors, throwExceptions) { + protected List execute(Object... args) throws Exception { + long batchRequestStartTime = System.currentTimeMillis(); + + List operations = new ArrayList<>(); + items.forEach((item, source) -> { + UpdateOperation updateOperation = createUpdateOperation(clazz, item, source, alwaysOverwrite); + operations.add(BulkOperation.of(b -> b.update(updateOperation))); + }); + + BulkResponse bulkResponse = client.bulk(b -> b.operations(operations)); + LOGGER.debug("{} profiles updated with bulk segment in {}ms", operations.size(), System.currentTimeMillis() - batchRequestStartTime); + + List failedItemsIds = new ArrayList<>(); + + if (bulkResponse.errors()) { + bulkResponse.items().forEach(bulkItemResponse -> { + if (bulkItemResponse.error() != null) { + failedItemsIds.add(bulkItemResponse.id()); + } + }); + } + return failedItemsIds; + } + }.catchingExecuteInClassLoader(true); + } + + @Override + public boolean updateWithQueryAndScript(final Date dateHint, final Class clazz, final String[] scripts, final Map[] scriptParams, final Condition[] conditions) { + return updateWithQueryAndScript(clazz, scripts, scriptParams, conditions); + } + + @Override + public boolean updateWithQueryAndScript(final Class clazz, final String[] scripts, final Map[] scriptParams, final Condition[] conditions) { + Script[] builtScripts = new Script[scripts.length]; + for (int i = 0; i < scripts.length; i++) { + final int finalI = i; + builtScripts[i] = Script.of(script -> script.inline(inline->inline.lang("painless").source(scripts[finalI]).params(convertParams(scriptParams[finalI])))); + } + return updateWithQueryAndScript(new Class[]{clazz}, builtScripts, conditions, true); + } + + private Map convertParams(Map scriptParams) { + Map jsonParams = new HashMap<>(); + for (Map.Entry paramEntry : scriptParams.entrySet()) { + jsonParams.put(paramEntry.getKey(), JsonData.of(paramEntry.getValue(), jsonpMapper)); + } + return jsonParams; + } + + @Override + public boolean updateWithQueryAndStoredScript(Date dateHint, Class clazz, String[] scripts, Map[] scriptParams, Condition[] conditions) { + return updateWithQueryAndStoredScript(new Class[]{clazz}, scripts, scriptParams, conditions, true); + } + + @Override + public boolean updateWithQueryAndStoredScript(Class clazz, String[] scripts, Map[] scriptParams, Condition[] conditions) { + return updateWithQueryAndStoredScript(new Class[]{clazz}, scripts, scriptParams, conditions, true); + } + + @Override + public boolean updateWithQueryAndStoredScript(Class[] classes, String[] scripts, Map[] scriptParams, Condition[] conditions, boolean waitForComplete) { + Script[] builtScripts = new Script[scripts.length]; + for (int i = 0; i < scripts.length; i++) { + final int finalI = i; + builtScripts[i] = Script.of(s -> s.stored(stored -> stored.id(scripts[finalI]).params(convertParams(scriptParams[finalI])))); + } + return updateWithQueryAndScript(classes, builtScripts, conditions, waitForComplete); + } + + private boolean updateWithQueryAndScript(final Class[] classes, final Script[] scripts, final Condition[] conditions, boolean waitForComplete) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".updateWithQueryAndScript", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + String[] itemTypes = Arrays.stream(classes).map(Item::getItemType).toArray(String[]::new); + List indices = Arrays.stream(itemTypes).map(itemType -> getIndexNameForQuery(itemType)).collect(Collectors.toList()); + + try { + for (int i = 0; i < scripts.length; i++) { + RefreshRequest refreshRequest = new RefreshRequest.Builder().index(indices).build(); + client.indices().refresh(refreshRequest); + + Query queryBuilder = conditionOSQueryBuilderDispatcher.buildFilter(conditions[i]); + UpdateByQueryRequest.Builder updateByQueryRequestBuilder = new UpdateByQueryRequest.Builder().index(indices); + updateByQueryRequestBuilder.conflicts(Conflicts.Proceed); + // TODO fix this updateByQueryRequest.setMaxRetries(1000); + updateByQueryRequestBuilder.slices(2L); + updateByQueryRequestBuilder.script(scripts[i]); + updateByQueryRequestBuilder.query(wrapWithItemsTypeQuery(itemTypes, queryBuilder)); + updateByQueryRequestBuilder.waitForCompletion(false); // force the return of a task ID. + + UpdateByQueryRequest updateByQueryRequest = updateByQueryRequestBuilder.build(); + UpdateByQueryResponse updateByQueryResponse = client.updateByQuery(updateByQueryRequest); + if (updateByQueryResponse == null) { + LOGGER.error("update with query and script: no response returned for query: {}", queryBuilder); + } else if (waitForComplete) { + waitForTaskComplete(updateByQueryRequest.toString(), updateByQueryRequest.toString(), updateByQueryResponse.task()); + } else { + LOGGER.debug("ES task started {}", updateByQueryResponse.task()); + } + } + return true; + } catch (OpenSearchException ose) { + throw new Exception("No index found for itemTypes=" + String.join(",", itemTypes), ose); + /* TODO Implement this + } catch (ScriptException e) { + LOGGER.error("Error in the update script : {}\n{}\n{}", e.getScript(), e.getDetailedMessage(), e.getScriptStack()); + throw new Exception("Error in the update script"); + */ + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + private void waitForTaskComplete(String request, String requestSource, String taskId) { + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Waiting task [{}]: [{}] using query: [{}], polling every {}ms with a timeout configured to {}ms", + taskId, request, requestSource, taskWaitingPollingInterval, taskWaitingTimeout); + } + if (taskId == null) { + LOGGER.warn("No taskId provided, can't wait for task [{}]", request); + return; + } + long start = System.currentTimeMillis(); + new InClassLoaderExecute(metricsService, this.getClass().getName() + ".waitForTask", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Void execute(Object... args) throws Exception { + + while (true){ + GetTasksResponse getTasksResponse = client.tasks().get(t -> t.taskId(taskId)); + if (getTasksResponse.completed()) { + if (LOGGER.isDebugEnabled()) { + long millis = getTasksResponse.task().runningTimeInNanos() / 1_000_000; + long seconds = millis / 1000; + + LOGGER.debug("Waiting task [{}]: Finished in {} {}", taskId, + seconds >= 1 ? seconds : millis, + seconds >= 1 ? "seconds" : "milliseconds"); + } + break; + } else { + if ((start + taskWaitingTimeout) < System.currentTimeMillis()) { + LOGGER.error("Waiting task [{}]: Exceeded configured timeout ({}ms), aborting wait process", taskId, taskWaitingTimeout); + break; + } + + try { + Thread.sleep(taskWaitingPollingInterval); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IllegalStateException("Waiting task [{}]: interrupted"); + } + } + } + return null; + } + }.catchingExecuteInClassLoader(true); + } + + @Override + public boolean storeScripts(Map scripts) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".storeScripts", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + boolean executedSuccessfully = true; + for (Map.Entry script : scripts.entrySet()) { + PutScriptRequest.Builder putScriptRequestBuilder = new PutScriptRequest.Builder(); + putScriptRequestBuilder.script(s -> s.lang("painless").source(script.getValue())); + putScriptRequestBuilder.id(script.getKey()); + PutScriptResponse response = client.putScript(putScriptRequestBuilder.build()); + executedSuccessfully &= response.acknowledged(); + if (response.acknowledged()) { + LOGGER.info("Successfully stored painless script: {}", script.getKey()); + } else { + LOGGER.error("Failed to store painless script: {}", script.getKey()); + } + } + return executedSuccessfully; + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + public boolean updateWithScript(final Item item, final Date dateHint, final Class clazz, final String script, final Map scriptParams) { + return updateWithScript(item, clazz, script, scriptParams); + } + + @Override + public boolean updateWithScript(final Item item, final Class clazz, final String script, final Map scriptParams) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".updateWithScript", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + try { + String itemType = Item.getItemType(clazz); + String index = getIndex(itemType); + String documentId = getDocumentIDForItemType(item.getItemId(), itemType); + + Script actualScript = Script.of(s -> s.inline(i -> i.lang("painless").source(script).params(convertParams(scriptParams)))); + + UpdateRequest.Builder updateRequestBuilder = new UpdateRequest.Builder().index(index).id(documentId); + + Long seqNo = (Long) item.getSystemMetadata(SEQ_NO); + Long primaryTerm = (Long) item.getSystemMetadata(PRIMARY_TERM); + + if (seqNo != null && primaryTerm != null) { + updateRequestBuilder.ifSeqNo(seqNo); + updateRequestBuilder.ifPrimaryTerm(primaryTerm); + } + updateRequestBuilder.script(actualScript); + UpdateResponse response = client.update(updateRequestBuilder.build(), Item.class); + setMetadata(item, response.id(), response.version(), response.seqNo(), response.primaryTerm(), response.index()); + + return true; + } catch (OpenSearchException ose) { + throw new Exception("No index found for itemType=" + clazz.getName() + "itemId=" + item.getItemId(), ose); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + @Override + public boolean remove(final String itemId, final Class clazz) { + return remove(itemId, clazz, null); + } + + @Override + public boolean removeCustomItem(final String itemId, final String customItemType) { + return remove(itemId, CustomItem.class, customItemType); + } + + private boolean remove(final String itemId, final Class clazz, String customItemType) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".removeItem", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + try { + String itemType = Item.getItemType(clazz); + if (customItemType != null) { + itemType = customItemType; + } + String documentId = getDocumentIDForItemType(itemId, itemType); + String index = getIndex(itemType); + + DeleteRequest deleteRequest = DeleteRequest.of(d->d.index(index).id(documentId)); + client.delete(deleteRequest); + if (MetadataItem.class.isAssignableFrom(clazz)) { + LOGGER.info("Item of type {} with ID {} has been removed", customItemType != null ? customItemType : clazz.getSimpleName(), itemId); + } + return true; + } catch (Exception e) { + throw new Exception("Cannot remove", e); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + public boolean removeByQuery(final Condition query, final Class clazz) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".removeByQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + Query queryBuilder = conditionOSQueryBuilderDispatcher.getQueryBuilder(query); + return removeByQuery(queryBuilder, clazz); + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + public boolean removeByQuery(Query queryBuilder, final Class clazz) throws Exception { + try { + String itemType = Item.getItemType(clazz); + LOGGER.debug("Remove item of type {} using a query", itemType); + final DeleteByQueryRequest.Builder deleteByQueryRequestBuilder = new DeleteByQueryRequest.Builder().index(getIndexNameForQuery(itemType)) + .query(wrapWithItemTypeQuery(itemType, queryBuilder)) + // Setting slices to auto will let OpenSearch choose the number of slices to use. + // This setting will use one slice per shard, up to a certain limit. + // The delete request will be more efficient and faster than no slicing. + .slices(0L) // 0L means auto + // OpenSearch takes a snapshot of the index when you hit delete by query request and uses the _version of the documents to process the request. + // If a document gets updated in the meantime, it will result in a version conflict error and the delete operation will fail. + // So we explicitly set the conflict strategy to proceed in case of version conflict. + .conflicts(Conflicts.Proceed) + // We force waitForCompletion to the value false to make sure we get back a taskID that we can then poll for + // in our waitForTaskComplete method + .waitForCompletion(false) + // Remove by Query is mostly used for purge and cleaning up old data + // It's mostly used in jobs/timed tasks so we don't really care about long request + // So we increase default timeout of 1min to 10min + .timeout(t -> t.time(removeByQueryTimeoutInMinutes + "m")); + + DeleteByQueryRequest deleteByQueryRequest = deleteByQueryRequestBuilder.build(); + DeleteByQueryResponse deleteByQueryResponse = client.deleteByQuery(deleteByQueryRequest); + + if (deleteByQueryResponse == null) { + LOGGER.error("Remove by query: no response returned for query: {}", queryBuilder); + return false; + } + + waitForTaskComplete(deleteByQueryRequest.toString(), deleteByQueryRequest.toString(), deleteByQueryResponse.task()); + + return true; + } catch (Exception e) { + throw new Exception("Cannot remove by query", e); + } + } + + public boolean indexTemplateExists(final String templateName) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".indexTemplateExists", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws IOException { + return client.indices().existsTemplate(e -> e.name(templateName)).value(); + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + public boolean removeIndexTemplate(final String templateName) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".removeIndexTemplate", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws IOException { + DeleteTemplateResponse deleteTemplateResponse = client.indices().deleteTemplate(d -> d.name(templateName)); + return deleteTemplateResponse.acknowledged(); + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + public boolean registerRolloverLifecyclePolicy() { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".createMonthlyIndexLifecyclePolicy", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws IOException { + try { + String policyName = indexPrefix + "-rollover-lifecycle-policy"; + String endpoint = "_plugins/_ism/policies/" + policyName; + + RestClient restClient = ((RestClientTransport) client._transport()).restClient(); + Request getRequest = new Request("GET", endpoint); + Response response = restClient.performRequest(getRequest); + if (response.getStatusLine().getStatusCode() == 200) { + LOGGER.info("Found existing rollover lifecycle policy, deleting the existing one."); + Request deleteRequest = new Request("DELETE", endpoint); + restClient.performRequest(deleteRequest); + } + + // Build the ILM policy JSON + Map rolloverAction = new HashMap<>(); + + if (rolloverMaxDocs != null && !rolloverMaxDocs.isEmpty()) { + rolloverAction.put("min_doc_count", Long.parseLong(rolloverMaxDocs)); + } + if (rolloverMaxSize != null && !rolloverMaxSize.isEmpty()) { + rolloverAction.put("min_size", rolloverMaxSize); + } + if (rolloverMaxAge != null && !rolloverMaxAge.isEmpty()) { + rolloverAction.put("min_index_age", rolloverMaxAge); + } + + List> actions = new ArrayList<>(); + actions.add(Map.of("rollover", rolloverAction)); + Map state = new HashMap<>(); + state.put("name", "ingest"); + state.put("actions", actions); + state.put("transitions", new ArrayList<>()); + List> states = new ArrayList<>(); + states.add(state); + Map policy = new HashMap<>(); + policy.put("states", states); + policy.put("default_state", "ingest"); + policy.put("description", "Rollover lifecycle policy"); + if (rolloverIndices != null && !rolloverIndices.isEmpty()) { + Map ismTemplate = new HashMap<>(); + List indexPatterns = new ArrayList<>(); + indexPatterns.addAll(rolloverIndices); + ismTemplate.put("index_patterns", indexPatterns); + ismTemplate.put("priority", 100); + policy.put("ism_template", ismTemplate); + } + Map policies = new HashMap<>(); + policies.put("policy", policy); + + // Convert the policy to JSON + ObjectMapper objectMapper = new ObjectMapper(); + String policyJson = objectMapper.writeValueAsString(policies); + + // Send the request + + Request request = new Request("PUT", endpoint); + request.setJsonEntity(policyJson); + response = restClient.performRequest(request); + + return response.getStatusLine().getStatusCode() == 200; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + public boolean createIndex(final String itemType) { + LOGGER.debug("Create index {}", itemType); + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".createIndex", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws IOException { + String index = getIndex(itemType); + boolean indexExists = client.indices().exists(e -> e.index(index)).value(); + + if (!indexExists) { + if (isItemTypeRollingOver(itemType)) { + internalCreateRolloverTemplate(itemType); + internalCreateRolloverIndex(index); + } else { + internalCreateIndex(index, mappings.get(itemType)); + } + } + + return !indexExists; + } + }.catchingExecuteInClassLoader(true); + + return Objects.requireNonNullElse(result, false); + } + + public boolean removeIndex(final String itemType) { + String index = getIndex(itemType); + + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".removeIndex", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws IOException { + boolean indexExists = client.indices().exists(e -> e.index(index)).value(); + if (indexExists) { + client.indices().delete(d -> d.index(index)); + } + return indexExists; + } + }.catchingExecuteInClassLoader(true); + + return Objects.requireNonNullElse(result, false); + } + + private void internalCreateRolloverTemplate(String itemName) throws IOException { + String rolloverAlias = indexPrefix + "-" + itemName; + if (mappings.get(itemName) == null) { + LOGGER.warn("Couldn't find mapping for item {}, won't create monthly index template", itemName); + return; + } + String indexSource = + " {" + + " \"number_of_shards\" : " + StringUtils.defaultIfEmpty(rolloverIndexNumberOfShards, monthlyIndexNumberOfShards) + "," + + " \"number_of_replicas\" : " + StringUtils.defaultIfEmpty(rolloverIndexNumberOfReplicas, monthlyIndexNumberOfReplicas) + "," + + " \"mapping.total_fields.limit\" : " + StringUtils.defaultIfEmpty(rolloverIndexMappingTotalFieldsLimit, monthlyIndexMappingTotalFieldsLimit) + "," + + " \"max_docvalue_fields_search\" : " + StringUtils.defaultIfEmpty(rolloverIndexMaxDocValueFieldsSearch, monthlyIndexMaxDocValueFieldsSearch) + "," + + " \"plugins.index_state_management.rollover_alias\": \"" + rolloverAlias + "\"" + + " },"; + String analysisSource = + " {" + + " \"analyzer\": {" + + " \"folding\": {" + + " \"type\":\"custom\"," + + " \"tokenizer\": \"keyword\"," + + " \"filter\": [ \"lowercase\", \"asciifolding\" ]" + + " }\n" + + " }\n" + + " }\n"; + Map settings = new HashMap<>(); + settings.put("index", getJsonData(indexSource)); + settings.put("analysis", getJsonData(analysisSource)); + client.indices().putTemplate(p-> + p.name(rolloverAlias + "-rollover-template") + .indexPatterns(Collections.singletonList(getRolloverIndexForQuery(itemName))) + .order(1) + .settings(settings) + .mappings(getTypeMapping(mappings.get(itemName))) + ); + } + + private JsonData getJsonData(String input) { + JsonpMapper mapper = client._transport().jsonpMapper(); + JsonParser parser = mapper + .jsonProvider() + .createParser(new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8))); + return JsonData._DESERIALIZER.deserialize(parser, mapper); + } + + private void internalCreateRolloverIndex(String indexName) throws IOException { + CreateIndexResponse createIndexResponse = client.indices().create(c->c + .index(indexName + "-000001") + .aliases(indexName, a->a.isWriteIndex(true))); + LOGGER.info("Index created: [{}], acknowledge: [{}], shards acknowledge: [{}]", createIndexResponse.index(), + createIndexResponse.acknowledged(), createIndexResponse.shardsAcknowledged()); + } + + private void internalCreateIndex(String indexName, String mappingSource) throws IOException { + CreateIndexResponse createIndexResponse = client.indices().create(c -> c + .index(indexName) + .settings(s -> s + .index(i -> i + .numberOfShards(numberOfShards) + .numberOfReplicas(numberOfReplicas) + .mapping(m -> m + .totalFields(t -> t + .limit(Long.parseLong(indexMappingTotalFieldsLimit)) + ) + ) + .maxDocvalueFieldsSearch(Integer.parseInt(indexMaxDocValueFieldsSearch)) + ) + .analysis(a -> a + .analyzer("folding", an -> an + .custom(cu -> cu + .tokenizer("keyword") + .filter("lowercase", "asciifolding") + ) + ) + ) + ) + .mappings(getTypeMapping(mappingSource)) + ); + LOGGER.info("Index created: [{}], acknowledge: [{}], shards acknowledge: [{}]", createIndexResponse.index(), + createIndexResponse.acknowledged(), createIndexResponse.shardsAcknowledged()); + } + + @Override + public void createMapping(String type, String source) { + try { + putMapping(source, getIndex(type)); + } catch (IOException ioe) { + LOGGER.error("Error while creating mapping for type " + type + " and source " + source, ioe); + } + } + + public void setPropertyMapping(final PropertyType property, final String itemType) { + try { + Map> mappings = getPropertiesMapping(itemType); + if (mappings == null) { + mappings = new HashMap<>(); + } + Map subMappings = mappings.computeIfAbsent("properties", k -> new HashMap<>()); + Map subSubMappings = (Map) subMappings.computeIfAbsent("properties", k -> new HashMap<>()); + + if (subSubMappings.containsKey(property.getItemId())) { + LOGGER.warn("Mapping already exists for type " + itemType + " and property " + property.getItemId()); + return; + } + + Map propertyMapping = createPropertyMapping(property); + if (propertyMapping.isEmpty()) { + return; + } + + mergePropertiesMapping(subSubMappings, propertyMapping); + + Map mappingsWrapper = new HashMap<>(); + mappingsWrapper.put("properties", mappings); + final String mappingsSource = OSCustomObjectMapper.getObjectMapper().writeValueAsString(mappingsWrapper); + + putMapping(mappingsSource, getIndex(itemType)); + } catch (IOException ioe) { + LOGGER.error("Error while creating mapping for type " + itemType + " and property " + property.getValueTypeId(), ioe); + } + } + + private Map createPropertyMapping(final PropertyType property) { + final String esType = convertValueTypeToESType(property.getValueTypeId()); + final HashMap definition = new HashMap<>(); + + if (esType == null) { + LOGGER.warn("No predefined type found for property[{}], no mapping will be created", property.getValueTypeId()); + return Collections.emptyMap(); + } else { + definition.put("type", esType); + if ("text".equals(esType)) { + definition.put("analyzer", "folding"); + final Map fields = new HashMap<>(); + final Map keywordField = new HashMap<>(); + keywordField.put("type", "keyword"); + keywordField.put("ignore_above", 256); + fields.put("keyword", keywordField); + definition.put("fields", fields); + } + } + + if ("set".equals(property.getValueTypeId())) { + Map childProperties = new HashMap<>(); + property.getChildPropertyTypes().forEach(childType -> { + Map propertyMapping = createPropertyMapping(childType); + if (!propertyMapping.isEmpty()) { + mergePropertiesMapping(childProperties, propertyMapping); + } + }); + definition.put("properties", childProperties); + } + + return Collections.singletonMap(property.getItemId(), definition); + } + + private String convertValueTypeToESType(String valueTypeId) { + switch (valueTypeId) { + case "set": + case "json": + return "object"; + case "boolean": + return "boolean"; + case "geopoint": + return "geo_point"; + case "integer": + return "integer"; + case "long": + return "long"; + case "float": + return "float"; + case "date": + return "date"; + case "string": + case "id": + case "email": // TODO Consider supporting email mapping in ES, right now will be map to text to avoid warning in logs + return "text"; + default: + return null; + } + } + + private boolean putMapping(final String source, final String indexName) throws IOException { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".putMapping", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + try { + TypeMapping typeMapping = getTypeMapping(source); + PutMappingResponse response = client.indices().putMapping(p -> p + .index(indexName) + .properties(typeMapping.properties()) + .dynamicTemplates(typeMapping.dynamicTemplates()) + .dateDetection(typeMapping.dateDetection()) + .dynamic(typeMapping.dynamic()) + .dynamicDateFormats(typeMapping.dynamicDateFormats()) + .fieldNames(typeMapping.fieldNames()) + .meta(typeMapping.meta()) + .numericDetection(typeMapping.numericDetection()) + .routing(typeMapping.routing()) + .source(typeMapping.source()) + ); + return response.acknowledged(); + } catch (Exception e) { + throw new Exception("Cannot create/update mapping", e); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + @Override + public Map> getPropertiesMapping(final String itemType) { + return new InClassLoaderExecute>>(metricsService, this.getClass().getName() + ".getPropertiesMapping", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + @SuppressWarnings("unchecked") + protected Map> execute(Object... args) throws Exception { + + Request request = new Request("GET", "/" + getIndexNameForQuery(itemType) + "/_mapping"); + + // Send the request + Response response = restClient.performRequest(request); + String json = EntityUtils.toString(response.getEntity()); + Map>> indexMappings = (Map>>) new ObjectMapper().readValue(json, Map.class); + + Map> mappings = (Map>) indexMappings.get(indexMappings.keySet().iterator().next()); // remove index wrapping object + + // Get all mapping for current itemType + + // create a list of Keys to get the mappings in chronological order + // in case there is monthly context then the mapping will be added from the oldest to the most recent one + Set orderedKeys = new TreeSet<>(mappings.keySet()); + Map> result = new HashMap<>(); + try { + for (String key : orderedKeys) { + if (mappings.containsKey(key)) { + Map> properties = (Map>) mappings.get(key).get("properties"); + for (Map.Entry> entry : properties.entrySet()) { + if (result.containsKey(entry.getKey())) { + Map subResult = result.get(entry.getKey()); + + for (Map.Entry subentry : entry.getValue().entrySet()) { + if (subResult.containsKey(subentry.getKey()) + && subResult.get(subentry.getKey()) instanceof Map + && subentry.getValue() instanceof Map) { + mergePropertiesMapping((Map) subResult.get(subentry.getKey()), (Map) subentry.getValue()); + } else { + subResult.put(subentry.getKey(), subentry.getValue()); + } + } + } else { + result.put(entry.getKey(), entry.getValue()); + } + } + } + } + } catch (Throwable t) { + throw new Exception("Cannot get mapping for itemType=" + itemType, t); + } + return result; + } + }.catchingExecuteInClassLoader(true); + } + + private void mergePropertiesMapping(Map result, Map entry) { + if (entry == null || entry.isEmpty()) { + return; + } + for (Map.Entry subentry : entry.entrySet()) { + if (result.containsKey(subentry.getKey()) + && result.get(subentry.getKey()) instanceof Map + && subentry.getValue() instanceof Map) { + mergePropertiesMapping((Map) result.get(subentry.getKey()), (Map) subentry.getValue()); + } else { + result.put(subentry.getKey(), subentry.getValue()); + } + } + } + + public Map getPropertyMapping(String property, String itemType) { + Map> mappings = knownMappings.get(itemType); + Map result = getPropertyMapping(property, mappings); + if (result == null) { + mappings = getPropertiesMapping(itemType); + knownMappings.put(itemType, mappings); + result = getPropertyMapping(property, mappings); + } + return result; + } + + private Map getPropertyMapping(String property, Map> mappings) { + Map propMapping = null; + String[] properties = StringUtils.split(property, '.'); + for (int i = 0; i < properties.length && mappings != null; i++) { + String s = properties[i]; + propMapping = mappings.get(s); + if (i == properties.length - 1) { + return propMapping; + } else { + mappings = propMapping != null ? ((Map>) propMapping.get("properties")) : null; + } + } + return null; + } + + private String getPropertyNameWithData(String name, String itemType) { + Map propertyMapping = getPropertyMapping(name, itemType); + if (propertyMapping == null) { + return null; + } + if (propertyMapping != null + && "text".equals(propertyMapping.get("type")) + && propertyMapping.containsKey("fields") + && ((Map) propertyMapping.get("fields")).containsKey("keyword")) { + name += ".keyword"; + } + return name; + } + + public boolean saveQuery(final String queryName, final String query) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".saveQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + //Index the query = register it in the percolator + try { + LOGGER.info("Saving query : " + queryName); + String index = getIndex(".percolator"); + client.index(i->i.id(queryName).index(index).refresh(Refresh.WaitFor).document(query)); + return true; + } catch (Exception e) { + throw new Exception("Cannot save query", e); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + @Override + public boolean saveQuery(String queryName, Condition query) { + if (query == null) { + return false; + } + saveQuery(queryName, conditionOSQueryBuilderDispatcher.getQuery(query)); + return true; + } + + @Override + public boolean removeQuery(final String queryName) { + Boolean result = new InClassLoaderExecute(metricsService, this.getClass().getName() + ".removeQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + //Index the query = register it in the percolator + try { + String index = getIndex(".percolator"); + client.delete(d->d.index(index).id(queryName).refresh(Refresh.WaitFor)); + return true; + } catch (Exception e) { + throw new Exception("Cannot delete query", e); + } + } + }.catchingExecuteInClassLoader(true); + return Objects.requireNonNullElse(result, false); + } + + @Override + public boolean isValidCondition(Condition condition, Item item) { + try { + conditionEvaluatorDispatcher.eval(condition, item); + Query.of(q -> q + .bool(b -> b + .must(m -> m.ids(i -> i.values(item.getItemId()))) + .must(conditionOSQueryBuilderDispatcher.buildFilter(condition)))); + } catch (Exception e) { + LOGGER.error("Failed to validate condition. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Failed to validate condition, condition={}", condition, e); + } + + return false; + } + return true; + } + + @Override + public boolean testMatch(Condition query, Item item) { + long startTime = System.currentTimeMillis(); + try { + return conditionEvaluatorDispatcher.eval(query, item); + } catch (UnsupportedOperationException e) { + LOGGER.error("Eval not supported, continue with query", e); + } finally { + if (metricsService != null && metricsService.isActivated()) { + metricsService.updateTimer(this.getClass().getName() + ".testMatchLocally", startTime); + } + } + startTime = System.currentTimeMillis(); + try { + final Class clazz = item.getClass(); + String itemType = Item.getItemType(clazz); + String documentId = getDocumentIDForItemType(item.getItemId(), itemType); + + Query builder = Query.of(q -> q.bool(b -> b + .must(Query.of(q2->q2.ids(i->i.values(documentId)))) + .must(conditionOSQueryBuilderDispatcher.buildFilter(query)))); + return queryCount(builder, itemType) > 0; + } finally { + if (metricsService != null && metricsService.isActivated()) { + metricsService.updateTimer(this.getClass().getName() + ".testMatchInOpenSearch", startTime); + } + } + } + + + @Override + public List query(final Condition query, String sortBy, final Class clazz) { + return query(query, sortBy, clazz, 0, -1).getList(); + } + + @Override + public PartialList query(final Condition query, String sortBy, final Class clazz, final int offset, final int size) { + return query(conditionOSQueryBuilderDispatcher.getQueryBuilder(query), sortBy, clazz, offset, size, null, null); + } + + @Override + public PartialList query(final Condition query, String sortBy, final Class clazz, final int offset, final int size, final String scrollTimeValidity) { + return query(conditionOSQueryBuilderDispatcher.getQueryBuilder(query), sortBy, clazz, offset, size, null, scrollTimeValidity); + } + + @Override + public PartialList queryCustomItem(final Condition query, String sortBy, final String customItemType, final int offset, final int size, final String scrollTimeValidity) { + return query(conditionOSQueryBuilderDispatcher.getQueryBuilder(query), sortBy, customItemType, offset, size, null, scrollTimeValidity); + } + + @Override + public PartialList queryFullText(final String fulltext, final Condition query, String sortBy, final Class clazz, final int offset, final int size) { + return query(Query.of(q -> + q.bool(b -> + b.must(Query.of(q2 -> + q2.queryString(qs -> qs.query(fulltext)))) + .must(conditionOSQueryBuilderDispatcher.getQueryBuilder(query)))), sortBy, clazz, offset, size, null, null); + } + + @Override + public List query(final String fieldName, final String fieldValue, String sortBy, final Class clazz) { + return query(fieldName, fieldValue, sortBy, clazz, 0, -1).getList(); + } + + @Override + public List query(final String fieldName, final String[] fieldValues, String sortBy, final Class clazz) { + List foldedFieldValues = Arrays.stream(ConditionContextHelper.foldToASCII(fieldValues)).map(FieldValue::of).collect(Collectors.toList()); + return query(Query.of(q->q.terms(t->t.field(fieldName).terms(tv->tv.value(foldedFieldValues)))), sortBy, clazz, 0, -1, getRouting(fieldName, fieldValues, clazz), null).getList(); + } + + @Override + public PartialList query(String fieldName, String fieldValue, String sortBy, Class clazz, int offset, int size) { + return query(Query.of(q->q.term(t->t.field(fieldName).value(v->v.stringValue(ConditionContextHelper.foldToASCII(fieldValue))))), sortBy, clazz, offset, size, getRouting(fieldName, new String[]{fieldValue}, clazz), null); + } + + @Override + public PartialList queryFullText(String fieldName, String fieldValue, String fulltext, String sortBy, Class clazz, int offset, int size) { + return query(Query.of(q -> q + .bool(b -> b + .must(Query.of(q2 -> q2 + .queryString(q3 -> q3 + .query(fulltext) + ) + ) + ) + .must(Query.of(q4 -> q4 + .term(t -> t + .field(fieldName) + .value(v -> v.stringValue(fieldValue) + ) + ) + ) + ) + ) + ), + sortBy, clazz, offset, size, getRouting(fieldName, new String[]{fieldValue}, clazz), null); + } + + @Override + public PartialList queryFullText(String fulltext, String sortBy, Class clazz, int offset, int size) { + return query(Query.of(q->q.queryString(s->s.query(fulltext))), sortBy, clazz, offset, size, null, null); + } + + @Override + public PartialList rangeQuery(String fieldName, String from, String to, String sortBy, Class clazz, int offset, int size) { + return query(Query.of(q->q.range(r->r.field(fieldName).from(JsonData.of(from)).to(JsonData.of(to)))), sortBy, clazz, offset, size, null, null); + } + + @Override + public long queryCount(Condition query, String itemType) { + try { + return conditionOSQueryBuilderDispatcher.count(query); + } catch (UnsupportedOperationException e) { + try { + Query filter = conditionOSQueryBuilderDispatcher.buildFilter(query); + if (filter.isIds()) { + return filter.ids().values().size(); + } + return queryCount(filter, itemType); + } catch (UnsupportedOperationException e1) { + return -1; + } + } + } + + private long queryCount(final Query filter, final String itemType) { + return new InClassLoaderExecute(metricsService, this.getClass().getName() + ".queryCount", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + + @Override + protected Long execute(Object... args) throws IOException { + CountResponse response = client.count(count -> count.index(getIndexNameForQuery(itemType)) + .query(wrapWithItemTypeQuery(itemType, filter))); + return response.count(); + } + }.catchingExecuteInClassLoader(true); + } + + private PartialList query(final Query query, final String sortBy, final Class clazz, final int offset, final int size, final String[] routing, final String scrollTimeValidity) { + return query(query, sortBy, clazz, null, offset, size, routing, scrollTimeValidity); + } + + private PartialList query(final Query query, final String sortBy, final String customItemType, final int offset, final int size, final String[] routing, final String scrollTimeValidity) { + return query(query, sortBy, CustomItem.class, customItemType, offset, size, routing, scrollTimeValidity); + } + + private PartialList query(final Query query, final String sortBy, final Class clazz, final String customItemType, final int offset, final int size, final String[] routing, final String scrollTimeValidity) { + return new InClassLoaderExecute>(metricsService, this.getClass().getName() + ".query", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + + @Override + protected PartialList execute(Object... args) throws Exception { + List results = new ArrayList<>(); + String scrollIdentifier = null; + long totalHits = 0; + PartialList.Relation totalHitsRelation = PartialList.Relation.EQUAL; + try { + String itemType = Item.getItemType(clazz); + if (customItemType != null) { + itemType = customItemType; + } + String keepAlive; + SearchRequest.Builder searchRequest = new SearchRequest.Builder().index(getIndexNameForQuery(itemType)); + searchRequest.seqNoPrimaryTerm(true) + .query(wrapWithItemTypeQuery(itemType, query)) + .size(size < 0 ? defaultQueryLimit : size) + .source(s->s.fetch(true)) + .from(offset); + if (scrollTimeValidity != null) { + keepAlive = scrollTimeValidity; + searchRequest.scroll(s->s.time(keepAlive)); + } else { + keepAlive = "1h"; + } + + if (size == Integer.MIN_VALUE) { + searchRequest.size(defaultQueryLimit); + } else if (size != -1) { + searchRequest.size(size); + } else { + // size == -1, use scroll query to retrieve all the results + searchRequest.scroll(s->s.time(keepAlive)); + } + if (routing != null) { + searchRequest.routing(StringUtils.join(routing, ",")); + } + if (sortBy != null) { + String[] sortByArray = sortBy.split(","); + for (String sortByElement : sortByArray) { + if (sortByElement.startsWith("geo:")) { + String[] elements = sortByElement.split(":"); + GeoDistanceSort.Builder distanceSortBuilder = new GeoDistanceSort.Builder(); + distanceSortBuilder.field(elements[1]); + distanceSortBuilder.location(l->l.latlon(latlon->latlon.lat(Double.parseDouble(elements[2])).lon(Double.parseDouble(elements[3])))); + distanceSortBuilder.unit(DistanceUnit.Kilometers); + if (elements.length > 4 && elements[4].equals("desc")) { + distanceSortBuilder.order(SortOrder.Desc); + searchRequest.sort(distanceSortBuilder.build()._toSortOptions()); + } else { + distanceSortBuilder.order(SortOrder.Asc); + searchRequest.sort(distanceSortBuilder.build()._toSortOptions()); + } + } else { + String name = getPropertyNameWithData(StringUtils.substringBeforeLast(sortByElement, ":"), itemType); + if (name != null) { + if (sortByElement.endsWith(":desc")) { + searchRequest.sort(s->s.field(f->f.field(name).order(SortOrder.Desc))); + } else { + searchRequest.sort(s->s.field(f->f.field(name).order(SortOrder.Asc))); + } + } else { + // in the case of no data existing for the property, we will not add the sorting to the request. + } + + } + } + } + searchRequest.version(true); + SearchResponse response = client.search(searchRequest.build(), clazz); + + if (size == -1) { + // Scroll until no more hits are returned + do { + HitsMetadata hitsMetadata = (HitsMetadata) response.hits(); + List> hits = hitsMetadata.hits(); + for (Hit searchHit : hits) { + // add hit to results + final T value = searchHit.source(); + setMetadata(value, searchHit.id(), searchHit.version(), searchHit.seqNo(), searchHit.primaryTerm(), searchHit.index()); + results.add(value); + } + + ScrollRequest searchScrollRequest = new ScrollRequest.Builder().scroll(s -> s.time(keepAlive)).scrollId(response.scrollId()).build(); + response = client.scroll(searchScrollRequest, clazz); + + // If we have no more hits, exit + } while (!response.hits().hits().isEmpty()); + SearchResponse finalResponse = response; + client.clearScroll(c->c.scrollId(finalResponse.scrollId())); + } else { + HitsMetadata searchHits = (HitsMetadata) response.hits(); + scrollIdentifier = response.scrollId(); + totalHits = searchHits.total().value(); + totalHitsRelation = getTotalHitsRelation(searchHits.total()); + if (scrollIdentifier != null && totalHits == 0) { + // we have no results, we must clear the scroll request immediately. + String finalScrollIdentifier = scrollIdentifier; + client.clearScroll(c->c.scrollId(finalScrollIdentifier)); + } + for (Hit searchHit : searchHits.hits()) { + final T value = searchHit.source(); + setMetadata(value, searchHit.id(), searchHit.version(), searchHit.seqNo(), searchHit.primaryTerm(), searchHit.index()); + results.add(value); + } + } + } catch (Exception t) { + throw new Exception("Error loading itemType=" + clazz.getName() + " query=" + query + " sortBy=" + sortBy, t); + } + + PartialList result = new PartialList<>(results, offset, size, totalHits, totalHitsRelation); + if (scrollIdentifier != null && totalHits != 0) { + result.setScrollIdentifier(scrollIdentifier); + result.setScrollTimeValidity(scrollTimeValidity); + } + return result; + } + }.catchingExecuteInClassLoader(true); + } + + private PartialList.Relation getTotalHitsRelation(TotalHits totalHits) { + return TotalHitsRelation.Gte.equals(totalHits.relation()) ? PartialList.Relation.GREATER_THAN_OR_EQUAL_TO : PartialList.Relation.EQUAL; + } + + @Override + public PartialList continueScrollQuery(final Class clazz, final String scrollIdentifier, final String scrollTimeValidity) { + return new InClassLoaderExecute>(metricsService, this.getClass().getName() + ".continueScrollQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + + @Override + protected PartialList execute(Object... args) throws Exception { + List results = new ArrayList<>(); + long totalHits = 0; + try { + String keepAlive = scrollTimeValidity != null ? scrollTimeValidity : "10m"; + + SearchResponse response = client.scroll(s->s.scrollId(scrollIdentifier).scroll(t->t.time(keepAlive)), clazz); + + if (response.hits().hits().isEmpty()) { + client.clearScroll(c->c.scrollId(response.scrollId())); + } else { + for (Hit searchHit : (List>) response.hits().hits()) { + // add hit to results + final T value = searchHit.source(); + setMetadata(value, searchHit.id(), searchHit.version(), searchHit.seqNo(), searchHit.primaryTerm(), searchHit.index()); + results.add(value); + } + } + PartialList result = new PartialList(results, 0, response.hits().hits().size(), response.hits().total().value(), getTotalHitsRelation(response.hits().total())); + if (scrollIdentifier != null) { + result.setScrollIdentifier(scrollIdentifier); + result.setScrollTimeValidity(scrollTimeValidity); + } + return result; + } catch (Exception t) { + throw new Exception("Error continuing scrolling query for itemType=" + clazz.getName() + " scrollIdentifier=" + scrollIdentifier + " scrollTimeValidity=" + scrollTimeValidity, t); + } + } + }.catchingExecuteInClassLoader(true); + } + + @Override + public PartialList continueCustomItemScrollQuery(final String customItemType, final String scrollIdentifier, final String scrollTimeValidity) { + return new InClassLoaderExecute>(metricsService, this.getClass().getName() + ".continueScrollQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + + @Override + protected PartialList execute(Object... args) throws Exception { + List results = new ArrayList<>(); + long totalHits = 0; + try { + String keepAlive = scrollTimeValidity != null ? scrollTimeValidity : "10m"; + + SearchResponse response = client.scroll(s -> s.scrollId(scrollIdentifier).scroll(t -> t.time(keepAlive)), CustomItem.class); + + if (response.hits().hits().isEmpty()) { + client.clearScroll(c -> c.scrollId(response.scrollId())); + } else { + for (Hit searchHit : (List>) response.hits().hits()) { + // add hit to results + final CustomItem value = searchHit.source(); + setMetadata(value, searchHit.id(), searchHit.version(), searchHit.seqNo(), searchHit.primaryTerm(), searchHit.index()); + results.add(value); + } + } + PartialList result = new PartialList(results, 0, response.hits().hits().size(), response.hits().total().value(), getTotalHitsRelation(response.hits().total())); + if (scrollIdentifier != null) { + result.setScrollIdentifier(scrollIdentifier); + result.setScrollTimeValidity(scrollTimeValidity); + } + return result; + } catch (Exception t) { + throw new Exception("Error continuing scrolling query for itemType=" + customItemType + " scrollIdentifier=" + scrollIdentifier + " scrollTimeValidity=" + scrollTimeValidity, t); + } + } + }.catchingExecuteInClassLoader(true); + } + + /** + * @deprecated As of version 1.3.0-incubating, use {@link #aggregateWithOptimizedQuery(Condition, BaseAggregate, String)} instead + */ + @Deprecated + @Override + public Map aggregateQuery(Condition filter, BaseAggregate aggregate, String itemType) { + return aggregateQuery(filter, aggregate, itemType, false, aggregateQueryBucketSize); + } + + @Override + public Map aggregateWithOptimizedQuery(Condition filter, BaseAggregate aggregate, String itemType) { + return aggregateQuery(filter, aggregate, itemType, true, aggregateQueryBucketSize); + } + + @Override + public Map aggregateWithOptimizedQuery(Condition filter, BaseAggregate aggregate, String itemType, int size) { + return aggregateQuery(filter, aggregate, itemType, true, size); + } + + private Map aggregateQuery(final Condition filter, final BaseAggregate aggregate, final String itemType, + final boolean optimizedQuery, int queryBucketSize) { + return new InClassLoaderExecute>(metricsService, this.getClass().getName() + ".aggregateQuery", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + + @Override + protected Map execute(Object... args) throws IOException { + Map results = new LinkedHashMap<>(); + + SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder().index(getIndexNameForQuery(itemType)); + searchRequestBuilder.size(0); + Query matchAll = Query.of(q->q.matchAll(m->m)); + boolean isItemTypeSharingIndex = isItemTypeSharingIndex(itemType); + searchRequestBuilder.query(isItemTypeSharingIndex ? getItemTypeQueryBuilder(itemType) : matchAll); + Map lastAggregation = new LinkedHashMap<>(); + + if (aggregate != null) { + Aggregation.Builder bucketsAggregationBuilder = new Aggregation.Builder(); + Aggregation.Builder.ContainerBuilder bucketsContainerBuilder = null; + String fieldName = aggregate.getField(); + if (aggregate instanceof DateAggregate) { + DateAggregate dateAggregate = (DateAggregate) aggregate; + DateHistogramAggregation.Builder dateHistogramBuilder = new DateHistogramAggregation.Builder() + .field(fieldName) + .calendarInterval(CalendarInterval.valueOf(dateAggregate.getInterval())); + if (dateAggregate.getFormat() != null) { + dateHistogramBuilder.format(dateAggregate.getFormat()); + } + bucketsContainerBuilder = bucketsAggregationBuilder.dateHistogram(dateHistogramBuilder.build()); + } else if (aggregate instanceof NumericRangeAggregate) { + RangeAggregation.Builder rangeBuilder = new RangeAggregation.Builder() + .field(fieldName); + for (NumericRange range : ((NumericRangeAggregate) aggregate).getRanges()) { + if (range != null) { + if (range.getFrom() != null && range.getTo() != null) { + rangeBuilder.ranges(r -> r.key(range.getKey()) + .from(range.getFrom().toString()) + .to(range.getTo().toString())); + } else if (range.getFrom() != null) { + rangeBuilder.ranges(r -> r.key(range.getKey()) + .from(range.getFrom().toString())); + } else if (range.getTo() != null) { + rangeBuilder.ranges(r -> r.key(range.getKey()) + .to(range.getTo().toString())); + } + } + } + bucketsContainerBuilder = bucketsAggregationBuilder.range(rangeBuilder.build()); + } else if (aggregate instanceof DateRangeAggregate) { + DateRangeAggregate dateRangeAggregate = (DateRangeAggregate) aggregate; + DateRangeAggregation.Builder rangeBuilder = new DateRangeAggregation.Builder() + .field(fieldName); + if (dateRangeAggregate.getFormat() != null) { + rangeBuilder.format(dateRangeAggregate.getFormat()); + } + for (DateRange range : dateRangeAggregate.getDateRanges()) { + if (range != null) { + rangeBuilder.ranges(r -> r.key(range.getKey()) + .from(f -> f.expr(range.getFrom() != null ? range.getFrom().toString() : null)) + .to(t -> t.expr(range.getTo() != null ? range.getTo().toString() : null))); + } + } + bucketsContainerBuilder = bucketsAggregationBuilder.dateRange(rangeBuilder.build()); + } else if (aggregate instanceof IpRangeAggregate) { + IpRangeAggregate ipRangeAggregate = (IpRangeAggregate) aggregate; + IpRangeAggregation.Builder rangeBuilder = new IpRangeAggregation.Builder() + .field(fieldName); + for (IpRange range : ipRangeAggregate.getRanges()) { + if (range != null) { + rangeBuilder.ranges(r -> r.mask(range.getKey()).from(range.getFrom()).to(range.getTo())); + } + } + bucketsContainerBuilder = bucketsAggregationBuilder.ipRange(rangeBuilder.build()); + } else { + fieldName = getPropertyNameWithData(fieldName, itemType); + //default + if (fieldName != null) { + TermsAggregation.Builder termsBuilder = new TermsAggregation.Builder() + .field(fieldName) + .size(queryBucketSize); + if (aggregate instanceof TermsAggregate) { + TermsAggregate termsAggregate = (TermsAggregate) aggregate; + if (termsAggregate.getPartition() > -1 && termsAggregate.getNumPartitions() > -1) { + termsBuilder.include(i->i.partition(p->p.partition(termsAggregate.getPartition()).numPartitions(termsAggregate.getNumPartitions()))); + } + } + bucketsContainerBuilder = bucketsAggregationBuilder.terms(termsBuilder.build()); + } else { + // field name could be null if no existing data exists + } + } + if (bucketsAggregationBuilder != null) { + Aggregation.Builder missingAggregationBuilder = new Aggregation.Builder(); + MissingAggregation.Builder missingBuilder = new MissingAggregation.Builder().field(fieldName); + Aggregation.Builder.ContainerBuilder missingContainerBuilder = missingAggregationBuilder.missing(missingBuilder.build()); + for (Map.Entry aggregationBuilder : lastAggregation.entrySet()) { + bucketsContainerBuilder.aggregations(aggregationBuilder.getKey(), aggregationBuilder.getValue().build()); + missingContainerBuilder.aggregations(aggregationBuilder.getKey(), aggregationBuilder.getValue().build()); + } + lastAggregation = Map.of("buckets", bucketsContainerBuilder, "missing", missingContainerBuilder); + } + } + + // If the request is optimized then we don't need a global aggregation which is very slow and we can put the query with a + // filter on range items in the query block so we don't retrieve all the document before filtering the whole + if (optimizedQuery) { + for (Map.Entry aggregationBuilder : lastAggregation.entrySet()) { + searchRequestBuilder.aggregations(aggregationBuilder.getKey(), aggregationBuilder.getValue().build()); + } + + if (filter != null) { + searchRequestBuilder.query(wrapWithItemTypeQuery(itemType, conditionOSQueryBuilderDispatcher.buildFilter(filter))); + } + } else { + if (filter != null) { + Aggregation.Builder.ContainerBuilder filterAggregationContainerBuilder = new Aggregation.Builder().filter(wrapWithItemTypeQuery(itemType, conditionOSQueryBuilderDispatcher.buildFilter(filter))); + for (Map.Entry aggregationBuilder : lastAggregation.entrySet()) { + filterAggregationContainerBuilder.aggregations(aggregationBuilder.getKey(), aggregationBuilder.getValue().build()); + } + lastAggregation = Map.of("buckets", filterAggregationContainerBuilder); + } + + Aggregation.Builder.ContainerBuilder globalAggregationContainerBuilder = new Aggregation.Builder().global(g -> g.name("global")); + for (Map.Entry aggregationBuilder : lastAggregation.entrySet()) { + globalAggregationContainerBuilder.aggregations(aggregationBuilder.getKey(), aggregationBuilder.getValue().build()); + } + + searchRequestBuilder.aggregations("buckets", globalAggregationContainerBuilder.build()); + } + + /* + @TODO can we implement this ? + RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder(); + + if (aggQueryMaxResponseSizeHttp != null) { + builder.setHttpAsyncResponseConsumerFactory( + new HttpAsyncResponseConsumerFactory + .HeapBufferedResponseConsumerFactory(aggQueryMaxResponseSizeHttp)); + } + + */ + + SearchResponse response = client.search(searchRequestBuilder.build(), Item.class); + Map aggregates = response.aggregations(); + + + if (aggregates != null) { + if (optimizedQuery) { + if (response.hits() != null) { + results.put("_filtered", response.hits().total().value()); + } + } else { + GlobalAggregate globalAgg = aggregates.get("global").global(); + results.put("_all", globalAgg.docCount()); + aggregates = globalAgg.aggregations(); + + if (aggregates.get("filter") != null) { + FilterAggregate filterAgg = aggregates.get("filter").filter(); + results.put("_filtered", filterAgg.docCount()); + aggregates = filterAgg.aggregations(); + } + } + if (aggregates.get("buckets") != null) { + + if (aggQueryThrowOnMissingDocs) { + if (aggregates.get("buckets").isSterms()) { + StringTermsAggregate terms = aggregates.get("buckets").sterms(); + if (terms.docCountErrorUpperBound() > 0 || terms.sumOtherDocCount() > 0) { + throw new UnsupportedOperationException("Some docs are missing in aggregation query. docCountError is:" + + terms.docCountErrorUpperBound() + " sumOfOtherDocCounts:" + terms.sumOtherDocCount()); + } + } + } + + long totalDocCount = 0; + Aggregate bucketsAggregate = aggregates.get("buckets"); + if (bucketsAggregate.isSterms()) { + for (StringTermsBucket bucket : bucketsAggregate.sterms().buckets().array()) { + results.put(bucket.key(), bucket.docCount()); + totalDocCount += bucket.docCount(); + } + } + MissingAggregate missing = aggregates.get("missing").missing(); + if (missing.docCount() > 0) { + results.put("_missing", missing.docCount()); + totalDocCount += missing.docCount(); + } + if (response.hits() != null && TotalHitsRelation.Gte.equals(response.hits().total().relation())) { + results.put("_filtered", totalDocCount); + } + } + } + return results; + } + }.catchingExecuteInClassLoader(true); + } + + private String[] getRouting(String fieldName, String[] fieldValues, Class clazz) { + String itemType = Item.getItemType(clazz); + String[] routing = null; + if (routingByType.containsKey(itemType) && routingByType.get(itemType).equals(fieldName)) { + routing = fieldValues; + } + return routing; + } + + @Override + public void refresh() { + new InClassLoaderExecute(metricsService, this.getClass().getName() + ".refresh", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) { + try { + client.indices().refresh(r->r); + } catch (IOException e) { + e.printStackTrace();//TODO manage ES7 + } + return true; + } + }.catchingExecuteInClassLoader(true); + } + + @Override + public void refreshIndex(Class clazz, Date dateHint) { + new InClassLoaderExecute(metricsService, this.getClass().getName() + ".refreshIndex", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) { + try { + String itemType = Item.getItemType(clazz); + String index = getIndex(itemType); + client.indices().refresh(r->r.index(index)); + } catch (IOException e) { + e.printStackTrace();//TODO manage ES7 + } + return true; + } + }.catchingExecuteInClassLoader(true); + } + + + @Override + public void purge(final Date date) { + // nothing, this method is deprecated since 2.2.0 + } + + @Override + public void purgeTimeBasedItems(int existsNumberOfDays, Class clazz) { + new InClassLoaderExecute(metricsService, this.getClass().getName() + ".purgeTimeBasedItems", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + protected Boolean execute(Object... args) throws Exception { + String itemType = Item.getItemType(clazz); + + if (existsNumberOfDays > 0 && isItemTypeRollingOver(itemType)) { + // First we purge the documents + removeByQuery(Query.of(q->q.range(r->r.field("timeStamp").lte(JsonData.of("now-" + existsNumberOfDays + "d")))), clazz); + + // get count per index for those time based data + TreeMap countsPerIndex = new TreeMap<>(); + GetIndexResponse getIndexResponse = client.indices().get(g->g.index(getIndexNameForQuery(itemType))); + for (String index : getIndexResponse.result().keySet()) { + countsPerIndex.put(index, client.count(c->c.index(index)).count()); + } + + // Check for count=0 and remove them + if (!countsPerIndex.isEmpty()) { + // do not check the last index, because it's the one used to write documents + countsPerIndex.pollLastEntry(); + + for (Map.Entry indexCount : countsPerIndex.entrySet()) { + if (indexCount.getValue() == 0) { + client.indices().delete(d->d.index(indexCount.getKey())); + } + } + } + } + + return true; + } + }.catchingExecuteInClassLoader(true); + } + + @Override + public void purge(final String scope) { + LOGGER.debug("Purge scope {}", scope); + new InClassLoaderExecute(metricsService, this.getClass().getName() + ".purgeWithScope", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + @Override + protected Void execute(Object... args) throws IOException { + + SearchResponse response = client.search(s -> s + .query(q -> q + .term(t -> t + .field("scope") + .value(v -> v + .stringValue(scope) + ) + ) + ) + .size(100) + .scroll(scr -> scr + .time("1h") + ) + .index(getAllIndexForQuery()) + , Item.class); + + // Scroll until no more hits are returned + List bulkOperations = new ArrayList<>(); + while (true) { + + for (Hit hit : response.hits().hits()) { + // add hit to bulk delete + bulkOperations.add(BulkOperation.of(b -> b.delete(d->d.index(hit.index()).id(hit.id())))); + } + + SearchResponse finalResponse = response; + response = client.scroll(scr -> scr.scrollId(finalResponse.scrollId()).scroll(t -> t.time("1h")), Item.class); + + // If we have no more hits, exit + if (response.hits().hits().isEmpty()) { + SearchResponse clearfinalResponse = response; + client.clearScroll(c -> c.scrollId(clearfinalResponse.scrollId())); + break; + } + } + + // we're done with the scrolling, delete now + if (!bulkOperations.isEmpty()) { + final BulkResponse deleteResponse = client.bulk(b -> b.operations(bulkOperations)); + if (deleteResponse.errors()) { + // do something + LOGGER.warn("Couldn't delete from scope " + scope + ":\n{}", deleteResponse); + } + } + return null; + } + }.catchingExecuteInClassLoader(true); + } + + @Override + public Map getSingleValuesMetrics(final Condition condition, final String[] metrics, final String field, final String itemType) { + return new InClassLoaderExecute>(metricsService, this.getClass().getName() + ".getSingleValuesMetrics", this.bundleContext, this.fatalIllegalStateErrors, throwExceptions) { + + @Override + protected Map execute(Object... args) throws IOException { + Map results = new LinkedHashMap<>(); + + Aggregation.Builder.ContainerBuilder filterAggregationContainerBuilder = new Aggregation.Builder().filter(conditionOSQueryBuilderDispatcher.buildFilter(condition)); + + if (metrics != null) { + for (String metric : metrics) { + switch (metric) { + case "sum": + filterAggregationContainerBuilder.aggregations("sum", Aggregation.of(a -> a.sum(s -> s.field(field)))); + break; + case "avg": + filterAggregationContainerBuilder.aggregations("avg", Aggregation.of(a -> a.avg(s -> s.field(field)))); + break; + case "min": + filterAggregationContainerBuilder.aggregations("min", Aggregation.of(a -> a.min(s -> s.field(field)))); + break; + case "max": + filterAggregationContainerBuilder.aggregations("max", Aggregation.of(a -> a.max(s -> s.field(field)))); + break; + case "card": + filterAggregationContainerBuilder.aggregations("card", Aggregation.of(a -> a.cardinality(s -> s.field(field)))); + break; + case "count": + filterAggregationContainerBuilder.aggregations("count", Aggregation.of(a -> a.valueCount(s -> s.field(field)))); + break; + } + } + } + SearchResponse response = client.search(s -> s + .index(getIndexNameForQuery(itemType)) + .size(0) + .aggregations("metrics", filterAggregationContainerBuilder.build()) + .query(isItemTypeSharingIndex(itemType) ? getItemTypeQueryBuilder(itemType) : Query.of(q -> q.matchAll(i -> i))) + , Item.class + ); + + Map aggregations = response.aggregations(); + if (aggregations != null) { + FilterAggregate metricsResults = aggregations.get("metrics").filter(); + if (!metricsResults.aggregations().isEmpty()) { + for (Map.Entry aggregationEntry : metricsResults.aggregations().entrySet()) { + Aggregate aggregateValue = aggregationEntry.getValue(); + if (aggregateValue.isSum()) { + results.put("_" + aggregationEntry.getKey(), aggregateValue.sum().value()); + } else if (aggregateValue.isAvg()) { + results.put("_" + aggregationEntry.getKey(), aggregateValue.avg().value()); + } else if (aggregateValue.isMin()) { + results.put("_" + aggregationEntry.getKey(), aggregateValue.min().value()); + } else if (aggregateValue.isMax()) { + results.put("_" + aggregationEntry.getKey(), aggregateValue.max().value()); + } else if (aggregateValue.isCardinality()) { + results.put("_" + aggregationEntry.getKey(), new Double(aggregateValue.cardinality().value())); + } else if (aggregateValue.isValueCount()) { + results.put("_" + aggregationEntry.getKey(), aggregateValue.valueCount().value()); + } + } + } + } + return results; + } + }.catchingExecuteInClassLoader(true); + } + + + private String getConfig(Map settings, String key, + String defaultValue) { + if (settings != null && settings.get(key) != null) { + return settings.get(key); + } + return defaultValue; + } + + public abstract static class InClassLoaderExecute { + + private String timerName; + private MetricsService metricsService; + private BundleContext bundleContext; + private String[] fatalIllegalStateErrors; // Errors that if occur - stop the application + private boolean throwExceptions; + + public InClassLoaderExecute(MetricsService metricsService, String timerName, BundleContext bundleContext, String[] fatalIllegalStateErrors, boolean throwExceptions) { + this.timerName = timerName; + this.metricsService = metricsService; + this.bundleContext = bundleContext; + this.fatalIllegalStateErrors = fatalIllegalStateErrors; + this.throwExceptions = throwExceptions; + } + + protected abstract T execute(Object... args) throws Exception; + + public T executeInClassLoader(Object... args) throws Exception { + + long startTime = System.currentTimeMillis(); + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + try { + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + return execute(args); + } finally { + if (metricsService != null && metricsService.isActivated()) { + metricsService.updateTimer(timerName, startTime); + } + Thread.currentThread().setContextClassLoader(tccl); + } + } + + public T catchingExecuteInClassLoader(boolean logError, Object... args) { + try { + return executeInClassLoader(timerName, args); + } catch (Throwable t) { + Throwable tTemp = t; + // Go over the stack trace and check if there were any fatal state errors + while (tTemp != null) { + if (tTemp instanceof IllegalStateException && Arrays.stream(this.fatalIllegalStateErrors).anyMatch(tTemp.getMessage()::contains)) { + handleFatalStateError(); // Stop application + return null; + } + tTemp = tTemp.getCause(); + } + handleError(t, logError); + } + return null; + } + + private void handleError(Throwable t, boolean logError) { + if (logError) { + LOGGER.error("Error while executing in class loader", t); + } + if (throwExceptions) { + throw new RuntimeException(t); + } + } + + private void handleFatalStateError() { + LOGGER.error("Fatal state error occurred - stopping application"); + try { + this.bundleContext.getBundle(0).stop(); + } catch (Throwable tInner) { // Stopping system bundle failed - force exit + System.exit(-1); + } + } + } + + private String getAllIndexForQuery() { + return indexPrefix + "*"; + } + + private String getIndexNameForQuery(String itemType) { + return isItemTypeRollingOver(itemType) ? getRolloverIndexForQuery(itemType) : getIndex(itemType); + } + + private String getRolloverIndexForQuery(String itemType) { + return indexPrefix + "-" + itemType.toLowerCase() + "-*"; + } + + private String getIndex(String itemType) { + return (indexPrefix + "-" + getIndexNameForItemType(itemType)).toLowerCase(); + } + + private String getIndexNameForItemType(String itemType) { + return itemTypeIndexNameMap.getOrDefault(itemType, itemType); + } + + private String getDocumentIDForItemType(String itemId, String itemType) { + return systemItems.contains(itemType) ? (itemId + "_" + itemType.toLowerCase()) : itemId; + } + + private Query wrapWithItemTypeQuery(String itemType, Query originalQuery) { + if (isItemTypeSharingIndex(itemType)) { + return new Query.Builder().bool(bool -> bool.must(getItemTypeQueryBuilder(itemType)) + .must(originalQuery)).build(); + } + return originalQuery; + } + + private Query wrapWithItemsTypeQuery(String[] itemTypes, Query originalQuery) { + if (itemTypes.length == 1) { + return wrapWithItemTypeQuery(itemTypes[0], originalQuery); + } + + if (Arrays.stream(itemTypes).anyMatch(this::isItemTypeSharingIndex)) { + return Query.of(q -> q + .bool(b -> b + .must(originalQuery) + .filter(f -> f + .bool(b2 -> b2 + .minimumShouldMatch("1") + .should(Arrays + .stream(itemTypes) + .map(this::getItemTypeQueryBuilder) + .collect(Collectors.toList()) + ) + ) + ) + ) + ); + } + return originalQuery; + } + + private Query getItemTypeQueryBuilder(String itemType) { + return new Query.Builder().term(term -> term.field("itemType") + .value(value -> value.stringValue(ConditionContextHelper.foldToASCII(itemType)))) + .build(); + } + + private boolean isItemTypeSharingIndex(String itemType) { + return itemTypeIndexNameMap.containsKey(itemType); + } + + private boolean isItemTypeRollingOver(String itemType) { + return (rolloverIndices != null ? rolloverIndices : itemsMonthlyIndexed).contains(itemType); + } + + private Refresh getRefreshPolicy(String itemType) { + if (itemTypeToRefreshPolicy.containsKey(itemType)) { + return itemTypeToRefreshPolicy.get(itemType); + } + return Refresh.False; + } + + private void logMetadataItemOperation (String operation, Item item) { + if (item instanceof MetadataItem) { + LOGGER.info("Item of type {} with ID {} has been {}", item.getItemType(), item.getItemId(), operation); + } + } +} diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java new file mode 100644 index 000000000..c9012b207 --- /dev/null +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.persistence.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.opensearch.client.opensearch._types.query_dsl.Query; + +import java.util.Map; + +public interface ConditionOSQueryBuilder { + + Query buildQuery(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher); + + default long count(Condition condition, Map context, ConditionOSQueryBuilderDispatcher dispatcher) { + throw new UnsupportedOperationException(); + } +} diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java new file mode 100644 index 000000000..4f645c047 --- /dev/null +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java @@ -0,0 +1,131 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.persistence.opensearch.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.scripting.ScriptExecutor; +import org.opensearch.client.opensearch._types.query_dsl.Query; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ConditionOSQueryBuilderDispatcher { + private static final Logger LOGGER = LoggerFactory.getLogger(ConditionOSQueryBuilderDispatcher.class.getName()); + + private Map queryBuilders = new ConcurrentHashMap<>(); + private ScriptExecutor scriptExecutor; + + public ConditionOSQueryBuilderDispatcher() { + } + + public void setScriptExecutor(ScriptExecutor scriptExecutor) { + this.scriptExecutor = scriptExecutor; + } + + public void addQueryBuilder(String name, ConditionOSQueryBuilder evaluator) { + queryBuilders.put(name, evaluator); + } + + public void removeQueryBuilder(String name) { + queryBuilders.remove(name); + } + + + public String getQuery(Condition condition) { + return "{\"query\": " + getQueryBuilder(condition).toString() + "}"; + } + + public Query getQueryBuilder(Condition condition) { + return Query.of(q->q.bool(b->b.must(Query.of(q2 -> q2.matchAll(t -> t))).filter(buildFilter(condition)))); + } + + public Query buildFilter(Condition condition) { + return buildFilter(condition, new HashMap()); + } + + public Query buildFilter(Condition condition, Map context) { + if(condition == null || condition.getConditionType() == null) { + throw new IllegalArgumentException("Condition is null or doesn't have type, impossible to build filter"); + } + + String queryBuilderKey = condition.getConditionType().getQueryBuilder(); + if (queryBuilderKey == null && condition.getConditionType().getParentCondition() != null) { + context.putAll(condition.getParameterValues()); + return buildFilter(condition.getConditionType().getParentCondition(), context); + } + + if (queryBuilderKey == null) { + throw new UnsupportedOperationException("No query builder defined for : " + condition.getConditionTypeId()); + } + + if (queryBuilders.containsKey(queryBuilderKey)) { + ConditionOSQueryBuilder queryBuilder = queryBuilders.get(queryBuilderKey); + Condition contextualCondition = ConditionContextHelper.getContextualCondition(condition, context, scriptExecutor); + if (contextualCondition != null) { + return queryBuilder.buildQuery(contextualCondition, context, this); + } + } else { + // if no matching + LOGGER.warn("No matching query builder. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("No matching query builder for condition {} and context {}", condition, context); + } + } + + return Query.of(q -> q.matchAll(t->t)); + } + + public long count(Condition condition) { + return count(condition, new HashMap<>()); + } + + public long count(Condition condition, Map context) { + if(condition == null || condition.getConditionType() == null) { + throw new IllegalArgumentException("Condition is null or doesn't have type, impossible to build filter"); + } + + String queryBuilderKey = condition.getConditionType().getQueryBuilder(); + if (queryBuilderKey == null && condition.getConditionType().getParentCondition() != null) { + context.putAll(condition.getParameterValues()); + return count(condition.getConditionType().getParentCondition(), context); + } + + if (queryBuilderKey == null) { + throw new UnsupportedOperationException("No query builder defined for : " + condition.getConditionTypeId()); + } + + if (queryBuilders.containsKey(queryBuilderKey)) { + ConditionOSQueryBuilder queryBuilder = queryBuilders.get(queryBuilderKey); + Condition contextualCondition = ConditionContextHelper.getContextualCondition(condition, context, scriptExecutor); + if (contextualCondition != null) { + return queryBuilder.count(contextualCondition, context, this); + } + } + + // if no matching + LOGGER.warn("No matching query builder. See debug log level for more information"); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("No matching query builder for condition {} and context {}", condition, context); + } + throw new UnsupportedOperationException(); + } +} diff --git a/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/event.json b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/event.json new file mode 100644 index 000000000..a7dc14c8b --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/event.json @@ -0,0 +1,64 @@ +{ + "dynamic_templates": [ + { + "all": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "type": "text", + "analyzer": "folding", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + ], + "properties": { + "flattenedProperties": { + "type": "flat_object" + }, + "timeStamp": { + "type": "date" + }, + "target" : { + "properties" : { + "lastEventDate" : { + "type" : "date" + }, + "profile" : { + "properties" : { + "properties" : { + "properties" : { + "birthDate" : { + "type" : "date" + }, + "firstVisit" : { + "type" : "date" + }, + "lastVisit" : { + "type" : "date" + }, + "notificationRefreshDate" : { + "type" : "date" + }, + "previousVisit" : { + "type" : "date" + } + } + }, + "systemProperties" : { + "properties" : { + + } + } + } + } + } + } + } +} + diff --git a/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/personaSession.json b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/personaSession.json new file mode 100644 index 000000000..c635e0285 --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/personaSession.json @@ -0,0 +1,41 @@ +{ + "dynamic_templates": [ + { + "all": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "type": "text", + "analyzer": "folding", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + ], + "properties": { + "duration": { + "type": "long" + }, + "timeStamp": { + "type": "date" + }, + "lastEventDate": { + "type": "date" + }, + "properties": { + "properties": { + "location": { + "type": "geo_point" + } + } + }, + "size": { + "type": "long" + } + } +} \ No newline at end of file diff --git a/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profile.json b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profile.json new file mode 100644 index 000000000..81cc14d0f --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profile.json @@ -0,0 +1,54 @@ +{ + "dynamic_templates": [ + { + "all": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "type": "text", + "analyzer": "folding", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + ], + "properties": { + "properties": { + "properties": { + "age": { + "type": "long" + }, + "firstVisit": { + "type": "date" + }, + "lastVisit": { + "type": "date" + }, + "previousVisit": { + "type": "date" + }, + "nbOfVisits": { + "type": "long" + }, + "interests": { + "type": "nested" + } + } + }, + "consents": { + "properties": { + "statusDate": { + "type": "date" + }, + "revokeDate": { + "type": "date" + } + } + } + } +} diff --git a/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json new file mode 100644 index 000000000..6d2f54d7e --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/profileAlias.json @@ -0,0 +1,28 @@ +{ + "dynamic_templates": [ + { + "all": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "type": "text", + "analyzer": "folding", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + ], + "properties": { + "creationTime": { + "type": "date" + }, + "modifiedTime": { + "type": "date" + } + } +} diff --git a/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/session.json b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/session.json new file mode 100644 index 000000000..e28657c67 --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/session.json @@ -0,0 +1,73 @@ +{ + "dynamic_templates": [ + { + "all": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "type": "text", + "analyzer": "folding", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + ], + "properties": { + "duration": { + "type": "long" + }, + "lastEventDate": { + "type": "date" + }, + "profile" : { + "properties" : { + "properties" : { + "properties" : { + "age" : { + "type" : "long" + }, + "birthDate" : { + "type" : "date" + }, + "firstDate" : { + "type" : "date" + }, + "lastVisit" : { + "type" : "date" + }, + "previousVisit" : { + "type" : "date" + }, + "notificationsRefreshDate" : { + "type" : "date" + } + } + } + } + }, + "properties": { + "properties": { + "location": { + "type": "geo_point" + }, + "sessionAdminSubDiv1" : { + "type": "long" + }, + "sessionAdminSubDiv2" : { + "type": "long" + } + } + }, + "size": { + "type": "long" + }, + "timeStamp": { + "type": "date" + } + } +} diff --git a/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/systemItems.json b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/systemItems.json new file mode 100644 index 000000000..ca5a7a397 --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/META-INF/cxs/mappings/systemItems.json @@ -0,0 +1,141 @@ +{ + "dynamic_templates": [ + { + "all": { + "match": "*", + "match_mapping_type": "string", + "mapping": { + "type": "text", + "analyzer": "folding", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + ], + "properties": { + "cost": { + "type": "double" + }, + "startDate": { + "type": "date" + }, + "endDate": { + "type": "date" + }, + "metadata": { + "properties": { + "enabled": { + "type": "boolean" + }, + "hidden": { + "type": "boolean" + }, + "missingPlugins": { + "type": "boolean" + }, + "readOnly": { + "type": "boolean" + } + } + }, + "entryCondition": { + "type": "object", + "enabled": false + }, + "parentCondition": { + "type": "object", + "enabled": false + }, + "startEvent": { + "type": "object", + "enabled": false + }, + "targetEvent": { + "type": "object", + "enabled": false + }, + "eventDate": { + "type": "date" + }, + "multivalued": { + "type": "boolean" + }, + "numericRanges": { + "properties": { + "from": { + "type": "double" + }, + "to": { + "type": "double" + } + } + }, + "protected": { + "type": "boolean" + }, + "rank": { + "type": "double" + }, + "dateRanges": { + "properties": { + } + }, + "priority": { + "type": "long" + }, + "raiseEventOnlyOnceForProfile": { + "type": "boolean" + }, + "raiseEventOnlyOnceForSession": { + "type": "boolean" + }, + "raiseEventOnlyOnce": { + "type": "boolean" + }, + "condition": { + "type": "object", + "enabled": false + }, + "actions": { + "properties": { + "parameterValues": { + "type": "object", + "enabled": false + } + } + }, + "elements": { + "properties": { + "condition": { + "type": "object", + "enabled": false + } + } + }, + + "patchedItemId": { + "type": "text" + }, + "patchedItemType": { + "type": "text" + }, + "operation": { + "type": "text" + }, + "data": { + "type": "object", + "enabled": false + }, + "lastApplication": { + "type": "date" + }, + "schema": { + "type": "text" + } + } +} \ No newline at end of file diff --git a/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..2536f9e10 --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,179 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.unomi.persistence.spi.PersistenceService + org.osgi.framework.SynchronousBundleListener + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/persistence-opensearch/core/src/main/resources/log4j2.xml b/persistence-opensearch/core/src/main/resources/log4j2.xml new file mode 100644 index 000000000..3bf63c3f3 --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-opensearch/core/src/main/resources/org.apache.unomi.persistence.opensearch.cfg b/persistence-opensearch/core/src/main/resources/org.apache.unomi.persistence.opensearch.cfg new file mode 100644 index 000000000..e0bb5dc16 --- /dev/null +++ b/persistence-opensearch/core/src/main/resources/org.apache.unomi.persistence.opensearch.cfg @@ -0,0 +1,116 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cluster.name=${org.apache.unomi.opensearch.cluster.name:-opensearch-cluster} +# The openSearchAddresses may be a comma seperated list of host names and ports such as +# hostA:9200,hostB:9200 +# Note: the port number must be repeated for each host. +openSearchAddresses=${org.apache.unomi.opensearch.addresses:-localhost:9200} +fatalIllegalStateErrors=${org.apache.unomi.opensearch.fatalIllegalStateErrors:-} +index.prefix=${org.apache.unomi.opensearch.index.prefix:-context} + +# Deprecated properties. Please use rollover corresponding properties +monthlyIndex.numberOfShards=${org.apache.unomi.opensearch.monthlyIndex.nbShards:-5} +monthlyIndex.numberOfReplicas=${org.apache.unomi.opensearch.monthlyIndex.nbReplicas:-0} +monthlyIndex.indexMappingTotalFieldsLimit=${org.apache.unomi.opensearch.monthlyIndex.indexMappingTotalFieldsLimit:-1000} +monthlyIndex.indexMaxDocValueFieldsSearch=${org.apache.unomi.opensearch.monthlyIndex.indexMaxDocValueFieldsSearch:-1000} +monthlyIndex.itemsMonthlyIndexedOverride=${org.apache.unomi.opensearch.monthlyIndex.itemsMonthlyIndexedOverride:-event,session} +# New properties for index rotation: +rollover.numberOfShards=${org.apache.unomi.opensearch.rollover.nbShards} +rollover.numberOfReplicas=${org.apache.unomi.opensearch.rollover.nbReplicas} +rollover.indexMappingTotalFieldsLimit=${org.apache.unomi.opensearch.rollover.indexMappingTotalFieldsLimit} +rollover.indexMaxDocValueFieldsSearch=${org.apache.unomi.opensearch.rollover.indexMaxDocValueFieldsSearch} +rollover.indices=${org.apache.unomi.opensearch.rollover.indices} + +numberOfShards=${org.apache.unomi.opensearch.defaultIndex.nbShards:-5} +numberOfReplicas=${org.apache.unomi.opensearch.defaultIndex.nbReplicas:-0} +indexMappingTotalFieldsLimit=${org.apache.unomi.opensearch.defaultIndex.indexMappingTotalFieldsLimit:-1000} +indexMaxDocValueFieldsSearch=${org.apache.unomi.opensearch.defaultIndex.indexMaxDocValueFieldsSearch:-1000} +defaultQueryLimit=${org.apache.unomi.opensearch.defaultQueryLimit:-10} + +# Rollover amd index configuration for event and session indices, values are cumulative +# See https://www.elastic.co/guide/en/opensearch/reference/7.17/ilm-rollover.html for option details. +rollover.maxSize=${org.apache.unomi.opensearch.rollover.maxSize:-30gb} +rollover.maxAge=${org.apache.unomi.opensearch.rollover.maxAge} +rollover.maxDocs=${org.apache.unomi.opensearch.rollover.maxDocs} + +# The following settings control the behavior of the BulkProcessor API. You can find more information about these +# settings and their behavior here : https://www.elastic.co/guide/en/opensearch/client/java-api/2.4/java-docs-bulk-processor.html +# The values used here are the default values of the API +bulkProcessor.concurrentRequests=${org.apache.unomi.opensearch.bulkProcessor.concurrentRequests:-1} +bulkProcessor.bulkActions=${org.apache.unomi.opensearch.bulkProcessor.bulkActions:-1000} +bulkProcessor.bulkSize=${org.apache.unomi.opensearch.bulkProcessor.bulkSize:-5MB} +bulkProcessor.flushInterval=${org.apache.unomi.opensearch.bulkProcessor.flushInterval:-5s} +bulkProcessor.backoffPolicy=${org.apache.unomi.opensearch.bulkProcessor.backoffPolicy:-exponential} + +# The following settings are used to perform version checks on the connected OpenSearch cluster, to make sure that +# appropriate versions are used. The check is performed like this : +# for each node in the OpenSearch cluster: +# minimalOpenSearchVersion <= OpenSearch node version < maximalOpenSearchVersion +minimalOpenSearchVersion=2.0.0 +maximalOpenSearchVersion=3.0.0 + +# The following setting is used to set the aggregate query bucket size +aggregateQueryBucketSize=${org.apache.unomi.opensearch.aggregateQueryBucketSize:-5000} + +# Maximum size allowed for an elastic "ids" query +maximumIdsQueryCount=${org.apache.unomi.opensearch.maximumIdsQueryCount:-5000} + +# Disable partitions on aggregation queries for past events. +pastEventsDisablePartitions=${org.apache.unomi.opensearch.pastEventsDisablePartitions:-false} + +# Defines the socket timeout (SO_TIMEOUT) in milliseconds, which is the timeout for waiting for data or, put differently, a maximum period inactivity between two consecutive data packets). +# A timeout value of zero is interpreted as an infinite timeout. A negative value is interpreted as undefined (system default). +# Default: -1 +clientSocketTimeout=${org.apache.unomi.opensearch.clientSocketTimeout:--1} + +# Defines the waiting for task completion timeout in milliseconds. +# Some operations like update_by_query and delete_by_query are delegated to OpenSearch using tasks +# For consistency the thread that trigger one of those operations will wait for the task to be completed on OpenSearch side. +# This timeout configuration is here to ensure not blocking the thread infinitely, in case of very long running tasks. +# A timeout value of zero or negative is interpreted as an infinite timeout. +# Default: 3600000 (1 hour) +taskWaitingTimeout=${org.apache.unomi.opensearch.taskWaitingTimeout:-3600000} + +# Defines the polling interval in milliseconds, which is used to check if task is completed on OpenSearch side +# Default: 1000 (1 second) +taskWaitingPollingInterval=${org.apache.unomi.opensearch.taskWaitingPollingInterval:-1000} + +# refresh policy per item type in Json. +# Valid values are WAIT_UNTIL/IMMEDIATE/NONE. The default refresh policy is NONE. +# Example: "{"event":"WAIT_UNTIL","rule":"NONE"} +itemTypeToRefreshPolicy=${org.apache.unomi.opensearch.itemTypeToRefreshPolicy:-} + +# Retrun error in docs are missing in es aggregation calculation +aggQueryThrowOnMissingDocs=${org.apache.unomi.opensearch.aggQueryThrowOnMissingDocs:-false} + +aggQueryMaxResponseSizeHttp=${org.apache.unomi.opensearch.aggQueryMaxResponseSizeHttp:-} + +# Authentication +username=${org.apache.unomi.opensearch.username:-} +password=${org.apache.unomi.opensearch.password:-} +sslEnable=${org.apache.unomi.opensearch.sslEnable:-true} +sslTrustAllCertificates=${org.apache.unomi.opensearch.sslTrustAllCertificates:-true} + +# Errors +throwExceptions=${org.apache.unomi.opensearch.throwExceptions:-false} + +alwaysOverwrite=${org.apache.unomi.opensearch.alwaysOverwrite:-true} +useBatchingForUpdate=${org.apache.unomi.opensearch.useBatchingForUpdate:-true} + +# ES logging +logLevelRestClient=${org.apache.unomi.opensearch.logLevelRestClient:-ERROR} diff --git a/persistence-opensearch/pom.xml b/persistence-opensearch/pom.xml new file mode 100644 index 000000000..1f84083e0 --- /dev/null +++ b/persistence-opensearch/pom.xml @@ -0,0 +1,56 @@ + + + + + 4.0.0 + + + org.apache.unomi + unomi-root + 2.6.0-SNAPSHOT + + + unomi-persistence-opensearch + Apache Unomi :: Persistence :: OpenSearch + OpenSearch persistence implementation for the Apache Unomi Context Server + pom + + + core + conditions + + + + + + org.apache.felix + maven-bundle-plugin + true + + + *;scope=compile|runtime + + com.conversantmedia.util.concurrent;resolution:=optional, + * + + + + + + + diff --git a/persistence-spi/pom.xml b/persistence-spi/pom.xml index b1e348e96..c8f17a510 100644 --- a/persistence-spi/pom.xml +++ b/persistence-spi/pom.xml @@ -52,10 +52,45 @@ jackson-module-jaxb-annotations provided + + commons-collections + commons-collections + commons-beanutils commons-beanutils + + org.apache.commons + commons-lang3 + + + commons-io + commons-io + + + + org.apache.unomi + unomi-metrics + ${project.version} + provided + + + org.apache.unomi + unomi-scripting + ${project.version} + provided + + + org.apache.lucene + lucene-core + 8.11.3 + + + org.apache.lucene + lucene-analyzers-common + 8.11.3 + @@ -72,4 +107,92 @@ + + + + org.apache.felix + maven-bundle-plugin + true + + + *;scope=compile|runtime + + android.os;resolution:=optional, + com.conversantmedia.util.concurrent;resolution:=optional, + com.fasterxml.jackson.dataformat.xml;resolution:=optional, + com.fasterxml.jackson.dataformat.xml.annotation;resolution:=optional, + com.fasterxml.jackson.dataformat.xml.util;resolution:=optional, + com.google.appengine.api;resolution:=optional, + com.google.appengine.api.utils;resolution:=optional, + com.google.apphosting.api;resolution:=optional, + com.google.errorprone.annotations.concurrent;resolution:=optional, + com.google.errorprone.annotations;resolution:=optional, + com.google.common.util.concurrent.internal;resolution:=optional, + com.lmax.disruptor;resolution:=optional, + com.lmax.disruptor.dsl;resolution:=optional, + com.sun.management;resolution:=optional, + javax.activation;version="[1.2,2)", + javax.annotation.processing;resolution:=optional, + javax.annotation;resolution:=optional, + javax.annotation.meta;resolution:=optional, + javax.crypto;resolution:=optional, + javax.crypto.spec;resolution:=optional, + javax.jms;resolution:=optional, + javax.lang.model;resolution:=optional, + javax.lang.model.element;resolution:=optional, + javax.lang.model.util;resolution:=optional, + javax.mail;resolution:=optional, + javax.mail.internet;resolution:=optional, + javax.mail.util;resolution:=optional, + javax.management;resolution:=optional, + javax.naming;resolution:=optional, + javax.net;resolution:=optional, + javax.net.ssl;resolution:=optional, + javax.script;resolution:=optional, + javax.sql;resolution:=optional, + javax.tools;resolution:=optional, + javax.xml.parsers;resolution:=optional, + javax.xml.stream;resolution:=optional, + javax.xml.transform;resolution:=optional, + javax.xml.transform.stream;resolution:=optional, + javax.xml.validation;resolution:=optional, + org.apache.commons.compress.compressors;resolution:=optional, + org.apache.commons.compress.utils;resolution:=optional, + org.apache.commons.csv;resolution:=optional, + org.apache.commons.logging;resolution:=optional, + org.apache.kafka.clients.producer;resolution:=optional, + org.apache.logging.log4j;resolution:=optional, + org.apache.logging.log4j.message;resolution:=optional, + org.apache.logging.log4j.spi;resolution:=optional, + org.apache.logging.log4j.status;resolution:=optional, + org.apache.logging.log4j.util;resolution:=optional, + org.apache.lucene.analysis;resolution:=optional, + org.apache.lucene.analysis.tokenattributes;resolution:=optional, + org.apache.lucene.codecs;resolution:=optional, + org.apache.lucene.document;resolution:=optional, + org.apache.lucene.index;resolution:=optional, + org.apache.lucene.search;resolution:=optional, + org.apache.lucene.store;resolution:=optional, + org.apache.lucene.util;resolution:=optional, + org.apache.lucene.util.automaton;resolution:=optional, + org.apache.lucene.util.fst;resolution:=optional, + org.codehaus.stax2;resolution:=optional, + org.fusesource.jansi;resolution:=optional, + org.jctools.queues;resolution:=optional, + org.osgi.framework;resolution:=optional, + org.osgi.framework.wiring;resolution:=optional, + org.w3c.dom;resolution:=optional, + org.xml.sax;resolution:=optional, + org.xml.sax.helpers;resolution:=optional, + org.zeromq;resolution:=optional, + sun.misc;resolution:=optional, + sun.nio.ch;resolution:=optional, + * + + + + + + + diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionContextHelper.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionContextHelper.java similarity index 90% rename from persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionContextHelper.java rename to persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionContextHelper.java index 7a590cf84..1097dedfb 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionContextHelper.java +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionContextHelper.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.unomi.persistence.elasticsearch.conditions; +package org.apache.unomi.persistence.spi.conditions; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.core.util.IOUtils; import org.apache.lucene.analysis.charfilter.MappingCharFilterFactory; import org.apache.lucene.analysis.util.ClasspathResourceLoader; import org.apache.unomi.api.conditions.Condition; @@ -33,7 +33,7 @@ import java.util.stream.Collectors; public class ConditionContextHelper { - private static final Logger logger = LoggerFactory.getLogger(ConditionContextHelper.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ConditionContextHelper.class); private static MappingCharFilterFactory mappingCharFilterFactory; static { @@ -132,7 +132,7 @@ public static String foldToASCII(String s) { try (StringReader stringReader = new StringReader(s); Reader foldedStringReader = mappingCharFilterFactory.create(stringReader)) { return IOUtils.toString(foldedStringReader); } catch (IOException e) { - logger.error("Error folding to ASCII string " + s, e); + LOGGER.error("Error folding to ASCII string " + s, e); } } return null; @@ -140,12 +140,14 @@ public static String foldToASCII(String s) { public static Collection foldToASCII(Collection s) { if (s != null) { - return s.stream().map(o -> { - if (o instanceof String) { - return (T) ConditionContextHelper.foldToASCII((String) o); - } - return o; - }).collect(Collectors.toCollection(ArrayList::new)); + return s.stream() + .map(o -> { + if (o instanceof String) { + return (T) ConditionContextHelper.foldToASCII((String) o); + } + return o; + }) + .collect(Collectors.toList()); } return null; } diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluator.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluator.java similarity index 94% rename from persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluator.java rename to persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluator.java index 86f8f52d6..97af4ed97 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluator.java +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluator.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.persistence.elasticsearch.conditions; +package org.apache.unomi.persistence.spi.conditions; import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcher.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcher.java new file mode 100644 index 000000000..2f23741c1 --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcher.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions; + +import org.apache.unomi.api.Item; +import org.apache.unomi.api.conditions.Condition; + +import java.util.Map; + +public interface ConditionEvaluatorDispatcher { + void addEvaluator(String name, ConditionEvaluator evaluator); + + void removeEvaluator(String name); + + boolean eval(Condition condition, Item item); + + boolean eval(Condition condition, Item item, Map context); +} diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluatorDispatcher.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcherImpl.java similarity index 90% rename from persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluatorDispatcher.java rename to persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcherImpl.java index cd0bb35f7..edfbb5898 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionEvaluatorDispatcher.java +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/ConditionEvaluatorDispatcherImpl.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.persistence.elasticsearch.conditions; +package org.apache.unomi.persistence.spi.conditions; import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; @@ -32,8 +32,8 @@ /** * Entry point for condition evaluation. Will dispatch to all evaluators. */ -public class ConditionEvaluatorDispatcher { - private static final Logger logger = LoggerFactory.getLogger(ConditionEvaluatorDispatcher.class.getName()); +public class ConditionEvaluatorDispatcherImpl implements ConditionEvaluatorDispatcher { + private static final Logger LOGGER = LoggerFactory.getLogger(ConditionEvaluatorDispatcherImpl.class.getName()); private Map evaluators = new ConcurrentHashMap<>(); @@ -48,18 +48,22 @@ public void setScriptExecutor(ScriptExecutor scriptExecutor) { this.scriptExecutor = scriptExecutor; } + @Override public void addEvaluator(String name, ConditionEvaluator evaluator) { evaluators.put(name, evaluator); } + @Override public void removeEvaluator(String name) { evaluators.remove(name); } + @Override public boolean eval(Condition condition, Item item) { return eval(condition, item, new HashMap()); } + @Override public boolean eval(Condition condition, Item item, Map context) { String conditionEvaluatorKey = condition.getConditionType().getConditionEvaluator(); if (condition.getConditionType().getParentCondition() != null) { @@ -87,7 +91,7 @@ public Boolean execute(Object... args) throws Exception { } }.runWithTimer(); } catch (Exception e) { - logger.error("Error executing condition evaluator with key=" + conditionEvaluatorKey, e); + LOGGER.error("Error executing condition evaluator with key=" + conditionEvaluatorKey, e); } } diff --git a/persistence-spi/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-spi/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..e5da9cece --- /dev/null +++ b/persistence-spi/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher + + + + diff --git a/persistence-spi/src/main/resources/mapping-FoldToASCII.txt b/persistence-spi/src/main/resources/mapping-FoldToASCII.txt new file mode 100644 index 000000000..9a84b6eac --- /dev/null +++ b/persistence-spi/src/main/resources/mapping-FoldToASCII.txt @@ -0,0 +1,3813 @@ +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This map converts alphabetic, numeric, and symbolic Unicode characters +# which are not in the first 127 ASCII characters (the "Basic Latin" Unicode +# block) into their ASCII equivalents, if one exists. +# +# Characters from the following Unicode blocks are converted; however, only +# those characters with reasonable ASCII alternatives are converted: +# +# - C1 Controls and Latin-1 Supplement: http://www.unicode.org/charts/PDF/U0080.pdf +# - Latin Extended-A: http://www.unicode.org/charts/PDF/U0100.pdf +# - Latin Extended-B: http://www.unicode.org/charts/PDF/U0180.pdf +# - Latin Extended Additional: http://www.unicode.org/charts/PDF/U1E00.pdf +# - Latin Extended-C: http://www.unicode.org/charts/PDF/U2C60.pdf +# - Latin Extended-D: http://www.unicode.org/charts/PDF/UA720.pdf +# - IPA Extensions: http://www.unicode.org/charts/PDF/U0250.pdf +# - Phonetic Extensions: http://www.unicode.org/charts/PDF/U1D00.pdf +# - Phonetic Extensions Supplement: http://www.unicode.org/charts/PDF/U1D80.pdf +# - General Punctuation: http://www.unicode.org/charts/PDF/U2000.pdf +# - Superscripts and Subscripts: http://www.unicode.org/charts/PDF/U2070.pdf +# - Enclosed Alphanumerics: http://www.unicode.org/charts/PDF/U2460.pdf +# - Dingbats: http://www.unicode.org/charts/PDF/U2700.pdf +# - Supplemental Punctuation: http://www.unicode.org/charts/PDF/U2E00.pdf +# - Alphabetic Presentation Forms: http://www.unicode.org/charts/PDF/UFB00.pdf +# - Halfwidth and Fullwidth Forms: http://www.unicode.org/charts/PDF/UFF00.pdf +# +# See: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode +# +# The set of character conversions supported by this map is a superset of +# those supported by the map represented by mapping-ISOLatin1Accent.txt. +# +# See the bottom of this file for the Perl script used to generate the contents +# of this file (without this header) from ASCIIFoldingFilter.java. + + +# Syntax: +# "source" => "target" +# "source".length() > 0 (source cannot be empty.) +# "target".length() >= 0 (target can be empty.) + + +# À [LATIN CAPITAL LETTER A WITH GRAVE] +"\u00C0" => "A" + +# Á [LATIN CAPITAL LETTER A WITH ACUTE] +"\u00C1" => "A" + +#  [LATIN CAPITAL LETTER A WITH CIRCUMFLEX] +"\u00C2" => "A" + +# à [LATIN CAPITAL LETTER A WITH TILDE] +"\u00C3" => "A" + +# Ä [LATIN CAPITAL LETTER A WITH DIAERESIS] +"\u00C4" => "A" + +# Å [LATIN CAPITAL LETTER A WITH RING ABOVE] +"\u00C5" => "A" + +# Ā [LATIN CAPITAL LETTER A WITH MACRON] +"\u0100" => "A" + +# Ă [LATIN CAPITAL LETTER A WITH BREVE] +"\u0102" => "A" + +# Ą [LATIN CAPITAL LETTER A WITH OGONEK] +"\u0104" => "A" + +# Ə http://en.wikipedia.org/wiki/Schwa [LATIN CAPITAL LETTER SCHWA] +"\u018F" => "A" + +# Ǎ [LATIN CAPITAL LETTER A WITH CARON] +"\u01CD" => "A" + +# Ǟ [LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON] +"\u01DE" => "A" + +# Ǡ [LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON] +"\u01E0" => "A" + +# Ǻ [LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE] +"\u01FA" => "A" + +# Ȁ [LATIN CAPITAL LETTER A WITH DOUBLE GRAVE] +"\u0200" => "A" + +# Ȃ [LATIN CAPITAL LETTER A WITH INVERTED BREVE] +"\u0202" => "A" + +# Ȧ [LATIN CAPITAL LETTER A WITH DOT ABOVE] +"\u0226" => "A" + +# Ⱥ [LATIN CAPITAL LETTER A WITH STROKE] +"\u023A" => "A" + +# ᴀ [LATIN LETTER SMALL CAPITAL A] +"\u1D00" => "A" + +# Ḁ [LATIN CAPITAL LETTER A WITH RING BELOW] +"\u1E00" => "A" + +# Ạ [LATIN CAPITAL LETTER A WITH DOT BELOW] +"\u1EA0" => "A" + +# Ả [LATIN CAPITAL LETTER A WITH HOOK ABOVE] +"\u1EA2" => "A" + +# Ấ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE] +"\u1EA4" => "A" + +# Ầ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE] +"\u1EA6" => "A" + +# Ẩ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EA8" => "A" + +# Ẫ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE] +"\u1EAA" => "A" + +# Ậ [LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW] +"\u1EAC" => "A" + +# Ắ [LATIN CAPITAL LETTER A WITH BREVE AND ACUTE] +"\u1EAE" => "A" + +# Ằ [LATIN CAPITAL LETTER A WITH BREVE AND GRAVE] +"\u1EB0" => "A" + +# Ẳ [LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE] +"\u1EB2" => "A" + +# Ẵ [LATIN CAPITAL LETTER A WITH BREVE AND TILDE] +"\u1EB4" => "A" + +# Ặ [LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW] +"\u1EB6" => "A" + +# Ⓐ [CIRCLED LATIN CAPITAL LETTER A] +"\u24B6" => "A" + +# A [FULLWIDTH LATIN CAPITAL LETTER A] +"\uFF21" => "A" + +# à [LATIN SMALL LETTER A WITH GRAVE] +"\u00E0" => "a" + +# á [LATIN SMALL LETTER A WITH ACUTE] +"\u00E1" => "a" + +# â [LATIN SMALL LETTER A WITH CIRCUMFLEX] +"\u00E2" => "a" + +# ã [LATIN SMALL LETTER A WITH TILDE] +"\u00E3" => "a" + +# ä [LATIN SMALL LETTER A WITH DIAERESIS] +"\u00E4" => "a" + +# å [LATIN SMALL LETTER A WITH RING ABOVE] +"\u00E5" => "a" + +# ā [LATIN SMALL LETTER A WITH MACRON] +"\u0101" => "a" + +# ă [LATIN SMALL LETTER A WITH BREVE] +"\u0103" => "a" + +# ą [LATIN SMALL LETTER A WITH OGONEK] +"\u0105" => "a" + +# ǎ [LATIN SMALL LETTER A WITH CARON] +"\u01CE" => "a" + +# ǟ [LATIN SMALL LETTER A WITH DIAERESIS AND MACRON] +"\u01DF" => "a" + +# ǡ [LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON] +"\u01E1" => "a" + +# ǻ [LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE] +"\u01FB" => "a" + +# ȁ [LATIN SMALL LETTER A WITH DOUBLE GRAVE] +"\u0201" => "a" + +# ȃ [LATIN SMALL LETTER A WITH INVERTED BREVE] +"\u0203" => "a" + +# ȧ [LATIN SMALL LETTER A WITH DOT ABOVE] +"\u0227" => "a" + +# ɐ [LATIN SMALL LETTER TURNED A] +"\u0250" => "a" + +# ə [LATIN SMALL LETTER SCHWA] +"\u0259" => "a" + +# ɚ [LATIN SMALL LETTER SCHWA WITH HOOK] +"\u025A" => "a" + +# ᶏ [LATIN SMALL LETTER A WITH RETROFLEX HOOK] +"\u1D8F" => "a" + +# ᶕ [LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK] +"\u1D95" => "a" + +# ạ [LATIN SMALL LETTER A WITH RING BELOW] +"\u1E01" => "a" + +# ả [LATIN SMALL LETTER A WITH RIGHT HALF RING] +"\u1E9A" => "a" + +# ạ [LATIN SMALL LETTER A WITH DOT BELOW] +"\u1EA1" => "a" + +# ả [LATIN SMALL LETTER A WITH HOOK ABOVE] +"\u1EA3" => "a" + +# ấ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE] +"\u1EA5" => "a" + +# ầ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE] +"\u1EA7" => "a" + +# ẩ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EA9" => "a" + +# ẫ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE] +"\u1EAB" => "a" + +# ậ [LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW] +"\u1EAD" => "a" + +# ắ [LATIN SMALL LETTER A WITH BREVE AND ACUTE] +"\u1EAF" => "a" + +# ằ [LATIN SMALL LETTER A WITH BREVE AND GRAVE] +"\u1EB1" => "a" + +# ẳ [LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE] +"\u1EB3" => "a" + +# ẵ [LATIN SMALL LETTER A WITH BREVE AND TILDE] +"\u1EB5" => "a" + +# ặ [LATIN SMALL LETTER A WITH BREVE AND DOT BELOW] +"\u1EB7" => "a" + +# ₐ [LATIN SUBSCRIPT SMALL LETTER A] +"\u2090" => "a" + +# ₔ [LATIN SUBSCRIPT SMALL LETTER SCHWA] +"\u2094" => "a" + +# ⓐ [CIRCLED LATIN SMALL LETTER A] +"\u24D0" => "a" + +# ⱥ [LATIN SMALL LETTER A WITH STROKE] +"\u2C65" => "a" + +# Ɐ [LATIN CAPITAL LETTER TURNED A] +"\u2C6F" => "a" + +# a [FULLWIDTH LATIN SMALL LETTER A] +"\uFF41" => "a" + +# Ꜳ [LATIN CAPITAL LETTER AA] +"\uA732" => "AA" + +# Æ [LATIN CAPITAL LETTER AE] +"\u00C6" => "AE" + +# Ǣ [LATIN CAPITAL LETTER AE WITH MACRON] +"\u01E2" => "AE" + +# Ǽ [LATIN CAPITAL LETTER AE WITH ACUTE] +"\u01FC" => "AE" + +# ᴁ [LATIN LETTER SMALL CAPITAL AE] +"\u1D01" => "AE" + +# Ꜵ [LATIN CAPITAL LETTER AO] +"\uA734" => "AO" + +# Ꜷ [LATIN CAPITAL LETTER AU] +"\uA736" => "AU" + +# Ꜹ [LATIN CAPITAL LETTER AV] +"\uA738" => "AV" + +# Ꜻ [LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR] +"\uA73A" => "AV" + +# Ꜽ [LATIN CAPITAL LETTER AY] +"\uA73C" => "AY" + +# ⒜ [PARENTHESIZED LATIN SMALL LETTER A] +"\u249C" => "(a)" + +# ꜳ [LATIN SMALL LETTER AA] +"\uA733" => "aa" + +# æ [LATIN SMALL LETTER AE] +"\u00E6" => "ae" + +# ǣ [LATIN SMALL LETTER AE WITH MACRON] +"\u01E3" => "ae" + +# ǽ [LATIN SMALL LETTER AE WITH ACUTE] +"\u01FD" => "ae" + +# ᴂ [LATIN SMALL LETTER TURNED AE] +"\u1D02" => "ae" + +# ꜵ [LATIN SMALL LETTER AO] +"\uA735" => "ao" + +# ꜷ [LATIN SMALL LETTER AU] +"\uA737" => "au" + +# ꜹ [LATIN SMALL LETTER AV] +"\uA739" => "av" + +# ꜻ [LATIN SMALL LETTER AV WITH HORIZONTAL BAR] +"\uA73B" => "av" + +# ꜽ [LATIN SMALL LETTER AY] +"\uA73D" => "ay" + +# Ɓ [LATIN CAPITAL LETTER B WITH HOOK] +"\u0181" => "B" + +# Ƃ [LATIN CAPITAL LETTER B WITH TOPBAR] +"\u0182" => "B" + +# Ƀ [LATIN CAPITAL LETTER B WITH STROKE] +"\u0243" => "B" + +# ʙ [LATIN LETTER SMALL CAPITAL B] +"\u0299" => "B" + +# ᴃ [LATIN LETTER SMALL CAPITAL BARRED B] +"\u1D03" => "B" + +# Ḃ [LATIN CAPITAL LETTER B WITH DOT ABOVE] +"\u1E02" => "B" + +# Ḅ [LATIN CAPITAL LETTER B WITH DOT BELOW] +"\u1E04" => "B" + +# Ḇ [LATIN CAPITAL LETTER B WITH LINE BELOW] +"\u1E06" => "B" + +# Ⓑ [CIRCLED LATIN CAPITAL LETTER B] +"\u24B7" => "B" + +# B [FULLWIDTH LATIN CAPITAL LETTER B] +"\uFF22" => "B" + +# ƀ [LATIN SMALL LETTER B WITH STROKE] +"\u0180" => "b" + +# ƃ [LATIN SMALL LETTER B WITH TOPBAR] +"\u0183" => "b" + +# ɓ [LATIN SMALL LETTER B WITH HOOK] +"\u0253" => "b" + +# ᵬ [LATIN SMALL LETTER B WITH MIDDLE TILDE] +"\u1D6C" => "b" + +# ᶀ [LATIN SMALL LETTER B WITH PALATAL HOOK] +"\u1D80" => "b" + +# ḃ [LATIN SMALL LETTER B WITH DOT ABOVE] +"\u1E03" => "b" + +# ḅ [LATIN SMALL LETTER B WITH DOT BELOW] +"\u1E05" => "b" + +# ḇ [LATIN SMALL LETTER B WITH LINE BELOW] +"\u1E07" => "b" + +# ⓑ [CIRCLED LATIN SMALL LETTER B] +"\u24D1" => "b" + +# b [FULLWIDTH LATIN SMALL LETTER B] +"\uFF42" => "b" + +# ⒝ [PARENTHESIZED LATIN SMALL LETTER B] +"\u249D" => "(b)" + +# Ç [LATIN CAPITAL LETTER C WITH CEDILLA] +"\u00C7" => "C" + +# Ć [LATIN CAPITAL LETTER C WITH ACUTE] +"\u0106" => "C" + +# Ĉ [LATIN CAPITAL LETTER C WITH CIRCUMFLEX] +"\u0108" => "C" + +# Ċ [LATIN CAPITAL LETTER C WITH DOT ABOVE] +"\u010A" => "C" + +# Č [LATIN CAPITAL LETTER C WITH CARON] +"\u010C" => "C" + +# Ƈ [LATIN CAPITAL LETTER C WITH HOOK] +"\u0187" => "C" + +# Ȼ [LATIN CAPITAL LETTER C WITH STROKE] +"\u023B" => "C" + +# ʗ [LATIN LETTER STRETCHED C] +"\u0297" => "C" + +# ᴄ [LATIN LETTER SMALL CAPITAL C] +"\u1D04" => "C" + +# Ḉ [LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE] +"\u1E08" => "C" + +# Ⓒ [CIRCLED LATIN CAPITAL LETTER C] +"\u24B8" => "C" + +# C [FULLWIDTH LATIN CAPITAL LETTER C] +"\uFF23" => "C" + +# ç [LATIN SMALL LETTER C WITH CEDILLA] +"\u00E7" => "c" + +# ć [LATIN SMALL LETTER C WITH ACUTE] +"\u0107" => "c" + +# ĉ [LATIN SMALL LETTER C WITH CIRCUMFLEX] +"\u0109" => "c" + +# ċ [LATIN SMALL LETTER C WITH DOT ABOVE] +"\u010B" => "c" + +# č [LATIN SMALL LETTER C WITH CARON] +"\u010D" => "c" + +# ƈ [LATIN SMALL LETTER C WITH HOOK] +"\u0188" => "c" + +# ȼ [LATIN SMALL LETTER C WITH STROKE] +"\u023C" => "c" + +# ɕ [LATIN SMALL LETTER C WITH CURL] +"\u0255" => "c" + +# ḉ [LATIN SMALL LETTER C WITH CEDILLA AND ACUTE] +"\u1E09" => "c" + +# ↄ [LATIN SMALL LETTER REVERSED C] +"\u2184" => "c" + +# ⓒ [CIRCLED LATIN SMALL LETTER C] +"\u24D2" => "c" + +# Ꜿ [LATIN CAPITAL LETTER REVERSED C WITH DOT] +"\uA73E" => "c" + +# ꜿ [LATIN SMALL LETTER REVERSED C WITH DOT] +"\uA73F" => "c" + +# c [FULLWIDTH LATIN SMALL LETTER C] +"\uFF43" => "c" + +# ⒞ [PARENTHESIZED LATIN SMALL LETTER C] +"\u249E" => "(c)" + +# Ð [LATIN CAPITAL LETTER ETH] +"\u00D0" => "D" + +# Ď [LATIN CAPITAL LETTER D WITH CARON] +"\u010E" => "D" + +# Đ [LATIN CAPITAL LETTER D WITH STROKE] +"\u0110" => "D" + +# Ɖ [LATIN CAPITAL LETTER AFRICAN D] +"\u0189" => "D" + +# Ɗ [LATIN CAPITAL LETTER D WITH HOOK] +"\u018A" => "D" + +# Ƌ [LATIN CAPITAL LETTER D WITH TOPBAR] +"\u018B" => "D" + +# ᴅ [LATIN LETTER SMALL CAPITAL D] +"\u1D05" => "D" + +# ᴆ [LATIN LETTER SMALL CAPITAL ETH] +"\u1D06" => "D" + +# Ḋ [LATIN CAPITAL LETTER D WITH DOT ABOVE] +"\u1E0A" => "D" + +# Ḍ [LATIN CAPITAL LETTER D WITH DOT BELOW] +"\u1E0C" => "D" + +# Ḏ [LATIN CAPITAL LETTER D WITH LINE BELOW] +"\u1E0E" => "D" + +# Ḑ [LATIN CAPITAL LETTER D WITH CEDILLA] +"\u1E10" => "D" + +# Ḓ [LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW] +"\u1E12" => "D" + +# Ⓓ [CIRCLED LATIN CAPITAL LETTER D] +"\u24B9" => "D" + +# Ꝺ [LATIN CAPITAL LETTER INSULAR D] +"\uA779" => "D" + +# D [FULLWIDTH LATIN CAPITAL LETTER D] +"\uFF24" => "D" + +# ð [LATIN SMALL LETTER ETH] +"\u00F0" => "d" + +# ď [LATIN SMALL LETTER D WITH CARON] +"\u010F" => "d" + +# đ [LATIN SMALL LETTER D WITH STROKE] +"\u0111" => "d" + +# ƌ [LATIN SMALL LETTER D WITH TOPBAR] +"\u018C" => "d" + +# ȡ [LATIN SMALL LETTER D WITH CURL] +"\u0221" => "d" + +# ɖ [LATIN SMALL LETTER D WITH TAIL] +"\u0256" => "d" + +# ɗ [LATIN SMALL LETTER D WITH HOOK] +"\u0257" => "d" + +# ᵭ [LATIN SMALL LETTER D WITH MIDDLE TILDE] +"\u1D6D" => "d" + +# ᶁ [LATIN SMALL LETTER D WITH PALATAL HOOK] +"\u1D81" => "d" + +# ᶑ [LATIN SMALL LETTER D WITH HOOK AND TAIL] +"\u1D91" => "d" + +# ḋ [LATIN SMALL LETTER D WITH DOT ABOVE] +"\u1E0B" => "d" + +# ḍ [LATIN SMALL LETTER D WITH DOT BELOW] +"\u1E0D" => "d" + +# ḏ [LATIN SMALL LETTER D WITH LINE BELOW] +"\u1E0F" => "d" + +# ḑ [LATIN SMALL LETTER D WITH CEDILLA] +"\u1E11" => "d" + +# ḓ [LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW] +"\u1E13" => "d" + +# ⓓ [CIRCLED LATIN SMALL LETTER D] +"\u24D3" => "d" + +# ꝺ [LATIN SMALL LETTER INSULAR D] +"\uA77A" => "d" + +# d [FULLWIDTH LATIN SMALL LETTER D] +"\uFF44" => "d" + +# DŽ [LATIN CAPITAL LETTER DZ WITH CARON] +"\u01C4" => "DZ" + +# DZ [LATIN CAPITAL LETTER DZ] +"\u01F1" => "DZ" + +# Dž [LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON] +"\u01C5" => "Dz" + +# Dz [LATIN CAPITAL LETTER D WITH SMALL LETTER Z] +"\u01F2" => "Dz" + +# ⒟ [PARENTHESIZED LATIN SMALL LETTER D] +"\u249F" => "(d)" + +# ȸ [LATIN SMALL LETTER DB DIGRAPH] +"\u0238" => "db" + +# dž [LATIN SMALL LETTER DZ WITH CARON] +"\u01C6" => "dz" + +# dz [LATIN SMALL LETTER DZ] +"\u01F3" => "dz" + +# ʣ [LATIN SMALL LETTER DZ DIGRAPH] +"\u02A3" => "dz" + +# ʥ [LATIN SMALL LETTER DZ DIGRAPH WITH CURL] +"\u02A5" => "dz" + +# È [LATIN CAPITAL LETTER E WITH GRAVE] +"\u00C8" => "E" + +# É [LATIN CAPITAL LETTER E WITH ACUTE] +"\u00C9" => "E" + +# Ê [LATIN CAPITAL LETTER E WITH CIRCUMFLEX] +"\u00CA" => "E" + +# Ë [LATIN CAPITAL LETTER E WITH DIAERESIS] +"\u00CB" => "E" + +# Ē [LATIN CAPITAL LETTER E WITH MACRON] +"\u0112" => "E" + +# Ĕ [LATIN CAPITAL LETTER E WITH BREVE] +"\u0114" => "E" + +# Ė [LATIN CAPITAL LETTER E WITH DOT ABOVE] +"\u0116" => "E" + +# Ę [LATIN CAPITAL LETTER E WITH OGONEK] +"\u0118" => "E" + +# Ě [LATIN CAPITAL LETTER E WITH CARON] +"\u011A" => "E" + +# Ǝ [LATIN CAPITAL LETTER REVERSED E] +"\u018E" => "E" + +# Ɛ [LATIN CAPITAL LETTER OPEN E] +"\u0190" => "E" + +# Ȅ [LATIN CAPITAL LETTER E WITH DOUBLE GRAVE] +"\u0204" => "E" + +# Ȇ [LATIN CAPITAL LETTER E WITH INVERTED BREVE] +"\u0206" => "E" + +# Ȩ [LATIN CAPITAL LETTER E WITH CEDILLA] +"\u0228" => "E" + +# Ɇ [LATIN CAPITAL LETTER E WITH STROKE] +"\u0246" => "E" + +# ᴇ [LATIN LETTER SMALL CAPITAL E] +"\u1D07" => "E" + +# Ḕ [LATIN CAPITAL LETTER E WITH MACRON AND GRAVE] +"\u1E14" => "E" + +# Ḗ [LATIN CAPITAL LETTER E WITH MACRON AND ACUTE] +"\u1E16" => "E" + +# Ḙ [LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW] +"\u1E18" => "E" + +# Ḛ [LATIN CAPITAL LETTER E WITH TILDE BELOW] +"\u1E1A" => "E" + +# Ḝ [LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE] +"\u1E1C" => "E" + +# Ẹ [LATIN CAPITAL LETTER E WITH DOT BELOW] +"\u1EB8" => "E" + +# Ẻ [LATIN CAPITAL LETTER E WITH HOOK ABOVE] +"\u1EBA" => "E" + +# Ẽ [LATIN CAPITAL LETTER E WITH TILDE] +"\u1EBC" => "E" + +# Ế [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE] +"\u1EBE" => "E" + +# Ề [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE] +"\u1EC0" => "E" + +# Ể [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EC2" => "E" + +# Ễ [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE] +"\u1EC4" => "E" + +# Ệ [LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW] +"\u1EC6" => "E" + +# Ⓔ [CIRCLED LATIN CAPITAL LETTER E] +"\u24BA" => "E" + +# ⱻ [LATIN LETTER SMALL CAPITAL TURNED E] +"\u2C7B" => "E" + +# E [FULLWIDTH LATIN CAPITAL LETTER E] +"\uFF25" => "E" + +# è [LATIN SMALL LETTER E WITH GRAVE] +"\u00E8" => "e" + +# é [LATIN SMALL LETTER E WITH ACUTE] +"\u00E9" => "e" + +# ê [LATIN SMALL LETTER E WITH CIRCUMFLEX] +"\u00EA" => "e" + +# ë [LATIN SMALL LETTER E WITH DIAERESIS] +"\u00EB" => "e" + +# ē [LATIN SMALL LETTER E WITH MACRON] +"\u0113" => "e" + +# ĕ [LATIN SMALL LETTER E WITH BREVE] +"\u0115" => "e" + +# ė [LATIN SMALL LETTER E WITH DOT ABOVE] +"\u0117" => "e" + +# ę [LATIN SMALL LETTER E WITH OGONEK] +"\u0119" => "e" + +# ě [LATIN SMALL LETTER E WITH CARON] +"\u011B" => "e" + +# ǝ [LATIN SMALL LETTER TURNED E] +"\u01DD" => "e" + +# ȅ [LATIN SMALL LETTER E WITH DOUBLE GRAVE] +"\u0205" => "e" + +# ȇ [LATIN SMALL LETTER E WITH INVERTED BREVE] +"\u0207" => "e" + +# ȩ [LATIN SMALL LETTER E WITH CEDILLA] +"\u0229" => "e" + +# ɇ [LATIN SMALL LETTER E WITH STROKE] +"\u0247" => "e" + +# ɘ [LATIN SMALL LETTER REVERSED E] +"\u0258" => "e" + +# ɛ [LATIN SMALL LETTER OPEN E] +"\u025B" => "e" + +# ɜ [LATIN SMALL LETTER REVERSED OPEN E] +"\u025C" => "e" + +# ɝ [LATIN SMALL LETTER REVERSED OPEN E WITH HOOK] +"\u025D" => "e" + +# ɞ [LATIN SMALL LETTER CLOSED REVERSED OPEN E] +"\u025E" => "e" + +# ʚ [LATIN SMALL LETTER CLOSED OPEN E] +"\u029A" => "e" + +# ᴈ [LATIN SMALL LETTER TURNED OPEN E] +"\u1D08" => "e" + +# ᶒ [LATIN SMALL LETTER E WITH RETROFLEX HOOK] +"\u1D92" => "e" + +# ᶓ [LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK] +"\u1D93" => "e" + +# ᶔ [LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK] +"\u1D94" => "e" + +# ḕ [LATIN SMALL LETTER E WITH MACRON AND GRAVE] +"\u1E15" => "e" + +# ḗ [LATIN SMALL LETTER E WITH MACRON AND ACUTE] +"\u1E17" => "e" + +# ḙ [LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW] +"\u1E19" => "e" + +# ḛ [LATIN SMALL LETTER E WITH TILDE BELOW] +"\u1E1B" => "e" + +# ḝ [LATIN SMALL LETTER E WITH CEDILLA AND BREVE] +"\u1E1D" => "e" + +# ẹ [LATIN SMALL LETTER E WITH DOT BELOW] +"\u1EB9" => "e" + +# ẻ [LATIN SMALL LETTER E WITH HOOK ABOVE] +"\u1EBB" => "e" + +# ẽ [LATIN SMALL LETTER E WITH TILDE] +"\u1EBD" => "e" + +# ế [LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE] +"\u1EBF" => "e" + +# ề [LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE] +"\u1EC1" => "e" + +# ể [LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1EC3" => "e" + +# ễ [LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE] +"\u1EC5" => "e" + +# ệ [LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW] +"\u1EC7" => "e" + +# ₑ [LATIN SUBSCRIPT SMALL LETTER E] +"\u2091" => "e" + +# ⓔ [CIRCLED LATIN SMALL LETTER E] +"\u24D4" => "e" + +# ⱸ [LATIN SMALL LETTER E WITH NOTCH] +"\u2C78" => "e" + +# e [FULLWIDTH LATIN SMALL LETTER E] +"\uFF45" => "e" + +# ⒠ [PARENTHESIZED LATIN SMALL LETTER E] +"\u24A0" => "(e)" + +# Ƒ [LATIN CAPITAL LETTER F WITH HOOK] +"\u0191" => "F" + +# Ḟ [LATIN CAPITAL LETTER F WITH DOT ABOVE] +"\u1E1E" => "F" + +# Ⓕ [CIRCLED LATIN CAPITAL LETTER F] +"\u24BB" => "F" + +# ꜰ [LATIN LETTER SMALL CAPITAL F] +"\uA730" => "F" + +# Ꝼ [LATIN CAPITAL LETTER INSULAR F] +"\uA77B" => "F" + +# ꟻ [LATIN EPIGRAPHIC LETTER REVERSED F] +"\uA7FB" => "F" + +# F [FULLWIDTH LATIN CAPITAL LETTER F] +"\uFF26" => "F" + +# ƒ [LATIN SMALL LETTER F WITH HOOK] +"\u0192" => "f" + +# ᵮ [LATIN SMALL LETTER F WITH MIDDLE TILDE] +"\u1D6E" => "f" + +# ᶂ [LATIN SMALL LETTER F WITH PALATAL HOOK] +"\u1D82" => "f" + +# ḟ [LATIN SMALL LETTER F WITH DOT ABOVE] +"\u1E1F" => "f" + +# ẛ [LATIN SMALL LETTER LONG S WITH DOT ABOVE] +"\u1E9B" => "f" + +# ⓕ [CIRCLED LATIN SMALL LETTER F] +"\u24D5" => "f" + +# ꝼ [LATIN SMALL LETTER INSULAR F] +"\uA77C" => "f" + +# f [FULLWIDTH LATIN SMALL LETTER F] +"\uFF46" => "f" + +# ⒡ [PARENTHESIZED LATIN SMALL LETTER F] +"\u24A1" => "(f)" + +# ff [LATIN SMALL LIGATURE FF] +"\uFB00" => "ff" + +# ffi [LATIN SMALL LIGATURE FFI] +"\uFB03" => "ffi" + +# ffl [LATIN SMALL LIGATURE FFL] +"\uFB04" => "ffl" + +# fi [LATIN SMALL LIGATURE FI] +"\uFB01" => "fi" + +# fl [LATIN SMALL LIGATURE FL] +"\uFB02" => "fl" + +# Ĝ [LATIN CAPITAL LETTER G WITH CIRCUMFLEX] +"\u011C" => "G" + +# Ğ [LATIN CAPITAL LETTER G WITH BREVE] +"\u011E" => "G" + +# Ġ [LATIN CAPITAL LETTER G WITH DOT ABOVE] +"\u0120" => "G" + +# Ģ [LATIN CAPITAL LETTER G WITH CEDILLA] +"\u0122" => "G" + +# Ɠ [LATIN CAPITAL LETTER G WITH HOOK] +"\u0193" => "G" + +# Ǥ [LATIN CAPITAL LETTER G WITH STROKE] +"\u01E4" => "G" + +# ǥ [LATIN SMALL LETTER G WITH STROKE] +"\u01E5" => "G" + +# Ǧ [LATIN CAPITAL LETTER G WITH CARON] +"\u01E6" => "G" + +# ǧ [LATIN SMALL LETTER G WITH CARON] +"\u01E7" => "G" + +# Ǵ [LATIN CAPITAL LETTER G WITH ACUTE] +"\u01F4" => "G" + +# ɢ [LATIN LETTER SMALL CAPITAL G] +"\u0262" => "G" + +# ʛ [LATIN LETTER SMALL CAPITAL G WITH HOOK] +"\u029B" => "G" + +# Ḡ [LATIN CAPITAL LETTER G WITH MACRON] +"\u1E20" => "G" + +# Ⓖ [CIRCLED LATIN CAPITAL LETTER G] +"\u24BC" => "G" + +# Ᵹ [LATIN CAPITAL LETTER INSULAR G] +"\uA77D" => "G" + +# Ꝿ [LATIN CAPITAL LETTER TURNED INSULAR G] +"\uA77E" => "G" + +# G [FULLWIDTH LATIN CAPITAL LETTER G] +"\uFF27" => "G" + +# ĝ [LATIN SMALL LETTER G WITH CIRCUMFLEX] +"\u011D" => "g" + +# ğ [LATIN SMALL LETTER G WITH BREVE] +"\u011F" => "g" + +# ġ [LATIN SMALL LETTER G WITH DOT ABOVE] +"\u0121" => "g" + +# ģ [LATIN SMALL LETTER G WITH CEDILLA] +"\u0123" => "g" + +# ǵ [LATIN SMALL LETTER G WITH ACUTE] +"\u01F5" => "g" + +# ɠ [LATIN SMALL LETTER G WITH HOOK] +"\u0260" => "g" + +# ɡ [LATIN SMALL LETTER SCRIPT G] +"\u0261" => "g" + +# ᵷ [LATIN SMALL LETTER TURNED G] +"\u1D77" => "g" + +# ᵹ [LATIN SMALL LETTER INSULAR G] +"\u1D79" => "g" + +# ᶃ [LATIN SMALL LETTER G WITH PALATAL HOOK] +"\u1D83" => "g" + +# ḡ [LATIN SMALL LETTER G WITH MACRON] +"\u1E21" => "g" + +# ⓖ [CIRCLED LATIN SMALL LETTER G] +"\u24D6" => "g" + +# ꝿ [LATIN SMALL LETTER TURNED INSULAR G] +"\uA77F" => "g" + +# g [FULLWIDTH LATIN SMALL LETTER G] +"\uFF47" => "g" + +# ⒢ [PARENTHESIZED LATIN SMALL LETTER G] +"\u24A2" => "(g)" + +# Ĥ [LATIN CAPITAL LETTER H WITH CIRCUMFLEX] +"\u0124" => "H" + +# Ħ [LATIN CAPITAL LETTER H WITH STROKE] +"\u0126" => "H" + +# Ȟ [LATIN CAPITAL LETTER H WITH CARON] +"\u021E" => "H" + +# ʜ [LATIN LETTER SMALL CAPITAL H] +"\u029C" => "H" + +# Ḣ [LATIN CAPITAL LETTER H WITH DOT ABOVE] +"\u1E22" => "H" + +# Ḥ [LATIN CAPITAL LETTER H WITH DOT BELOW] +"\u1E24" => "H" + +# Ḧ [LATIN CAPITAL LETTER H WITH DIAERESIS] +"\u1E26" => "H" + +# Ḩ [LATIN CAPITAL LETTER H WITH CEDILLA] +"\u1E28" => "H" + +# Ḫ [LATIN CAPITAL LETTER H WITH BREVE BELOW] +"\u1E2A" => "H" + +# Ⓗ [CIRCLED LATIN CAPITAL LETTER H] +"\u24BD" => "H" + +# Ⱨ [LATIN CAPITAL LETTER H WITH DESCENDER] +"\u2C67" => "H" + +# Ⱶ [LATIN CAPITAL LETTER HALF H] +"\u2C75" => "H" + +# H [FULLWIDTH LATIN CAPITAL LETTER H] +"\uFF28" => "H" + +# ĥ [LATIN SMALL LETTER H WITH CIRCUMFLEX] +"\u0125" => "h" + +# ħ [LATIN SMALL LETTER H WITH STROKE] +"\u0127" => "h" + +# ȟ [LATIN SMALL LETTER H WITH CARON] +"\u021F" => "h" + +# ɥ [LATIN SMALL LETTER TURNED H] +"\u0265" => "h" + +# ɦ [LATIN SMALL LETTER H WITH HOOK] +"\u0266" => "h" + +# ʮ [LATIN SMALL LETTER TURNED H WITH FISHHOOK] +"\u02AE" => "h" + +# ʯ [LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL] +"\u02AF" => "h" + +# ḣ [LATIN SMALL LETTER H WITH DOT ABOVE] +"\u1E23" => "h" + +# ḥ [LATIN SMALL LETTER H WITH DOT BELOW] +"\u1E25" => "h" + +# ḧ [LATIN SMALL LETTER H WITH DIAERESIS] +"\u1E27" => "h" + +# ḩ [LATIN SMALL LETTER H WITH CEDILLA] +"\u1E29" => "h" + +# ḫ [LATIN SMALL LETTER H WITH BREVE BELOW] +"\u1E2B" => "h" + +# ẖ [LATIN SMALL LETTER H WITH LINE BELOW] +"\u1E96" => "h" + +# ⓗ [CIRCLED LATIN SMALL LETTER H] +"\u24D7" => "h" + +# ⱨ [LATIN SMALL LETTER H WITH DESCENDER] +"\u2C68" => "h" + +# ⱶ [LATIN SMALL LETTER HALF H] +"\u2C76" => "h" + +# h [FULLWIDTH LATIN SMALL LETTER H] +"\uFF48" => "h" + +# Ƕ http://en.wikipedia.org/wiki/Hwair [LATIN CAPITAL LETTER HWAIR] +"\u01F6" => "HV" + +# ⒣ [PARENTHESIZED LATIN SMALL LETTER H] +"\u24A3" => "(h)" + +# ƕ [LATIN SMALL LETTER HV] +"\u0195" => "hv" + +# Ì [LATIN CAPITAL LETTER I WITH GRAVE] +"\u00CC" => "I" + +# Í [LATIN CAPITAL LETTER I WITH ACUTE] +"\u00CD" => "I" + +# Î [LATIN CAPITAL LETTER I WITH CIRCUMFLEX] +"\u00CE" => "I" + +# Ï [LATIN CAPITAL LETTER I WITH DIAERESIS] +"\u00CF" => "I" + +# Ĩ [LATIN CAPITAL LETTER I WITH TILDE] +"\u0128" => "I" + +# Ī [LATIN CAPITAL LETTER I WITH MACRON] +"\u012A" => "I" + +# Ĭ [LATIN CAPITAL LETTER I WITH BREVE] +"\u012C" => "I" + +# Į [LATIN CAPITAL LETTER I WITH OGONEK] +"\u012E" => "I" + +# İ [LATIN CAPITAL LETTER I WITH DOT ABOVE] +"\u0130" => "I" + +# Ɩ [LATIN CAPITAL LETTER IOTA] +"\u0196" => "I" + +# Ɨ [LATIN CAPITAL LETTER I WITH STROKE] +"\u0197" => "I" + +# Ǐ [LATIN CAPITAL LETTER I WITH CARON] +"\u01CF" => "I" + +# Ȉ [LATIN CAPITAL LETTER I WITH DOUBLE GRAVE] +"\u0208" => "I" + +# Ȋ [LATIN CAPITAL LETTER I WITH INVERTED BREVE] +"\u020A" => "I" + +# ɪ [LATIN LETTER SMALL CAPITAL I] +"\u026A" => "I" + +# ᵻ [LATIN SMALL CAPITAL LETTER I WITH STROKE] +"\u1D7B" => "I" + +# Ḭ [LATIN CAPITAL LETTER I WITH TILDE BELOW] +"\u1E2C" => "I" + +# Ḯ [LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE] +"\u1E2E" => "I" + +# Ỉ [LATIN CAPITAL LETTER I WITH HOOK ABOVE] +"\u1EC8" => "I" + +# Ị [LATIN CAPITAL LETTER I WITH DOT BELOW] +"\u1ECA" => "I" + +# Ⓘ [CIRCLED LATIN CAPITAL LETTER I] +"\u24BE" => "I" + +# ꟾ [LATIN EPIGRAPHIC LETTER I LONGA] +"\uA7FE" => "I" + +# I [FULLWIDTH LATIN CAPITAL LETTER I] +"\uFF29" => "I" + +# ì [LATIN SMALL LETTER I WITH GRAVE] +"\u00EC" => "i" + +# í [LATIN SMALL LETTER I WITH ACUTE] +"\u00ED" => "i" + +# î [LATIN SMALL LETTER I WITH CIRCUMFLEX] +"\u00EE" => "i" + +# ï [LATIN SMALL LETTER I WITH DIAERESIS] +"\u00EF" => "i" + +# ĩ [LATIN SMALL LETTER I WITH TILDE] +"\u0129" => "i" + +# ī [LATIN SMALL LETTER I WITH MACRON] +"\u012B" => "i" + +# ĭ [LATIN SMALL LETTER I WITH BREVE] +"\u012D" => "i" + +# į [LATIN SMALL LETTER I WITH OGONEK] +"\u012F" => "i" + +# ı [LATIN SMALL LETTER DOTLESS I] +"\u0131" => "i" + +# ǐ [LATIN SMALL LETTER I WITH CARON] +"\u01D0" => "i" + +# ȉ [LATIN SMALL LETTER I WITH DOUBLE GRAVE] +"\u0209" => "i" + +# ȋ [LATIN SMALL LETTER I WITH INVERTED BREVE] +"\u020B" => "i" + +# ɨ [LATIN SMALL LETTER I WITH STROKE] +"\u0268" => "i" + +# ᴉ [LATIN SMALL LETTER TURNED I] +"\u1D09" => "i" + +# ᵢ [LATIN SUBSCRIPT SMALL LETTER I] +"\u1D62" => "i" + +# ᵼ [LATIN SMALL LETTER IOTA WITH STROKE] +"\u1D7C" => "i" + +# ᶖ [LATIN SMALL LETTER I WITH RETROFLEX HOOK] +"\u1D96" => "i" + +# ḭ [LATIN SMALL LETTER I WITH TILDE BELOW] +"\u1E2D" => "i" + +# ḯ [LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE] +"\u1E2F" => "i" + +# ỉ [LATIN SMALL LETTER I WITH HOOK ABOVE] +"\u1EC9" => "i" + +# ị [LATIN SMALL LETTER I WITH DOT BELOW] +"\u1ECB" => "i" + +# ⁱ [SUPERSCRIPT LATIN SMALL LETTER I] +"\u2071" => "i" + +# ⓘ [CIRCLED LATIN SMALL LETTER I] +"\u24D8" => "i" + +# i [FULLWIDTH LATIN SMALL LETTER I] +"\uFF49" => "i" + +# IJ [LATIN CAPITAL LIGATURE IJ] +"\u0132" => "IJ" + +# ⒤ [PARENTHESIZED LATIN SMALL LETTER I] +"\u24A4" => "(i)" + +# ij [LATIN SMALL LIGATURE IJ] +"\u0133" => "ij" + +# Ĵ [LATIN CAPITAL LETTER J WITH CIRCUMFLEX] +"\u0134" => "J" + +# Ɉ [LATIN CAPITAL LETTER J WITH STROKE] +"\u0248" => "J" + +# ᴊ [LATIN LETTER SMALL CAPITAL J] +"\u1D0A" => "J" + +# Ⓙ [CIRCLED LATIN CAPITAL LETTER J] +"\u24BF" => "J" + +# J [FULLWIDTH LATIN CAPITAL LETTER J] +"\uFF2A" => "J" + +# ĵ [LATIN SMALL LETTER J WITH CIRCUMFLEX] +"\u0135" => "j" + +# ǰ [LATIN SMALL LETTER J WITH CARON] +"\u01F0" => "j" + +# ȷ [LATIN SMALL LETTER DOTLESS J] +"\u0237" => "j" + +# ɉ [LATIN SMALL LETTER J WITH STROKE] +"\u0249" => "j" + +# ɟ [LATIN SMALL LETTER DOTLESS J WITH STROKE] +"\u025F" => "j" + +# ʄ [LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK] +"\u0284" => "j" + +# ʝ [LATIN SMALL LETTER J WITH CROSSED-TAIL] +"\u029D" => "j" + +# ⓙ [CIRCLED LATIN SMALL LETTER J] +"\u24D9" => "j" + +# ⱼ [LATIN SUBSCRIPT SMALL LETTER J] +"\u2C7C" => "j" + +# j [FULLWIDTH LATIN SMALL LETTER J] +"\uFF4A" => "j" + +# ⒥ [PARENTHESIZED LATIN SMALL LETTER J] +"\u24A5" => "(j)" + +# Ķ [LATIN CAPITAL LETTER K WITH CEDILLA] +"\u0136" => "K" + +# Ƙ [LATIN CAPITAL LETTER K WITH HOOK] +"\u0198" => "K" + +# Ǩ [LATIN CAPITAL LETTER K WITH CARON] +"\u01E8" => "K" + +# ᴋ [LATIN LETTER SMALL CAPITAL K] +"\u1D0B" => "K" + +# Ḱ [LATIN CAPITAL LETTER K WITH ACUTE] +"\u1E30" => "K" + +# Ḳ [LATIN CAPITAL LETTER K WITH DOT BELOW] +"\u1E32" => "K" + +# Ḵ [LATIN CAPITAL LETTER K WITH LINE BELOW] +"\u1E34" => "K" + +# Ⓚ [CIRCLED LATIN CAPITAL LETTER K] +"\u24C0" => "K" + +# Ⱪ [LATIN CAPITAL LETTER K WITH DESCENDER] +"\u2C69" => "K" + +# Ꝁ [LATIN CAPITAL LETTER K WITH STROKE] +"\uA740" => "K" + +# Ꝃ [LATIN CAPITAL LETTER K WITH DIAGONAL STROKE] +"\uA742" => "K" + +# Ꝅ [LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE] +"\uA744" => "K" + +# K [FULLWIDTH LATIN CAPITAL LETTER K] +"\uFF2B" => "K" + +# ķ [LATIN SMALL LETTER K WITH CEDILLA] +"\u0137" => "k" + +# ƙ [LATIN SMALL LETTER K WITH HOOK] +"\u0199" => "k" + +# ǩ [LATIN SMALL LETTER K WITH CARON] +"\u01E9" => "k" + +# ʞ [LATIN SMALL LETTER TURNED K] +"\u029E" => "k" + +# ᶄ [LATIN SMALL LETTER K WITH PALATAL HOOK] +"\u1D84" => "k" + +# ḱ [LATIN SMALL LETTER K WITH ACUTE] +"\u1E31" => "k" + +# ḳ [LATIN SMALL LETTER K WITH DOT BELOW] +"\u1E33" => "k" + +# ḵ [LATIN SMALL LETTER K WITH LINE BELOW] +"\u1E35" => "k" + +# ⓚ [CIRCLED LATIN SMALL LETTER K] +"\u24DA" => "k" + +# ⱪ [LATIN SMALL LETTER K WITH DESCENDER] +"\u2C6A" => "k" + +# ꝁ [LATIN SMALL LETTER K WITH STROKE] +"\uA741" => "k" + +# ꝃ [LATIN SMALL LETTER K WITH DIAGONAL STROKE] +"\uA743" => "k" + +# ꝅ [LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE] +"\uA745" => "k" + +# k [FULLWIDTH LATIN SMALL LETTER K] +"\uFF4B" => "k" + +# ⒦ [PARENTHESIZED LATIN SMALL LETTER K] +"\u24A6" => "(k)" + +# Ĺ [LATIN CAPITAL LETTER L WITH ACUTE] +"\u0139" => "L" + +# Ļ [LATIN CAPITAL LETTER L WITH CEDILLA] +"\u013B" => "L" + +# Ľ [LATIN CAPITAL LETTER L WITH CARON] +"\u013D" => "L" + +# Ŀ [LATIN CAPITAL LETTER L WITH MIDDLE DOT] +"\u013F" => "L" + +# Ł [LATIN CAPITAL LETTER L WITH STROKE] +"\u0141" => "L" + +# Ƚ [LATIN CAPITAL LETTER L WITH BAR] +"\u023D" => "L" + +# ʟ [LATIN LETTER SMALL CAPITAL L] +"\u029F" => "L" + +# ᴌ [LATIN LETTER SMALL CAPITAL L WITH STROKE] +"\u1D0C" => "L" + +# Ḷ [LATIN CAPITAL LETTER L WITH DOT BELOW] +"\u1E36" => "L" + +# Ḹ [LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON] +"\u1E38" => "L" + +# Ḻ [LATIN CAPITAL LETTER L WITH LINE BELOW] +"\u1E3A" => "L" + +# Ḽ [LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW] +"\u1E3C" => "L" + +# Ⓛ [CIRCLED LATIN CAPITAL LETTER L] +"\u24C1" => "L" + +# Ⱡ [LATIN CAPITAL LETTER L WITH DOUBLE BAR] +"\u2C60" => "L" + +# Ɫ [LATIN CAPITAL LETTER L WITH MIDDLE TILDE] +"\u2C62" => "L" + +# Ꝇ [LATIN CAPITAL LETTER BROKEN L] +"\uA746" => "L" + +# Ꝉ [LATIN CAPITAL LETTER L WITH HIGH STROKE] +"\uA748" => "L" + +# Ꞁ [LATIN CAPITAL LETTER TURNED L] +"\uA780" => "L" + +# L [FULLWIDTH LATIN CAPITAL LETTER L] +"\uFF2C" => "L" + +# ĺ [LATIN SMALL LETTER L WITH ACUTE] +"\u013A" => "l" + +# ļ [LATIN SMALL LETTER L WITH CEDILLA] +"\u013C" => "l" + +# ľ [LATIN SMALL LETTER L WITH CARON] +"\u013E" => "l" + +# ŀ [LATIN SMALL LETTER L WITH MIDDLE DOT] +"\u0140" => "l" + +# ł [LATIN SMALL LETTER L WITH STROKE] +"\u0142" => "l" + +# ƚ [LATIN SMALL LETTER L WITH BAR] +"\u019A" => "l" + +# ȴ [LATIN SMALL LETTER L WITH CURL] +"\u0234" => "l" + +# ɫ [LATIN SMALL LETTER L WITH MIDDLE TILDE] +"\u026B" => "l" + +# ɬ [LATIN SMALL LETTER L WITH BELT] +"\u026C" => "l" + +# ɭ [LATIN SMALL LETTER L WITH RETROFLEX HOOK] +"\u026D" => "l" + +# ᶅ [LATIN SMALL LETTER L WITH PALATAL HOOK] +"\u1D85" => "l" + +# ḷ [LATIN SMALL LETTER L WITH DOT BELOW] +"\u1E37" => "l" + +# ḹ [LATIN SMALL LETTER L WITH DOT BELOW AND MACRON] +"\u1E39" => "l" + +# ḻ [LATIN SMALL LETTER L WITH LINE BELOW] +"\u1E3B" => "l" + +# ḽ [LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW] +"\u1E3D" => "l" + +# ⓛ [CIRCLED LATIN SMALL LETTER L] +"\u24DB" => "l" + +# ⱡ [LATIN SMALL LETTER L WITH DOUBLE BAR] +"\u2C61" => "l" + +# ꝇ [LATIN SMALL LETTER BROKEN L] +"\uA747" => "l" + +# ꝉ [LATIN SMALL LETTER L WITH HIGH STROKE] +"\uA749" => "l" + +# ꞁ [LATIN SMALL LETTER TURNED L] +"\uA781" => "l" + +# l [FULLWIDTH LATIN SMALL LETTER L] +"\uFF4C" => "l" + +# LJ [LATIN CAPITAL LETTER LJ] +"\u01C7" => "LJ" + +# Ỻ [LATIN CAPITAL LETTER MIDDLE-WELSH LL] +"\u1EFA" => "LL" + +# Lj [LATIN CAPITAL LETTER L WITH SMALL LETTER J] +"\u01C8" => "Lj" + +# ⒧ [PARENTHESIZED LATIN SMALL LETTER L] +"\u24A7" => "(l)" + +# lj [LATIN SMALL LETTER LJ] +"\u01C9" => "lj" + +# ỻ [LATIN SMALL LETTER MIDDLE-WELSH LL] +"\u1EFB" => "ll" + +# ʪ [LATIN SMALL LETTER LS DIGRAPH] +"\u02AA" => "ls" + +# ʫ [LATIN SMALL LETTER LZ DIGRAPH] +"\u02AB" => "lz" + +# Ɯ [LATIN CAPITAL LETTER TURNED M] +"\u019C" => "M" + +# ᴍ [LATIN LETTER SMALL CAPITAL M] +"\u1D0D" => "M" + +# Ḿ [LATIN CAPITAL LETTER M WITH ACUTE] +"\u1E3E" => "M" + +# Ṁ [LATIN CAPITAL LETTER M WITH DOT ABOVE] +"\u1E40" => "M" + +# Ṃ [LATIN CAPITAL LETTER M WITH DOT BELOW] +"\u1E42" => "M" + +# Ⓜ [CIRCLED LATIN CAPITAL LETTER M] +"\u24C2" => "M" + +# Ɱ [LATIN CAPITAL LETTER M WITH HOOK] +"\u2C6E" => "M" + +# ꟽ [LATIN EPIGRAPHIC LETTER INVERTED M] +"\uA7FD" => "M" + +# ꟿ [LATIN EPIGRAPHIC LETTER ARCHAIC M] +"\uA7FF" => "M" + +# M [FULLWIDTH LATIN CAPITAL LETTER M] +"\uFF2D" => "M" + +# ɯ [LATIN SMALL LETTER TURNED M] +"\u026F" => "m" + +# ɰ [LATIN SMALL LETTER TURNED M WITH LONG LEG] +"\u0270" => "m" + +# ɱ [LATIN SMALL LETTER M WITH HOOK] +"\u0271" => "m" + +# ᵯ [LATIN SMALL LETTER M WITH MIDDLE TILDE] +"\u1D6F" => "m" + +# ᶆ [LATIN SMALL LETTER M WITH PALATAL HOOK] +"\u1D86" => "m" + +# ḿ [LATIN SMALL LETTER M WITH ACUTE] +"\u1E3F" => "m" + +# ṁ [LATIN SMALL LETTER M WITH DOT ABOVE] +"\u1E41" => "m" + +# ṃ [LATIN SMALL LETTER M WITH DOT BELOW] +"\u1E43" => "m" + +# ⓜ [CIRCLED LATIN SMALL LETTER M] +"\u24DC" => "m" + +# m [FULLWIDTH LATIN SMALL LETTER M] +"\uFF4D" => "m" + +# ⒨ [PARENTHESIZED LATIN SMALL LETTER M] +"\u24A8" => "(m)" + +# Ñ [LATIN CAPITAL LETTER N WITH TILDE] +"\u00D1" => "N" + +# Ń [LATIN CAPITAL LETTER N WITH ACUTE] +"\u0143" => "N" + +# Ņ [LATIN CAPITAL LETTER N WITH CEDILLA] +"\u0145" => "N" + +# Ň [LATIN CAPITAL LETTER N WITH CARON] +"\u0147" => "N" + +# Ŋ http://en.wikipedia.org/wiki/Eng_(letter) [LATIN CAPITAL LETTER ENG] +"\u014A" => "N" + +# Ɲ [LATIN CAPITAL LETTER N WITH LEFT HOOK] +"\u019D" => "N" + +# Ǹ [LATIN CAPITAL LETTER N WITH GRAVE] +"\u01F8" => "N" + +# Ƞ [LATIN CAPITAL LETTER N WITH LONG RIGHT LEG] +"\u0220" => "N" + +# ɴ [LATIN LETTER SMALL CAPITAL N] +"\u0274" => "N" + +# ᴎ [LATIN LETTER SMALL CAPITAL REVERSED N] +"\u1D0E" => "N" + +# Ṅ [LATIN CAPITAL LETTER N WITH DOT ABOVE] +"\u1E44" => "N" + +# Ṇ [LATIN CAPITAL LETTER N WITH DOT BELOW] +"\u1E46" => "N" + +# Ṉ [LATIN CAPITAL LETTER N WITH LINE BELOW] +"\u1E48" => "N" + +# Ṋ [LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW] +"\u1E4A" => "N" + +# Ⓝ [CIRCLED LATIN CAPITAL LETTER N] +"\u24C3" => "N" + +# N [FULLWIDTH LATIN CAPITAL LETTER N] +"\uFF2E" => "N" + +# ñ [LATIN SMALL LETTER N WITH TILDE] +"\u00F1" => "n" + +# ń [LATIN SMALL LETTER N WITH ACUTE] +"\u0144" => "n" + +# ņ [LATIN SMALL LETTER N WITH CEDILLA] +"\u0146" => "n" + +# ň [LATIN SMALL LETTER N WITH CARON] +"\u0148" => "n" + +# ʼn [LATIN SMALL LETTER N PRECEDED BY APOSTROPHE] +"\u0149" => "n" + +# ŋ http://en.wikipedia.org/wiki/Eng_(letter) [LATIN SMALL LETTER ENG] +"\u014B" => "n" + +# ƞ [LATIN SMALL LETTER N WITH LONG RIGHT LEG] +"\u019E" => "n" + +# ǹ [LATIN SMALL LETTER N WITH GRAVE] +"\u01F9" => "n" + +# ȵ [LATIN SMALL LETTER N WITH CURL] +"\u0235" => "n" + +# ɲ [LATIN SMALL LETTER N WITH LEFT HOOK] +"\u0272" => "n" + +# ɳ [LATIN SMALL LETTER N WITH RETROFLEX HOOK] +"\u0273" => "n" + +# ᵰ [LATIN SMALL LETTER N WITH MIDDLE TILDE] +"\u1D70" => "n" + +# ᶇ [LATIN SMALL LETTER N WITH PALATAL HOOK] +"\u1D87" => "n" + +# ṅ [LATIN SMALL LETTER N WITH DOT ABOVE] +"\u1E45" => "n" + +# ṇ [LATIN SMALL LETTER N WITH DOT BELOW] +"\u1E47" => "n" + +# ṉ [LATIN SMALL LETTER N WITH LINE BELOW] +"\u1E49" => "n" + +# ṋ [LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW] +"\u1E4B" => "n" + +# ⁿ [SUPERSCRIPT LATIN SMALL LETTER N] +"\u207F" => "n" + +# ⓝ [CIRCLED LATIN SMALL LETTER N] +"\u24DD" => "n" + +# n [FULLWIDTH LATIN SMALL LETTER N] +"\uFF4E" => "n" + +# NJ [LATIN CAPITAL LETTER NJ] +"\u01CA" => "NJ" + +# Nj [LATIN CAPITAL LETTER N WITH SMALL LETTER J] +"\u01CB" => "Nj" + +# ⒩ [PARENTHESIZED LATIN SMALL LETTER N] +"\u24A9" => "(n)" + +# nj [LATIN SMALL LETTER NJ] +"\u01CC" => "nj" + +# Ò [LATIN CAPITAL LETTER O WITH GRAVE] +"\u00D2" => "O" + +# Ó [LATIN CAPITAL LETTER O WITH ACUTE] +"\u00D3" => "O" + +# Ô [LATIN CAPITAL LETTER O WITH CIRCUMFLEX] +"\u00D4" => "O" + +# Õ [LATIN CAPITAL LETTER O WITH TILDE] +"\u00D5" => "O" + +# Ö [LATIN CAPITAL LETTER O WITH DIAERESIS] +"\u00D6" => "O" + +# Ø [LATIN CAPITAL LETTER O WITH STROKE] +"\u00D8" => "O" + +# Ō [LATIN CAPITAL LETTER O WITH MACRON] +"\u014C" => "O" + +# Ŏ [LATIN CAPITAL LETTER O WITH BREVE] +"\u014E" => "O" + +# Ő [LATIN CAPITAL LETTER O WITH DOUBLE ACUTE] +"\u0150" => "O" + +# Ɔ [LATIN CAPITAL LETTER OPEN O] +"\u0186" => "O" + +# Ɵ [LATIN CAPITAL LETTER O WITH MIDDLE TILDE] +"\u019F" => "O" + +# Ơ [LATIN CAPITAL LETTER O WITH HORN] +"\u01A0" => "O" + +# Ǒ [LATIN CAPITAL LETTER O WITH CARON] +"\u01D1" => "O" + +# Ǫ [LATIN CAPITAL LETTER O WITH OGONEK] +"\u01EA" => "O" + +# Ǭ [LATIN CAPITAL LETTER O WITH OGONEK AND MACRON] +"\u01EC" => "O" + +# Ǿ [LATIN CAPITAL LETTER O WITH STROKE AND ACUTE] +"\u01FE" => "O" + +# Ȍ [LATIN CAPITAL LETTER O WITH DOUBLE GRAVE] +"\u020C" => "O" + +# Ȏ [LATIN CAPITAL LETTER O WITH INVERTED BREVE] +"\u020E" => "O" + +# Ȫ [LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON] +"\u022A" => "O" + +# Ȭ [LATIN CAPITAL LETTER O WITH TILDE AND MACRON] +"\u022C" => "O" + +# Ȯ [LATIN CAPITAL LETTER O WITH DOT ABOVE] +"\u022E" => "O" + +# Ȱ [LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON] +"\u0230" => "O" + +# ᴏ [LATIN LETTER SMALL CAPITAL O] +"\u1D0F" => "O" + +# ᴐ [LATIN LETTER SMALL CAPITAL OPEN O] +"\u1D10" => "O" + +# Ṍ [LATIN CAPITAL LETTER O WITH TILDE AND ACUTE] +"\u1E4C" => "O" + +# Ṏ [LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS] +"\u1E4E" => "O" + +# Ṑ [LATIN CAPITAL LETTER O WITH MACRON AND GRAVE] +"\u1E50" => "O" + +# Ṓ [LATIN CAPITAL LETTER O WITH MACRON AND ACUTE] +"\u1E52" => "O" + +# Ọ [LATIN CAPITAL LETTER O WITH DOT BELOW] +"\u1ECC" => "O" + +# Ỏ [LATIN CAPITAL LETTER O WITH HOOK ABOVE] +"\u1ECE" => "O" + +# Ố [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE] +"\u1ED0" => "O" + +# Ồ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE] +"\u1ED2" => "O" + +# Ổ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1ED4" => "O" + +# Ỗ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE] +"\u1ED6" => "O" + +# Ộ [LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW] +"\u1ED8" => "O" + +# Ớ [LATIN CAPITAL LETTER O WITH HORN AND ACUTE] +"\u1EDA" => "O" + +# Ờ [LATIN CAPITAL LETTER O WITH HORN AND GRAVE] +"\u1EDC" => "O" + +# Ở [LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE] +"\u1EDE" => "O" + +# Ỡ [LATIN CAPITAL LETTER O WITH HORN AND TILDE] +"\u1EE0" => "O" + +# Ợ [LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW] +"\u1EE2" => "O" + +# Ⓞ [CIRCLED LATIN CAPITAL LETTER O] +"\u24C4" => "O" + +# Ꝋ [LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY] +"\uA74A" => "O" + +# Ꝍ [LATIN CAPITAL LETTER O WITH LOOP] +"\uA74C" => "O" + +# O [FULLWIDTH LATIN CAPITAL LETTER O] +"\uFF2F" => "O" + +# ò [LATIN SMALL LETTER O WITH GRAVE] +"\u00F2" => "o" + +# ó [LATIN SMALL LETTER O WITH ACUTE] +"\u00F3" => "o" + +# ô [LATIN SMALL LETTER O WITH CIRCUMFLEX] +"\u00F4" => "o" + +# õ [LATIN SMALL LETTER O WITH TILDE] +"\u00F5" => "o" + +# ö [LATIN SMALL LETTER O WITH DIAERESIS] +"\u00F6" => "o" + +# ø [LATIN SMALL LETTER O WITH STROKE] +"\u00F8" => "o" + +# ō [LATIN SMALL LETTER O WITH MACRON] +"\u014D" => "o" + +# ŏ [LATIN SMALL LETTER O WITH BREVE] +"\u014F" => "o" + +# ő [LATIN SMALL LETTER O WITH DOUBLE ACUTE] +"\u0151" => "o" + +# ơ [LATIN SMALL LETTER O WITH HORN] +"\u01A1" => "o" + +# ǒ [LATIN SMALL LETTER O WITH CARON] +"\u01D2" => "o" + +# ǫ [LATIN SMALL LETTER O WITH OGONEK] +"\u01EB" => "o" + +# ǭ [LATIN SMALL LETTER O WITH OGONEK AND MACRON] +"\u01ED" => "o" + +# ǿ [LATIN SMALL LETTER O WITH STROKE AND ACUTE] +"\u01FF" => "o" + +# ȍ [LATIN SMALL LETTER O WITH DOUBLE GRAVE] +"\u020D" => "o" + +# ȏ [LATIN SMALL LETTER O WITH INVERTED BREVE] +"\u020F" => "o" + +# ȫ [LATIN SMALL LETTER O WITH DIAERESIS AND MACRON] +"\u022B" => "o" + +# ȭ [LATIN SMALL LETTER O WITH TILDE AND MACRON] +"\u022D" => "o" + +# ȯ [LATIN SMALL LETTER O WITH DOT ABOVE] +"\u022F" => "o" + +# ȱ [LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON] +"\u0231" => "o" + +# ɔ [LATIN SMALL LETTER OPEN O] +"\u0254" => "o" + +# ɵ [LATIN SMALL LETTER BARRED O] +"\u0275" => "o" + +# ᴖ [LATIN SMALL LETTER TOP HALF O] +"\u1D16" => "o" + +# ᴗ [LATIN SMALL LETTER BOTTOM HALF O] +"\u1D17" => "o" + +# ᶗ [LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK] +"\u1D97" => "o" + +# ṍ [LATIN SMALL LETTER O WITH TILDE AND ACUTE] +"\u1E4D" => "o" + +# ṏ [LATIN SMALL LETTER O WITH TILDE AND DIAERESIS] +"\u1E4F" => "o" + +# ṑ [LATIN SMALL LETTER O WITH MACRON AND GRAVE] +"\u1E51" => "o" + +# ṓ [LATIN SMALL LETTER O WITH MACRON AND ACUTE] +"\u1E53" => "o" + +# ọ [LATIN SMALL LETTER O WITH DOT BELOW] +"\u1ECD" => "o" + +# ỏ [LATIN SMALL LETTER O WITH HOOK ABOVE] +"\u1ECF" => "o" + +# ố [LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE] +"\u1ED1" => "o" + +# ồ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE] +"\u1ED3" => "o" + +# ổ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE] +"\u1ED5" => "o" + +# ỗ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE] +"\u1ED7" => "o" + +# ộ [LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW] +"\u1ED9" => "o" + +# ớ [LATIN SMALL LETTER O WITH HORN AND ACUTE] +"\u1EDB" => "o" + +# ờ [LATIN SMALL LETTER O WITH HORN AND GRAVE] +"\u1EDD" => "o" + +# ở [LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE] +"\u1EDF" => "o" + +# ỡ [LATIN SMALL LETTER O WITH HORN AND TILDE] +"\u1EE1" => "o" + +# ợ [LATIN SMALL LETTER O WITH HORN AND DOT BELOW] +"\u1EE3" => "o" + +# ₒ [LATIN SUBSCRIPT SMALL LETTER O] +"\u2092" => "o" + +# ⓞ [CIRCLED LATIN SMALL LETTER O] +"\u24DE" => "o" + +# ⱺ [LATIN SMALL LETTER O WITH LOW RING INSIDE] +"\u2C7A" => "o" + +# ꝋ [LATIN SMALL LETTER O WITH LONG STROKE OVERLAY] +"\uA74B" => "o" + +# ꝍ [LATIN SMALL LETTER O WITH LOOP] +"\uA74D" => "o" + +# o [FULLWIDTH LATIN SMALL LETTER O] +"\uFF4F" => "o" + +# Œ [LATIN CAPITAL LIGATURE OE] +"\u0152" => "OE" + +# ɶ [LATIN LETTER SMALL CAPITAL OE] +"\u0276" => "OE" + +# Ꝏ [LATIN CAPITAL LETTER OO] +"\uA74E" => "OO" + +# Ȣ http://en.wikipedia.org/wiki/OU [LATIN CAPITAL LETTER OU] +"\u0222" => "OU" + +# ᴕ [LATIN LETTER SMALL CAPITAL OU] +"\u1D15" => "OU" + +# ⒪ [PARENTHESIZED LATIN SMALL LETTER O] +"\u24AA" => "(o)" + +# œ [LATIN SMALL LIGATURE OE] +"\u0153" => "oe" + +# ᴔ [LATIN SMALL LETTER TURNED OE] +"\u1D14" => "oe" + +# ꝏ [LATIN SMALL LETTER OO] +"\uA74F" => "oo" + +# ȣ http://en.wikipedia.org/wiki/OU [LATIN SMALL LETTER OU] +"\u0223" => "ou" + +# Ƥ [LATIN CAPITAL LETTER P WITH HOOK] +"\u01A4" => "P" + +# ᴘ [LATIN LETTER SMALL CAPITAL P] +"\u1D18" => "P" + +# Ṕ [LATIN CAPITAL LETTER P WITH ACUTE] +"\u1E54" => "P" + +# Ṗ [LATIN CAPITAL LETTER P WITH DOT ABOVE] +"\u1E56" => "P" + +# Ⓟ [CIRCLED LATIN CAPITAL LETTER P] +"\u24C5" => "P" + +# Ᵽ [LATIN CAPITAL LETTER P WITH STROKE] +"\u2C63" => "P" + +# Ꝑ [LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER] +"\uA750" => "P" + +# Ꝓ [LATIN CAPITAL LETTER P WITH FLOURISH] +"\uA752" => "P" + +# Ꝕ [LATIN CAPITAL LETTER P WITH SQUIRREL TAIL] +"\uA754" => "P" + +# P [FULLWIDTH LATIN CAPITAL LETTER P] +"\uFF30" => "P" + +# ƥ [LATIN SMALL LETTER P WITH HOOK] +"\u01A5" => "p" + +# ᵱ [LATIN SMALL LETTER P WITH MIDDLE TILDE] +"\u1D71" => "p" + +# ᵽ [LATIN SMALL LETTER P WITH STROKE] +"\u1D7D" => "p" + +# ᶈ [LATIN SMALL LETTER P WITH PALATAL HOOK] +"\u1D88" => "p" + +# ṕ [LATIN SMALL LETTER P WITH ACUTE] +"\u1E55" => "p" + +# ṗ [LATIN SMALL LETTER P WITH DOT ABOVE] +"\u1E57" => "p" + +# ⓟ [CIRCLED LATIN SMALL LETTER P] +"\u24DF" => "p" + +# ꝑ [LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER] +"\uA751" => "p" + +# ꝓ [LATIN SMALL LETTER P WITH FLOURISH] +"\uA753" => "p" + +# ꝕ [LATIN SMALL LETTER P WITH SQUIRREL TAIL] +"\uA755" => "p" + +# ꟼ [LATIN EPIGRAPHIC LETTER REVERSED P] +"\uA7FC" => "p" + +# p [FULLWIDTH LATIN SMALL LETTER P] +"\uFF50" => "p" + +# ⒫ [PARENTHESIZED LATIN SMALL LETTER P] +"\u24AB" => "(p)" + +# Ɋ [LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL] +"\u024A" => "Q" + +# Ⓠ [CIRCLED LATIN CAPITAL LETTER Q] +"\u24C6" => "Q" + +# Ꝗ [LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER] +"\uA756" => "Q" + +# Ꝙ [LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE] +"\uA758" => "Q" + +# Q [FULLWIDTH LATIN CAPITAL LETTER Q] +"\uFF31" => "Q" + +# ĸ http://en.wikipedia.org/wiki/Kra_(letter) [LATIN SMALL LETTER KRA] +"\u0138" => "q" + +# ɋ [LATIN SMALL LETTER Q WITH HOOK TAIL] +"\u024B" => "q" + +# ʠ [LATIN SMALL LETTER Q WITH HOOK] +"\u02A0" => "q" + +# ⓠ [CIRCLED LATIN SMALL LETTER Q] +"\u24E0" => "q" + +# ꝗ [LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER] +"\uA757" => "q" + +# ꝙ [LATIN SMALL LETTER Q WITH DIAGONAL STROKE] +"\uA759" => "q" + +# q [FULLWIDTH LATIN SMALL LETTER Q] +"\uFF51" => "q" + +# ⒬ [PARENTHESIZED LATIN SMALL LETTER Q] +"\u24AC" => "(q)" + +# ȹ [LATIN SMALL LETTER QP DIGRAPH] +"\u0239" => "qp" + +# Ŕ [LATIN CAPITAL LETTER R WITH ACUTE] +"\u0154" => "R" + +# Ŗ [LATIN CAPITAL LETTER R WITH CEDILLA] +"\u0156" => "R" + +# Ř [LATIN CAPITAL LETTER R WITH CARON] +"\u0158" => "R" + +# Ȓ [LATIN CAPITAL LETTER R WITH DOUBLE GRAVE] +"\u0210" => "R" + +# Ȓ [LATIN CAPITAL LETTER R WITH INVERTED BREVE] +"\u0212" => "R" + +# Ɍ [LATIN CAPITAL LETTER R WITH STROKE] +"\u024C" => "R" + +# ʀ [LATIN LETTER SMALL CAPITAL R] +"\u0280" => "R" + +# ʁ [LATIN LETTER SMALL CAPITAL INVERTED R] +"\u0281" => "R" + +# ᴙ [LATIN LETTER SMALL CAPITAL REVERSED R] +"\u1D19" => "R" + +# ᴚ [LATIN LETTER SMALL CAPITAL TURNED R] +"\u1D1A" => "R" + +# Ṙ [LATIN CAPITAL LETTER R WITH DOT ABOVE] +"\u1E58" => "R" + +# Ṛ [LATIN CAPITAL LETTER R WITH DOT BELOW] +"\u1E5A" => "R" + +# Ṝ [LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON] +"\u1E5C" => "R" + +# Ṟ [LATIN CAPITAL LETTER R WITH LINE BELOW] +"\u1E5E" => "R" + +# Ⓡ [CIRCLED LATIN CAPITAL LETTER R] +"\u24C7" => "R" + +# Ɽ [LATIN CAPITAL LETTER R WITH TAIL] +"\u2C64" => "R" + +# Ꝛ [LATIN CAPITAL LETTER R ROTUNDA] +"\uA75A" => "R" + +# Ꞃ [LATIN CAPITAL LETTER INSULAR R] +"\uA782" => "R" + +# R [FULLWIDTH LATIN CAPITAL LETTER R] +"\uFF32" => "R" + +# ŕ [LATIN SMALL LETTER R WITH ACUTE] +"\u0155" => "r" + +# ŗ [LATIN SMALL LETTER R WITH CEDILLA] +"\u0157" => "r" + +# ř [LATIN SMALL LETTER R WITH CARON] +"\u0159" => "r" + +# ȑ [LATIN SMALL LETTER R WITH DOUBLE GRAVE] +"\u0211" => "r" + +# ȓ [LATIN SMALL LETTER R WITH INVERTED BREVE] +"\u0213" => "r" + +# ɍ [LATIN SMALL LETTER R WITH STROKE] +"\u024D" => "r" + +# ɼ [LATIN SMALL LETTER R WITH LONG LEG] +"\u027C" => "r" + +# ɽ [LATIN SMALL LETTER R WITH TAIL] +"\u027D" => "r" + +# ɾ [LATIN SMALL LETTER R WITH FISHHOOK] +"\u027E" => "r" + +# ɿ [LATIN SMALL LETTER REVERSED R WITH FISHHOOK] +"\u027F" => "r" + +# ᵣ [LATIN SUBSCRIPT SMALL LETTER R] +"\u1D63" => "r" + +# ᵲ [LATIN SMALL LETTER R WITH MIDDLE TILDE] +"\u1D72" => "r" + +# ᵳ [LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE] +"\u1D73" => "r" + +# ᶉ [LATIN SMALL LETTER R WITH PALATAL HOOK] +"\u1D89" => "r" + +# ṙ [LATIN SMALL LETTER R WITH DOT ABOVE] +"\u1E59" => "r" + +# ṛ [LATIN SMALL LETTER R WITH DOT BELOW] +"\u1E5B" => "r" + +# ṝ [LATIN SMALL LETTER R WITH DOT BELOW AND MACRON] +"\u1E5D" => "r" + +# ṟ [LATIN SMALL LETTER R WITH LINE BELOW] +"\u1E5F" => "r" + +# ⓡ [CIRCLED LATIN SMALL LETTER R] +"\u24E1" => "r" + +# ꝛ [LATIN SMALL LETTER R ROTUNDA] +"\uA75B" => "r" + +# ꞃ [LATIN SMALL LETTER INSULAR R] +"\uA783" => "r" + +# r [FULLWIDTH LATIN SMALL LETTER R] +"\uFF52" => "r" + +# ⒭ [PARENTHESIZED LATIN SMALL LETTER R] +"\u24AD" => "(r)" + +# Ś [LATIN CAPITAL LETTER S WITH ACUTE] +"\u015A" => "S" + +# Ŝ [LATIN CAPITAL LETTER S WITH CIRCUMFLEX] +"\u015C" => "S" + +# Ş [LATIN CAPITAL LETTER S WITH CEDILLA] +"\u015E" => "S" + +# Š [LATIN CAPITAL LETTER S WITH CARON] +"\u0160" => "S" + +# Ș [LATIN CAPITAL LETTER S WITH COMMA BELOW] +"\u0218" => "S" + +# Ṡ [LATIN CAPITAL LETTER S WITH DOT ABOVE] +"\u1E60" => "S" + +# Ṣ [LATIN CAPITAL LETTER S WITH DOT BELOW] +"\u1E62" => "S" + +# Ṥ [LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE] +"\u1E64" => "S" + +# Ṧ [LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE] +"\u1E66" => "S" + +# Ṩ [LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE] +"\u1E68" => "S" + +# Ⓢ [CIRCLED LATIN CAPITAL LETTER S] +"\u24C8" => "S" + +# ꜱ [LATIN LETTER SMALL CAPITAL S] +"\uA731" => "S" + +# ꞅ [LATIN SMALL LETTER INSULAR S] +"\uA785" => "S" + +# S [FULLWIDTH LATIN CAPITAL LETTER S] +"\uFF33" => "S" + +# ś [LATIN SMALL LETTER S WITH ACUTE] +"\u015B" => "s" + +# ŝ [LATIN SMALL LETTER S WITH CIRCUMFLEX] +"\u015D" => "s" + +# ş [LATIN SMALL LETTER S WITH CEDILLA] +"\u015F" => "s" + +# š [LATIN SMALL LETTER S WITH CARON] +"\u0161" => "s" + +# ſ http://en.wikipedia.org/wiki/Long_S [LATIN SMALL LETTER LONG S] +"\u017F" => "s" + +# ș [LATIN SMALL LETTER S WITH COMMA BELOW] +"\u0219" => "s" + +# ȿ [LATIN SMALL LETTER S WITH SWASH TAIL] +"\u023F" => "s" + +# ʂ [LATIN SMALL LETTER S WITH HOOK] +"\u0282" => "s" + +# ᵴ [LATIN SMALL LETTER S WITH MIDDLE TILDE] +"\u1D74" => "s" + +# ᶊ [LATIN SMALL LETTER S WITH PALATAL HOOK] +"\u1D8A" => "s" + +# ṡ [LATIN SMALL LETTER S WITH DOT ABOVE] +"\u1E61" => "s" + +# ṣ [LATIN SMALL LETTER S WITH DOT BELOW] +"\u1E63" => "s" + +# ṥ [LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE] +"\u1E65" => "s" + +# ṧ [LATIN SMALL LETTER S WITH CARON AND DOT ABOVE] +"\u1E67" => "s" + +# ṩ [LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE] +"\u1E69" => "s" + +# ẜ [LATIN SMALL LETTER LONG S WITH DIAGONAL STROKE] +"\u1E9C" => "s" + +# ẝ [LATIN SMALL LETTER LONG S WITH HIGH STROKE] +"\u1E9D" => "s" + +# ⓢ [CIRCLED LATIN SMALL LETTER S] +"\u24E2" => "s" + +# Ꞅ [LATIN CAPITAL LETTER INSULAR S] +"\uA784" => "s" + +# s [FULLWIDTH LATIN SMALL LETTER S] +"\uFF53" => "s" + +# ẞ [LATIN CAPITAL LETTER SHARP S] +"\u1E9E" => "SS" + +# ⒮ [PARENTHESIZED LATIN SMALL LETTER S] +"\u24AE" => "(s)" + +# ß [LATIN SMALL LETTER SHARP S] +"\u00DF" => "ss" + +# st [LATIN SMALL LIGATURE ST] +"\uFB06" => "st" + +# Ţ [LATIN CAPITAL LETTER T WITH CEDILLA] +"\u0162" => "T" + +# Ť [LATIN CAPITAL LETTER T WITH CARON] +"\u0164" => "T" + +# Ŧ [LATIN CAPITAL LETTER T WITH STROKE] +"\u0166" => "T" + +# Ƭ [LATIN CAPITAL LETTER T WITH HOOK] +"\u01AC" => "T" + +# Ʈ [LATIN CAPITAL LETTER T WITH RETROFLEX HOOK] +"\u01AE" => "T" + +# Ț [LATIN CAPITAL LETTER T WITH COMMA BELOW] +"\u021A" => "T" + +# Ⱦ [LATIN CAPITAL LETTER T WITH DIAGONAL STROKE] +"\u023E" => "T" + +# ᴛ [LATIN LETTER SMALL CAPITAL T] +"\u1D1B" => "T" + +# Ṫ [LATIN CAPITAL LETTER T WITH DOT ABOVE] +"\u1E6A" => "T" + +# Ṭ [LATIN CAPITAL LETTER T WITH DOT BELOW] +"\u1E6C" => "T" + +# Ṯ [LATIN CAPITAL LETTER T WITH LINE BELOW] +"\u1E6E" => "T" + +# Ṱ [LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW] +"\u1E70" => "T" + +# Ⓣ [CIRCLED LATIN CAPITAL LETTER T] +"\u24C9" => "T" + +# Ꞇ [LATIN CAPITAL LETTER INSULAR T] +"\uA786" => "T" + +# T [FULLWIDTH LATIN CAPITAL LETTER T] +"\uFF34" => "T" + +# ţ [LATIN SMALL LETTER T WITH CEDILLA] +"\u0163" => "t" + +# ť [LATIN SMALL LETTER T WITH CARON] +"\u0165" => "t" + +# ŧ [LATIN SMALL LETTER T WITH STROKE] +"\u0167" => "t" + +# ƫ [LATIN SMALL LETTER T WITH PALATAL HOOK] +"\u01AB" => "t" + +# ƭ [LATIN SMALL LETTER T WITH HOOK] +"\u01AD" => "t" + +# ț [LATIN SMALL LETTER T WITH COMMA BELOW] +"\u021B" => "t" + +# ȶ [LATIN SMALL LETTER T WITH CURL] +"\u0236" => "t" + +# ʇ [LATIN SMALL LETTER TURNED T] +"\u0287" => "t" + +# ʈ [LATIN SMALL LETTER T WITH RETROFLEX HOOK] +"\u0288" => "t" + +# ᵵ [LATIN SMALL LETTER T WITH MIDDLE TILDE] +"\u1D75" => "t" + +# ṫ [LATIN SMALL LETTER T WITH DOT ABOVE] +"\u1E6B" => "t" + +# ṭ [LATIN SMALL LETTER T WITH DOT BELOW] +"\u1E6D" => "t" + +# ṯ [LATIN SMALL LETTER T WITH LINE BELOW] +"\u1E6F" => "t" + +# ṱ [LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW] +"\u1E71" => "t" + +# ẗ [LATIN SMALL LETTER T WITH DIAERESIS] +"\u1E97" => "t" + +# ⓣ [CIRCLED LATIN SMALL LETTER T] +"\u24E3" => "t" + +# ⱦ [LATIN SMALL LETTER T WITH DIAGONAL STROKE] +"\u2C66" => "t" + +# t [FULLWIDTH LATIN SMALL LETTER T] +"\uFF54" => "t" + +# Þ [LATIN CAPITAL LETTER THORN] +"\u00DE" => "TH" + +# Ꝧ [LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER] +"\uA766" => "TH" + +# Ꜩ [LATIN CAPITAL LETTER TZ] +"\uA728" => "TZ" + +# ⒯ [PARENTHESIZED LATIN SMALL LETTER T] +"\u24AF" => "(t)" + +# ʨ [LATIN SMALL LETTER TC DIGRAPH WITH CURL] +"\u02A8" => "tc" + +# þ [LATIN SMALL LETTER THORN] +"\u00FE" => "th" + +# ᵺ [LATIN SMALL LETTER TH WITH STRIKETHROUGH] +"\u1D7A" => "th" + +# ꝧ [LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER] +"\uA767" => "th" + +# ʦ [LATIN SMALL LETTER TS DIGRAPH] +"\u02A6" => "ts" + +# ꜩ [LATIN SMALL LETTER TZ] +"\uA729" => "tz" + +# Ù [LATIN CAPITAL LETTER U WITH GRAVE] +"\u00D9" => "U" + +# Ú [LATIN CAPITAL LETTER U WITH ACUTE] +"\u00DA" => "U" + +# Û [LATIN CAPITAL LETTER U WITH CIRCUMFLEX] +"\u00DB" => "U" + +# Ü [LATIN CAPITAL LETTER U WITH DIAERESIS] +"\u00DC" => "U" + +# Ũ [LATIN CAPITAL LETTER U WITH TILDE] +"\u0168" => "U" + +# Ū [LATIN CAPITAL LETTER U WITH MACRON] +"\u016A" => "U" + +# Ŭ [LATIN CAPITAL LETTER U WITH BREVE] +"\u016C" => "U" + +# Ů [LATIN CAPITAL LETTER U WITH RING ABOVE] +"\u016E" => "U" + +# Ű [LATIN CAPITAL LETTER U WITH DOUBLE ACUTE] +"\u0170" => "U" + +# Ų [LATIN CAPITAL LETTER U WITH OGONEK] +"\u0172" => "U" + +# Ư [LATIN CAPITAL LETTER U WITH HORN] +"\u01AF" => "U" + +# Ǔ [LATIN CAPITAL LETTER U WITH CARON] +"\u01D3" => "U" + +# Ǖ [LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON] +"\u01D5" => "U" + +# Ǘ [LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE] +"\u01D7" => "U" + +# Ǚ [LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON] +"\u01D9" => "U" + +# Ǜ [LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE] +"\u01DB" => "U" + +# Ȕ [LATIN CAPITAL LETTER U WITH DOUBLE GRAVE] +"\u0214" => "U" + +# Ȗ [LATIN CAPITAL LETTER U WITH INVERTED BREVE] +"\u0216" => "U" + +# Ʉ [LATIN CAPITAL LETTER U BAR] +"\u0244" => "U" + +# ᴜ [LATIN LETTER SMALL CAPITAL U] +"\u1D1C" => "U" + +# ᵾ [LATIN SMALL CAPITAL LETTER U WITH STROKE] +"\u1D7E" => "U" + +# Ṳ [LATIN CAPITAL LETTER U WITH DIAERESIS BELOW] +"\u1E72" => "U" + +# Ṵ [LATIN CAPITAL LETTER U WITH TILDE BELOW] +"\u1E74" => "U" + +# Ṷ [LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW] +"\u1E76" => "U" + +# Ṹ [LATIN CAPITAL LETTER U WITH TILDE AND ACUTE] +"\u1E78" => "U" + +# Ṻ [LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS] +"\u1E7A" => "U" + +# Ụ [LATIN CAPITAL LETTER U WITH DOT BELOW] +"\u1EE4" => "U" + +# Ủ [LATIN CAPITAL LETTER U WITH HOOK ABOVE] +"\u1EE6" => "U" + +# Ứ [LATIN CAPITAL LETTER U WITH HORN AND ACUTE] +"\u1EE8" => "U" + +# Ừ [LATIN CAPITAL LETTER U WITH HORN AND GRAVE] +"\u1EEA" => "U" + +# Ử [LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE] +"\u1EEC" => "U" + +# Ữ [LATIN CAPITAL LETTER U WITH HORN AND TILDE] +"\u1EEE" => "U" + +# Ự [LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW] +"\u1EF0" => "U" + +# Ⓤ [CIRCLED LATIN CAPITAL LETTER U] +"\u24CA" => "U" + +# U [FULLWIDTH LATIN CAPITAL LETTER U] +"\uFF35" => "U" + +# ù [LATIN SMALL LETTER U WITH GRAVE] +"\u00F9" => "u" + +# ú [LATIN SMALL LETTER U WITH ACUTE] +"\u00FA" => "u" + +# û [LATIN SMALL LETTER U WITH CIRCUMFLEX] +"\u00FB" => "u" + +# ü [LATIN SMALL LETTER U WITH DIAERESIS] +"\u00FC" => "u" + +# ũ [LATIN SMALL LETTER U WITH TILDE] +"\u0169" => "u" + +# ū [LATIN SMALL LETTER U WITH MACRON] +"\u016B" => "u" + +# ŭ [LATIN SMALL LETTER U WITH BREVE] +"\u016D" => "u" + +# ů [LATIN SMALL LETTER U WITH RING ABOVE] +"\u016F" => "u" + +# ű [LATIN SMALL LETTER U WITH DOUBLE ACUTE] +"\u0171" => "u" + +# ų [LATIN SMALL LETTER U WITH OGONEK] +"\u0173" => "u" + +# ư [LATIN SMALL LETTER U WITH HORN] +"\u01B0" => "u" + +# ǔ [LATIN SMALL LETTER U WITH CARON] +"\u01D4" => "u" + +# ǖ [LATIN SMALL LETTER U WITH DIAERESIS AND MACRON] +"\u01D6" => "u" + +# ǘ [LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE] +"\u01D8" => "u" + +# ǚ [LATIN SMALL LETTER U WITH DIAERESIS AND CARON] +"\u01DA" => "u" + +# ǜ [LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE] +"\u01DC" => "u" + +# ȕ [LATIN SMALL LETTER U WITH DOUBLE GRAVE] +"\u0215" => "u" + +# ȗ [LATIN SMALL LETTER U WITH INVERTED BREVE] +"\u0217" => "u" + +# ʉ [LATIN SMALL LETTER U BAR] +"\u0289" => "u" + +# ᵤ [LATIN SUBSCRIPT SMALL LETTER U] +"\u1D64" => "u" + +# ᶙ [LATIN SMALL LETTER U WITH RETROFLEX HOOK] +"\u1D99" => "u" + +# ṳ [LATIN SMALL LETTER U WITH DIAERESIS BELOW] +"\u1E73" => "u" + +# ṵ [LATIN SMALL LETTER U WITH TILDE BELOW] +"\u1E75" => "u" + +# ṷ [LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW] +"\u1E77" => "u" + +# ṹ [LATIN SMALL LETTER U WITH TILDE AND ACUTE] +"\u1E79" => "u" + +# ṻ [LATIN SMALL LETTER U WITH MACRON AND DIAERESIS] +"\u1E7B" => "u" + +# ụ [LATIN SMALL LETTER U WITH DOT BELOW] +"\u1EE5" => "u" + +# ủ [LATIN SMALL LETTER U WITH HOOK ABOVE] +"\u1EE7" => "u" + +# ứ [LATIN SMALL LETTER U WITH HORN AND ACUTE] +"\u1EE9" => "u" + +# ừ [LATIN SMALL LETTER U WITH HORN AND GRAVE] +"\u1EEB" => "u" + +# ử [LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE] +"\u1EED" => "u" + +# ữ [LATIN SMALL LETTER U WITH HORN AND TILDE] +"\u1EEF" => "u" + +# ự [LATIN SMALL LETTER U WITH HORN AND DOT BELOW] +"\u1EF1" => "u" + +# ⓤ [CIRCLED LATIN SMALL LETTER U] +"\u24E4" => "u" + +# u [FULLWIDTH LATIN SMALL LETTER U] +"\uFF55" => "u" + +# ⒰ [PARENTHESIZED LATIN SMALL LETTER U] +"\u24B0" => "(u)" + +# ᵫ [LATIN SMALL LETTER UE] +"\u1D6B" => "ue" + +# Ʋ [LATIN CAPITAL LETTER V WITH HOOK] +"\u01B2" => "V" + +# Ʌ [LATIN CAPITAL LETTER TURNED V] +"\u0245" => "V" + +# ᴠ [LATIN LETTER SMALL CAPITAL V] +"\u1D20" => "V" + +# Ṽ [LATIN CAPITAL LETTER V WITH TILDE] +"\u1E7C" => "V" + +# Ṿ [LATIN CAPITAL LETTER V WITH DOT BELOW] +"\u1E7E" => "V" + +# Ỽ [LATIN CAPITAL LETTER MIDDLE-WELSH V] +"\u1EFC" => "V" + +# Ⓥ [CIRCLED LATIN CAPITAL LETTER V] +"\u24CB" => "V" + +# Ꝟ [LATIN CAPITAL LETTER V WITH DIAGONAL STROKE] +"\uA75E" => "V" + +# Ꝩ [LATIN CAPITAL LETTER VEND] +"\uA768" => "V" + +# V [FULLWIDTH LATIN CAPITAL LETTER V] +"\uFF36" => "V" + +# ʋ [LATIN SMALL LETTER V WITH HOOK] +"\u028B" => "v" + +# ʌ [LATIN SMALL LETTER TURNED V] +"\u028C" => "v" + +# ᵥ [LATIN SUBSCRIPT SMALL LETTER V] +"\u1D65" => "v" + +# ᶌ [LATIN SMALL LETTER V WITH PALATAL HOOK] +"\u1D8C" => "v" + +# ṽ [LATIN SMALL LETTER V WITH TILDE] +"\u1E7D" => "v" + +# ṿ [LATIN SMALL LETTER V WITH DOT BELOW] +"\u1E7F" => "v" + +# ⓥ [CIRCLED LATIN SMALL LETTER V] +"\u24E5" => "v" + +# ⱱ [LATIN SMALL LETTER V WITH RIGHT HOOK] +"\u2C71" => "v" + +# ⱴ [LATIN SMALL LETTER V WITH CURL] +"\u2C74" => "v" + +# ꝟ [LATIN SMALL LETTER V WITH DIAGONAL STROKE] +"\uA75F" => "v" + +# v [FULLWIDTH LATIN SMALL LETTER V] +"\uFF56" => "v" + +# Ꝡ [LATIN CAPITAL LETTER VY] +"\uA760" => "VY" + +# ⒱ [PARENTHESIZED LATIN SMALL LETTER V] +"\u24B1" => "(v)" + +# ꝡ [LATIN SMALL LETTER VY] +"\uA761" => "vy" + +# Ŵ [LATIN CAPITAL LETTER W WITH CIRCUMFLEX] +"\u0174" => "W" + +# Ƿ http://en.wikipedia.org/wiki/Wynn [LATIN CAPITAL LETTER WYNN] +"\u01F7" => "W" + +# ᴡ [LATIN LETTER SMALL CAPITAL W] +"\u1D21" => "W" + +# Ẁ [LATIN CAPITAL LETTER W WITH GRAVE] +"\u1E80" => "W" + +# Ẃ [LATIN CAPITAL LETTER W WITH ACUTE] +"\u1E82" => "W" + +# Ẅ [LATIN CAPITAL LETTER W WITH DIAERESIS] +"\u1E84" => "W" + +# Ẇ [LATIN CAPITAL LETTER W WITH DOT ABOVE] +"\u1E86" => "W" + +# Ẉ [LATIN CAPITAL LETTER W WITH DOT BELOW] +"\u1E88" => "W" + +# Ⓦ [CIRCLED LATIN CAPITAL LETTER W] +"\u24CC" => "W" + +# Ⱳ [LATIN CAPITAL LETTER W WITH HOOK] +"\u2C72" => "W" + +# W [FULLWIDTH LATIN CAPITAL LETTER W] +"\uFF37" => "W" + +# ŵ [LATIN SMALL LETTER W WITH CIRCUMFLEX] +"\u0175" => "w" + +# ƿ http://en.wikipedia.org/wiki/Wynn [LATIN LETTER WYNN] +"\u01BF" => "w" + +# ʍ [LATIN SMALL LETTER TURNED W] +"\u028D" => "w" + +# ẁ [LATIN SMALL LETTER W WITH GRAVE] +"\u1E81" => "w" + +# ẃ [LATIN SMALL LETTER W WITH ACUTE] +"\u1E83" => "w" + +# ẅ [LATIN SMALL LETTER W WITH DIAERESIS] +"\u1E85" => "w" + +# ẇ [LATIN SMALL LETTER W WITH DOT ABOVE] +"\u1E87" => "w" + +# ẉ [LATIN SMALL LETTER W WITH DOT BELOW] +"\u1E89" => "w" + +# ẘ [LATIN SMALL LETTER W WITH RING ABOVE] +"\u1E98" => "w" + +# ⓦ [CIRCLED LATIN SMALL LETTER W] +"\u24E6" => "w" + +# ⱳ [LATIN SMALL LETTER W WITH HOOK] +"\u2C73" => "w" + +# w [FULLWIDTH LATIN SMALL LETTER W] +"\uFF57" => "w" + +# ⒲ [PARENTHESIZED LATIN SMALL LETTER W] +"\u24B2" => "(w)" + +# Ẋ [LATIN CAPITAL LETTER X WITH DOT ABOVE] +"\u1E8A" => "X" + +# Ẍ [LATIN CAPITAL LETTER X WITH DIAERESIS] +"\u1E8C" => "X" + +# Ⓧ [CIRCLED LATIN CAPITAL LETTER X] +"\u24CD" => "X" + +# X [FULLWIDTH LATIN CAPITAL LETTER X] +"\uFF38" => "X" + +# ᶍ [LATIN SMALL LETTER X WITH PALATAL HOOK] +"\u1D8D" => "x" + +# ẋ [LATIN SMALL LETTER X WITH DOT ABOVE] +"\u1E8B" => "x" + +# ẍ [LATIN SMALL LETTER X WITH DIAERESIS] +"\u1E8D" => "x" + +# ₓ [LATIN SUBSCRIPT SMALL LETTER X] +"\u2093" => "x" + +# ⓧ [CIRCLED LATIN SMALL LETTER X] +"\u24E7" => "x" + +# x [FULLWIDTH LATIN SMALL LETTER X] +"\uFF58" => "x" + +# ⒳ [PARENTHESIZED LATIN SMALL LETTER X] +"\u24B3" => "(x)" + +# Ý [LATIN CAPITAL LETTER Y WITH ACUTE] +"\u00DD" => "Y" + +# Ŷ [LATIN CAPITAL LETTER Y WITH CIRCUMFLEX] +"\u0176" => "Y" + +# Ÿ [LATIN CAPITAL LETTER Y WITH DIAERESIS] +"\u0178" => "Y" + +# Ƴ [LATIN CAPITAL LETTER Y WITH HOOK] +"\u01B3" => "Y" + +# Ȳ [LATIN CAPITAL LETTER Y WITH MACRON] +"\u0232" => "Y" + +# Ɏ [LATIN CAPITAL LETTER Y WITH STROKE] +"\u024E" => "Y" + +# ʏ [LATIN LETTER SMALL CAPITAL Y] +"\u028F" => "Y" + +# Ẏ [LATIN CAPITAL LETTER Y WITH DOT ABOVE] +"\u1E8E" => "Y" + +# Ỳ [LATIN CAPITAL LETTER Y WITH GRAVE] +"\u1EF2" => "Y" + +# Ỵ [LATIN CAPITAL LETTER Y WITH DOT BELOW] +"\u1EF4" => "Y" + +# Ỷ [LATIN CAPITAL LETTER Y WITH HOOK ABOVE] +"\u1EF6" => "Y" + +# Ỹ [LATIN CAPITAL LETTER Y WITH TILDE] +"\u1EF8" => "Y" + +# Ỿ [LATIN CAPITAL LETTER Y WITH LOOP] +"\u1EFE" => "Y" + +# Ⓨ [CIRCLED LATIN CAPITAL LETTER Y] +"\u24CE" => "Y" + +# Y [FULLWIDTH LATIN CAPITAL LETTER Y] +"\uFF39" => "Y" + +# ý [LATIN SMALL LETTER Y WITH ACUTE] +"\u00FD" => "y" + +# ÿ [LATIN SMALL LETTER Y WITH DIAERESIS] +"\u00FF" => "y" + +# ŷ [LATIN SMALL LETTER Y WITH CIRCUMFLEX] +"\u0177" => "y" + +# ƴ [LATIN SMALL LETTER Y WITH HOOK] +"\u01B4" => "y" + +# ȳ [LATIN SMALL LETTER Y WITH MACRON] +"\u0233" => "y" + +# ɏ [LATIN SMALL LETTER Y WITH STROKE] +"\u024F" => "y" + +# ʎ [LATIN SMALL LETTER TURNED Y] +"\u028E" => "y" + +# ẏ [LATIN SMALL LETTER Y WITH DOT ABOVE] +"\u1E8F" => "y" + +# ẙ [LATIN SMALL LETTER Y WITH RING ABOVE] +"\u1E99" => "y" + +# ỳ [LATIN SMALL LETTER Y WITH GRAVE] +"\u1EF3" => "y" + +# ỵ [LATIN SMALL LETTER Y WITH DOT BELOW] +"\u1EF5" => "y" + +# ỷ [LATIN SMALL LETTER Y WITH HOOK ABOVE] +"\u1EF7" => "y" + +# ỹ [LATIN SMALL LETTER Y WITH TILDE] +"\u1EF9" => "y" + +# ỿ [LATIN SMALL LETTER Y WITH LOOP] +"\u1EFF" => "y" + +# ⓨ [CIRCLED LATIN SMALL LETTER Y] +"\u24E8" => "y" + +# y [FULLWIDTH LATIN SMALL LETTER Y] +"\uFF59" => "y" + +# ⒴ [PARENTHESIZED LATIN SMALL LETTER Y] +"\u24B4" => "(y)" + +# Ź [LATIN CAPITAL LETTER Z WITH ACUTE] +"\u0179" => "Z" + +# Ż [LATIN CAPITAL LETTER Z WITH DOT ABOVE] +"\u017B" => "Z" + +# Ž [LATIN CAPITAL LETTER Z WITH CARON] +"\u017D" => "Z" + +# Ƶ [LATIN CAPITAL LETTER Z WITH STROKE] +"\u01B5" => "Z" + +# Ȝ http://en.wikipedia.org/wiki/Yogh [LATIN CAPITAL LETTER YOGH] +"\u021C" => "Z" + +# Ȥ [LATIN CAPITAL LETTER Z WITH HOOK] +"\u0224" => "Z" + +# ᴢ [LATIN LETTER SMALL CAPITAL Z] +"\u1D22" => "Z" + +# Ẑ [LATIN CAPITAL LETTER Z WITH CIRCUMFLEX] +"\u1E90" => "Z" + +# Ẓ [LATIN CAPITAL LETTER Z WITH DOT BELOW] +"\u1E92" => "Z" + +# Ẕ [LATIN CAPITAL LETTER Z WITH LINE BELOW] +"\u1E94" => "Z" + +# Ⓩ [CIRCLED LATIN CAPITAL LETTER Z] +"\u24CF" => "Z" + +# Ⱬ [LATIN CAPITAL LETTER Z WITH DESCENDER] +"\u2C6B" => "Z" + +# Ꝣ [LATIN CAPITAL LETTER VISIGOTHIC Z] +"\uA762" => "Z" + +# Z [FULLWIDTH LATIN CAPITAL LETTER Z] +"\uFF3A" => "Z" + +# ź [LATIN SMALL LETTER Z WITH ACUTE] +"\u017A" => "z" + +# ż [LATIN SMALL LETTER Z WITH DOT ABOVE] +"\u017C" => "z" + +# ž [LATIN SMALL LETTER Z WITH CARON] +"\u017E" => "z" + +# ƶ [LATIN SMALL LETTER Z WITH STROKE] +"\u01B6" => "z" + +# ȝ http://en.wikipedia.org/wiki/Yogh [LATIN SMALL LETTER YOGH] +"\u021D" => "z" + +# ȥ [LATIN SMALL LETTER Z WITH HOOK] +"\u0225" => "z" + +# ɀ [LATIN SMALL LETTER Z WITH SWASH TAIL] +"\u0240" => "z" + +# ʐ [LATIN SMALL LETTER Z WITH RETROFLEX HOOK] +"\u0290" => "z" + +# ʑ [LATIN SMALL LETTER Z WITH CURL] +"\u0291" => "z" + +# ᵶ [LATIN SMALL LETTER Z WITH MIDDLE TILDE] +"\u1D76" => "z" + +# ᶎ [LATIN SMALL LETTER Z WITH PALATAL HOOK] +"\u1D8E" => "z" + +# ẑ [LATIN SMALL LETTER Z WITH CIRCUMFLEX] +"\u1E91" => "z" + +# ẓ [LATIN SMALL LETTER Z WITH DOT BELOW] +"\u1E93" => "z" + +# ẕ [LATIN SMALL LETTER Z WITH LINE BELOW] +"\u1E95" => "z" + +# ⓩ [CIRCLED LATIN SMALL LETTER Z] +"\u24E9" => "z" + +# ⱬ [LATIN SMALL LETTER Z WITH DESCENDER] +"\u2C6C" => "z" + +# ꝣ [LATIN SMALL LETTER VISIGOTHIC Z] +"\uA763" => "z" + +# z [FULLWIDTH LATIN SMALL LETTER Z] +"\uFF5A" => "z" + +# ⒵ [PARENTHESIZED LATIN SMALL LETTER Z] +"\u24B5" => "(z)" + +# ⁰ [SUPERSCRIPT ZERO] +"\u2070" => "0" + +# ₀ [SUBSCRIPT ZERO] +"\u2080" => "0" + +# ⓪ [CIRCLED DIGIT ZERO] +"\u24EA" => "0" + +# ⓿ [NEGATIVE CIRCLED DIGIT ZERO] +"\u24FF" => "0" + +# 0 [FULLWIDTH DIGIT ZERO] +"\uFF10" => "0" + +# ¹ [SUPERSCRIPT ONE] +"\u00B9" => "1" + +# ₁ [SUBSCRIPT ONE] +"\u2081" => "1" + +# ① [CIRCLED DIGIT ONE] +"\u2460" => "1" + +# ⓵ [DOUBLE CIRCLED DIGIT ONE] +"\u24F5" => "1" + +# ❶ [DINGBAT NEGATIVE CIRCLED DIGIT ONE] +"\u2776" => "1" + +# ➀ [DINGBAT CIRCLED SANS-SERIF DIGIT ONE] +"\u2780" => "1" + +# ➊ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ONE] +"\u278A" => "1" + +# 1 [FULLWIDTH DIGIT ONE] +"\uFF11" => "1" + +# ⒈ [DIGIT ONE FULL STOP] +"\u2488" => "1." + +# ⑴ [PARENTHESIZED DIGIT ONE] +"\u2474" => "(1)" + +# ² [SUPERSCRIPT TWO] +"\u00B2" => "2" + +# ₂ [SUBSCRIPT TWO] +"\u2082" => "2" + +# ② [CIRCLED DIGIT TWO] +"\u2461" => "2" + +# ⓶ [DOUBLE CIRCLED DIGIT TWO] +"\u24F6" => "2" + +# ❷ [DINGBAT NEGATIVE CIRCLED DIGIT TWO] +"\u2777" => "2" + +# ➁ [DINGBAT CIRCLED SANS-SERIF DIGIT TWO] +"\u2781" => "2" + +# ➋ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT TWO] +"\u278B" => "2" + +# 2 [FULLWIDTH DIGIT TWO] +"\uFF12" => "2" + +# ⒉ [DIGIT TWO FULL STOP] +"\u2489" => "2." + +# ⑵ [PARENTHESIZED DIGIT TWO] +"\u2475" => "(2)" + +# ³ [SUPERSCRIPT THREE] +"\u00B3" => "3" + +# ₃ [SUBSCRIPT THREE] +"\u2083" => "3" + +# ③ [CIRCLED DIGIT THREE] +"\u2462" => "3" + +# ⓷ [DOUBLE CIRCLED DIGIT THREE] +"\u24F7" => "3" + +# ❸ [DINGBAT NEGATIVE CIRCLED DIGIT THREE] +"\u2778" => "3" + +# ➂ [DINGBAT CIRCLED SANS-SERIF DIGIT THREE] +"\u2782" => "3" + +# ➌ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT THREE] +"\u278C" => "3" + +# 3 [FULLWIDTH DIGIT THREE] +"\uFF13" => "3" + +# ⒊ [DIGIT THREE FULL STOP] +"\u248A" => "3." + +# ⑶ [PARENTHESIZED DIGIT THREE] +"\u2476" => "(3)" + +# ⁴ [SUPERSCRIPT FOUR] +"\u2074" => "4" + +# ₄ [SUBSCRIPT FOUR] +"\u2084" => "4" + +# ④ [CIRCLED DIGIT FOUR] +"\u2463" => "4" + +# ⓸ [DOUBLE CIRCLED DIGIT FOUR] +"\u24F8" => "4" + +# ❹ [DINGBAT NEGATIVE CIRCLED DIGIT FOUR] +"\u2779" => "4" + +# ➃ [DINGBAT CIRCLED SANS-SERIF DIGIT FOUR] +"\u2783" => "4" + +# ➍ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FOUR] +"\u278D" => "4" + +# 4 [FULLWIDTH DIGIT FOUR] +"\uFF14" => "4" + +# ⒋ [DIGIT FOUR FULL STOP] +"\u248B" => "4." + +# ⑷ [PARENTHESIZED DIGIT FOUR] +"\u2477" => "(4)" + +# ⁵ [SUPERSCRIPT FIVE] +"\u2075" => "5" + +# ₅ [SUBSCRIPT FIVE] +"\u2085" => "5" + +# ⑤ [CIRCLED DIGIT FIVE] +"\u2464" => "5" + +# ⓹ [DOUBLE CIRCLED DIGIT FIVE] +"\u24F9" => "5" + +# ❺ [DINGBAT NEGATIVE CIRCLED DIGIT FIVE] +"\u277A" => "5" + +# ➄ [DINGBAT CIRCLED SANS-SERIF DIGIT FIVE] +"\u2784" => "5" + +# ➎ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT FIVE] +"\u278E" => "5" + +# 5 [FULLWIDTH DIGIT FIVE] +"\uFF15" => "5" + +# ⒌ [DIGIT FIVE FULL STOP] +"\u248C" => "5." + +# ⑸ [PARENTHESIZED DIGIT FIVE] +"\u2478" => "(5)" + +# ⁶ [SUPERSCRIPT SIX] +"\u2076" => "6" + +# ₆ [SUBSCRIPT SIX] +"\u2086" => "6" + +# ⑥ [CIRCLED DIGIT SIX] +"\u2465" => "6" + +# ⓺ [DOUBLE CIRCLED DIGIT SIX] +"\u24FA" => "6" + +# ❻ [DINGBAT NEGATIVE CIRCLED DIGIT SIX] +"\u277B" => "6" + +# ➅ [DINGBAT CIRCLED SANS-SERIF DIGIT SIX] +"\u2785" => "6" + +# ➏ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SIX] +"\u278F" => "6" + +# 6 [FULLWIDTH DIGIT SIX] +"\uFF16" => "6" + +# ⒍ [DIGIT SIX FULL STOP] +"\u248D" => "6." + +# ⑹ [PARENTHESIZED DIGIT SIX] +"\u2479" => "(6)" + +# ⁷ [SUPERSCRIPT SEVEN] +"\u2077" => "7" + +# ₇ [SUBSCRIPT SEVEN] +"\u2087" => "7" + +# ⑦ [CIRCLED DIGIT SEVEN] +"\u2466" => "7" + +# ⓻ [DOUBLE CIRCLED DIGIT SEVEN] +"\u24FB" => "7" + +# ❼ [DINGBAT NEGATIVE CIRCLED DIGIT SEVEN] +"\u277C" => "7" + +# ➆ [DINGBAT CIRCLED SANS-SERIF DIGIT SEVEN] +"\u2786" => "7" + +# ➐ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT SEVEN] +"\u2790" => "7" + +# 7 [FULLWIDTH DIGIT SEVEN] +"\uFF17" => "7" + +# ⒎ [DIGIT SEVEN FULL STOP] +"\u248E" => "7." + +# ⑺ [PARENTHESIZED DIGIT SEVEN] +"\u247A" => "(7)" + +# ⁸ [SUPERSCRIPT EIGHT] +"\u2078" => "8" + +# ₈ [SUBSCRIPT EIGHT] +"\u2088" => "8" + +# ⑧ [CIRCLED DIGIT EIGHT] +"\u2467" => "8" + +# ⓼ [DOUBLE CIRCLED DIGIT EIGHT] +"\u24FC" => "8" + +# ❽ [DINGBAT NEGATIVE CIRCLED DIGIT EIGHT] +"\u277D" => "8" + +# ➇ [DINGBAT CIRCLED SANS-SERIF DIGIT EIGHT] +"\u2787" => "8" + +# ➑ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT EIGHT] +"\u2791" => "8" + +# 8 [FULLWIDTH DIGIT EIGHT] +"\uFF18" => "8" + +# ⒏ [DIGIT EIGHT FULL STOP] +"\u248F" => "8." + +# ⑻ [PARENTHESIZED DIGIT EIGHT] +"\u247B" => "(8)" + +# ⁹ [SUPERSCRIPT NINE] +"\u2079" => "9" + +# ₉ [SUBSCRIPT NINE] +"\u2089" => "9" + +# ⑨ [CIRCLED DIGIT NINE] +"\u2468" => "9" + +# ⓽ [DOUBLE CIRCLED DIGIT NINE] +"\u24FD" => "9" + +# ❾ [DINGBAT NEGATIVE CIRCLED DIGIT NINE] +"\u277E" => "9" + +# ➈ [DINGBAT CIRCLED SANS-SERIF DIGIT NINE] +"\u2788" => "9" + +# ➒ [DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE] +"\u2792" => "9" + +# 9 [FULLWIDTH DIGIT NINE] +"\uFF19" => "9" + +# ⒐ [DIGIT NINE FULL STOP] +"\u2490" => "9." + +# ⑼ [PARENTHESIZED DIGIT NINE] +"\u247C" => "(9)" + +# ⑩ [CIRCLED NUMBER TEN] +"\u2469" => "10" + +# ⓾ [DOUBLE CIRCLED NUMBER TEN] +"\u24FE" => "10" + +# ❿ [DINGBAT NEGATIVE CIRCLED NUMBER TEN] +"\u277F" => "10" + +# ➉ [DINGBAT CIRCLED SANS-SERIF NUMBER TEN] +"\u2789" => "10" + +# ➓ [DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN] +"\u2793" => "10" + +# ⒑ [NUMBER TEN FULL STOP] +"\u2491" => "10." + +# ⑽ [PARENTHESIZED NUMBER TEN] +"\u247D" => "(10)" + +# ⑪ [CIRCLED NUMBER ELEVEN] +"\u246A" => "11" + +# ⓫ [NEGATIVE CIRCLED NUMBER ELEVEN] +"\u24EB" => "11" + +# ⒒ [NUMBER ELEVEN FULL STOP] +"\u2492" => "11." + +# ⑾ [PARENTHESIZED NUMBER ELEVEN] +"\u247E" => "(11)" + +# ⑫ [CIRCLED NUMBER TWELVE] +"\u246B" => "12" + +# ⓬ [NEGATIVE CIRCLED NUMBER TWELVE] +"\u24EC" => "12" + +# ⒓ [NUMBER TWELVE FULL STOP] +"\u2493" => "12." + +# ⑿ [PARENTHESIZED NUMBER TWELVE] +"\u247F" => "(12)" + +# ⑬ [CIRCLED NUMBER THIRTEEN] +"\u246C" => "13" + +# ⓭ [NEGATIVE CIRCLED NUMBER THIRTEEN] +"\u24ED" => "13" + +# ⒔ [NUMBER THIRTEEN FULL STOP] +"\u2494" => "13." + +# ⒀ [PARENTHESIZED NUMBER THIRTEEN] +"\u2480" => "(13)" + +# ⑭ [CIRCLED NUMBER FOURTEEN] +"\u246D" => "14" + +# ⓮ [NEGATIVE CIRCLED NUMBER FOURTEEN] +"\u24EE" => "14" + +# ⒕ [NUMBER FOURTEEN FULL STOP] +"\u2495" => "14." + +# ⒁ [PARENTHESIZED NUMBER FOURTEEN] +"\u2481" => "(14)" + +# ⑮ [CIRCLED NUMBER FIFTEEN] +"\u246E" => "15" + +# ⓯ [NEGATIVE CIRCLED NUMBER FIFTEEN] +"\u24EF" => "15" + +# ⒖ [NUMBER FIFTEEN FULL STOP] +"\u2496" => "15." + +# ⒂ [PARENTHESIZED NUMBER FIFTEEN] +"\u2482" => "(15)" + +# ⑯ [CIRCLED NUMBER SIXTEEN] +"\u246F" => "16" + +# ⓰ [NEGATIVE CIRCLED NUMBER SIXTEEN] +"\u24F0" => "16" + +# ⒗ [NUMBER SIXTEEN FULL STOP] +"\u2497" => "16." + +# ⒃ [PARENTHESIZED NUMBER SIXTEEN] +"\u2483" => "(16)" + +# ⑰ [CIRCLED NUMBER SEVENTEEN] +"\u2470" => "17" + +# ⓱ [NEGATIVE CIRCLED NUMBER SEVENTEEN] +"\u24F1" => "17" + +# ⒘ [NUMBER SEVENTEEN FULL STOP] +"\u2498" => "17." + +# ⒄ [PARENTHESIZED NUMBER SEVENTEEN] +"\u2484" => "(17)" + +# ⑱ [CIRCLED NUMBER EIGHTEEN] +"\u2471" => "18" + +# ⓲ [NEGATIVE CIRCLED NUMBER EIGHTEEN] +"\u24F2" => "18" + +# ⒙ [NUMBER EIGHTEEN FULL STOP] +"\u2499" => "18." + +# ⒅ [PARENTHESIZED NUMBER EIGHTEEN] +"\u2485" => "(18)" + +# ⑲ [CIRCLED NUMBER NINETEEN] +"\u2472" => "19" + +# ⓳ [NEGATIVE CIRCLED NUMBER NINETEEN] +"\u24F3" => "19" + +# ⒚ [NUMBER NINETEEN FULL STOP] +"\u249A" => "19." + +# ⒆ [PARENTHESIZED NUMBER NINETEEN] +"\u2486" => "(19)" + +# ⑳ [CIRCLED NUMBER TWENTY] +"\u2473" => "20" + +# ⓴ [NEGATIVE CIRCLED NUMBER TWENTY] +"\u24F4" => "20" + +# ⒛ [NUMBER TWENTY FULL STOP] +"\u249B" => "20." + +# ⒇ [PARENTHESIZED NUMBER TWENTY] +"\u2487" => "(20)" + +# « [LEFT-POINTING DOUBLE ANGLE QUOTATION MARK] +"\u00AB" => "\"" + +# » [RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK] +"\u00BB" => "\"" + +# “ [LEFT DOUBLE QUOTATION MARK] +"\u201C" => "\"" + +# ” [RIGHT DOUBLE QUOTATION MARK] +"\u201D" => "\"" + +# „ [DOUBLE LOW-9 QUOTATION MARK] +"\u201E" => "\"" + +# ″ [DOUBLE PRIME] +"\u2033" => "\"" + +# ‶ [REVERSED DOUBLE PRIME] +"\u2036" => "\"" + +# ❝ [HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT] +"\u275D" => "\"" + +# ❞ [HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT] +"\u275E" => "\"" + +# ❮ [HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT] +"\u276E" => "\"" + +# ❯ [HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT] +"\u276F" => "\"" + +# " [FULLWIDTH QUOTATION MARK] +"\uFF02" => "\"" + +# ‘ [LEFT SINGLE QUOTATION MARK] +"\u2018" => "\'" + +# ’ [RIGHT SINGLE QUOTATION MARK] +"\u2019" => "\'" + +# ‚ [SINGLE LOW-9 QUOTATION MARK] +"\u201A" => "\'" + +# ‛ [SINGLE HIGH-REVERSED-9 QUOTATION MARK] +"\u201B" => "\'" + +# ′ [PRIME] +"\u2032" => "\'" + +# ‵ [REVERSED PRIME] +"\u2035" => "\'" + +# ‹ [SINGLE LEFT-POINTING ANGLE QUOTATION MARK] +"\u2039" => "\'" + +# › [SINGLE RIGHT-POINTING ANGLE QUOTATION MARK] +"\u203A" => "\'" + +# ❛ [HEAVY SINGLE TURNED COMMA QUOTATION MARK ORNAMENT] +"\u275B" => "\'" + +# ❜ [HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT] +"\u275C" => "\'" + +# ' [FULLWIDTH APOSTROPHE] +"\uFF07" => "\'" + +# ‐ [HYPHEN] +"\u2010" => "-" + +# ‑ [NON-BREAKING HYPHEN] +"\u2011" => "-" + +# ‒ [FIGURE DASH] +"\u2012" => "-" + +# – [EN DASH] +"\u2013" => "-" + +# — [EM DASH] +"\u2014" => "-" + +# ⁻ [SUPERSCRIPT MINUS] +"\u207B" => "-" + +# ₋ [SUBSCRIPT MINUS] +"\u208B" => "-" + +# - [FULLWIDTH HYPHEN-MINUS] +"\uFF0D" => "-" + +# ⁅ [LEFT SQUARE BRACKET WITH QUILL] +"\u2045" => "[" + +# ❲ [LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT] +"\u2772" => "[" + +# [ [FULLWIDTH LEFT SQUARE BRACKET] +"\uFF3B" => "[" + +# ⁆ [RIGHT SQUARE BRACKET WITH QUILL] +"\u2046" => "]" + +# ❳ [LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT] +"\u2773" => "]" + +# ] [FULLWIDTH RIGHT SQUARE BRACKET] +"\uFF3D" => "]" + +# ⁽ [SUPERSCRIPT LEFT PARENTHESIS] +"\u207D" => "(" + +# ₍ [SUBSCRIPT LEFT PARENTHESIS] +"\u208D" => "(" + +# ❨ [MEDIUM LEFT PARENTHESIS ORNAMENT] +"\u2768" => "(" + +# ❪ [MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT] +"\u276A" => "(" + +# ( [FULLWIDTH LEFT PARENTHESIS] +"\uFF08" => "(" + +# ⸨ [LEFT DOUBLE PARENTHESIS] +"\u2E28" => "((" + +# ⁾ [SUPERSCRIPT RIGHT PARENTHESIS] +"\u207E" => ")" + +# ₎ [SUBSCRIPT RIGHT PARENTHESIS] +"\u208E" => ")" + +# ❩ [MEDIUM RIGHT PARENTHESIS ORNAMENT] +"\u2769" => ")" + +# ❫ [MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT] +"\u276B" => ")" + +# ) [FULLWIDTH RIGHT PARENTHESIS] +"\uFF09" => ")" + +# ⸩ [RIGHT DOUBLE PARENTHESIS] +"\u2E29" => "))" + +# ❬ [MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT] +"\u276C" => "<" + +# ❰ [HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT] +"\u2770" => "<" + +# < [FULLWIDTH LESS-THAN SIGN] +"\uFF1C" => "<" + +# ❭ [MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT] +"\u276D" => ">" + +# ❱ [HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT] +"\u2771" => ">" + +# > [FULLWIDTH GREATER-THAN SIGN] +"\uFF1E" => ">" + +# ❴ [MEDIUM LEFT CURLY BRACKET ORNAMENT] +"\u2774" => "{" + +# { [FULLWIDTH LEFT CURLY BRACKET] +"\uFF5B" => "{" + +# ❵ [MEDIUM RIGHT CURLY BRACKET ORNAMENT] +"\u2775" => "}" + +# } [FULLWIDTH RIGHT CURLY BRACKET] +"\uFF5D" => "}" + +# ⁺ [SUPERSCRIPT PLUS SIGN] +"\u207A" => "+" + +# ₊ [SUBSCRIPT PLUS SIGN] +"\u208A" => "+" + +# + [FULLWIDTH PLUS SIGN] +"\uFF0B" => "+" + +# ⁼ [SUPERSCRIPT EQUALS SIGN] +"\u207C" => "=" + +# ₌ [SUBSCRIPT EQUALS SIGN] +"\u208C" => "=" + +# = [FULLWIDTH EQUALS SIGN] +"\uFF1D" => "=" + +# ! [FULLWIDTH EXCLAMATION MARK] +"\uFF01" => "!" + +# ‼ [DOUBLE EXCLAMATION MARK] +"\u203C" => "!!" + +# ⁉ [EXCLAMATION QUESTION MARK] +"\u2049" => "!?" + +# # [FULLWIDTH NUMBER SIGN] +"\uFF03" => "#" + +# $ [FULLWIDTH DOLLAR SIGN] +"\uFF04" => "$" + +# ⁒ [COMMERCIAL MINUS SIGN] +"\u2052" => "%" + +# % [FULLWIDTH PERCENT SIGN] +"\uFF05" => "%" + +# & [FULLWIDTH AMPERSAND] +"\uFF06" => "&" + +# ⁎ [LOW ASTERISK] +"\u204E" => "*" + +# * [FULLWIDTH ASTERISK] +"\uFF0A" => "*" + +# , [FULLWIDTH COMMA] +"\uFF0C" => "," + +# . [FULLWIDTH FULL STOP] +"\uFF0E" => "." + +# ⁄ [FRACTION SLASH] +"\u2044" => "/" + +# / [FULLWIDTH SOLIDUS] +"\uFF0F" => "/" + +# : [FULLWIDTH COLON] +"\uFF1A" => ":" + +# ⁏ [REVERSED SEMICOLON] +"\u204F" => ";" + +# ; [FULLWIDTH SEMICOLON] +"\uFF1B" => ";" + +# ? [FULLWIDTH QUESTION MARK] +"\uFF1F" => "?" + +# ⁇ [DOUBLE QUESTION MARK] +"\u2047" => "??" + +# ⁈ [QUESTION EXCLAMATION MARK] +"\u2048" => "?!" + +# @ [FULLWIDTH COMMERCIAL AT] +"\uFF20" => "@" + +# \ [FULLWIDTH REVERSE SOLIDUS] +"\uFF3C" => "\\" + +# ‸ [CARET] +"\u2038" => "^" + +# ^ [FULLWIDTH CIRCUMFLEX ACCENT] +"\uFF3E" => "^" + +# _ [FULLWIDTH LOW LINE] +"\uFF3F" => "_" + +# ⁓ [SWUNG DASH] +"\u2053" => "~" + +# ~ [FULLWIDTH TILDE] +"\uFF5E" => "~" + +################################################################ +# Below is the Perl script used to generate the above mappings # +# from ASCIIFoldingFilter.java: # +################################################################ +# +# #!/usr/bin/perl +# +# use warnings; +# use strict; +# +# my @source_chars = (); +# my @source_char_descriptions = (); +# my $target = ''; +# +# while (<>) { +# if (/case\s+'(\\u[A-F0-9]+)':\s*\/\/\s*(.*)/i) { +# push @source_chars, $1; +# push @source_char_descriptions, $2; +# next; +# } +# if (/output\[[^\]]+\]\s*=\s*'(\\'|\\\\|.)'/) { +# $target .= $1; +# next; +# } +# if (/break;/) { +# $target = "\\\"" if ($target eq '"'); +# for my $source_char_num (0..$#source_chars) { +# print "# $source_char_descriptions[$source_char_num]\n"; +# print "\"$source_chars[$source_char_num]\" => \"$target\"\n\n"; +# } +# @source_chars = (); +# @source_char_descriptions = (); +# $target = ''; +# } +# } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java index 59ef60646..a333490ab 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/actions/MergeProfilesOnPropertyAction.java @@ -35,7 +35,7 @@ import java.util.stream.Collectors; public class MergeProfilesOnPropertyAction implements ActionExecutor { - private static final Logger logger = LoggerFactory.getLogger(MergeProfilesOnPropertyAction.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(MergeProfilesOnPropertyAction.class.getName()); private ProfileService profileService; private PersistenceService persistenceService; @@ -135,7 +135,7 @@ public int execute(Action action, Event event) { } } } catch (Exception e) { - logger.error("unable to execute callback action, profile and session will not be saved", e); + LOGGER.error("unable to execute callback action, profile and session will not be saved", e); return false; } return true; @@ -192,7 +192,7 @@ private void reassignCurrentBrowsingData(Event event, List existingMerg eventProfile.getSystemProperties().put(mergePropName, mergePropValue); } - logger.info("Different users, switch to {}", eventProfile.getItemId()); + LOGGER.info("Different users, switch to {}", eventProfile.getItemId()); // At the end of the merge, we must set the merged profile as profile event to process other Actions event.setProfileId(eventProfile.getItemId()); event.setProfile(eventProfile); @@ -232,4 +232,4 @@ public void setSchedulerService(SchedulerService schedulerService) { public void setMaxProfilesInOneMerge(String maxProfilesInOneMerge) { this.maxProfilesInOneMerge = Integer.parseInt(maxProfilesInOneMerge); } -} \ No newline at end of file +} diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java index 1ecfc65be..ade280e6d 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionEvaluator.java @@ -19,8 +19,8 @@ import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import java.util.List; import java.util.Map; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java index e069ed87d..7c7d55e17 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java @@ -20,8 +20,8 @@ import org.apache.commons.beanutils.BeanUtils; import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import org.elasticsearch.common.geo.GeoDistance; import org.elasticsearch.common.unit.DistanceUnit; import org.slf4j.Logger; @@ -31,7 +31,7 @@ public class GeoLocationByPointSessionConditionEvaluator implements ConditionEvaluator { - private static final Logger logger = LoggerFactory.getLogger(GeoLocationByPointSessionConditionEvaluator.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(GeoLocationByPointSessionConditionEvaluator.class.getName()); @Override public boolean eval(Condition condition, Item item, Map context, ConditionEvaluatorDispatcher dispatcher) { @@ -39,8 +39,8 @@ public boolean eval(Condition condition, Item item, Map context, String type = (String) condition.getParameter("type"); String name = condition.getParameter("name") == null ? "properties.location" : (String) condition.getParameter("name"); - Double latitudeProperty = Double.parseDouble(BeanUtils.getProperty(item, name + ".lat")); - Double longitudeProperty = Double.parseDouble(BeanUtils.getProperty(item, name + ".lon")); + double latitudeProperty = Double.parseDouble(BeanUtils.getProperty(item, name + ".lat")); + double longitudeProperty = Double.parseDouble(BeanUtils.getProperty(item, name + ".lon")); if("circle".equals(type)) { @@ -64,10 +64,8 @@ public boolean eval(Condition condition, Item item, Map context, } } } catch (Exception e) { - logger.warn("Cannot evaluate condition, properties 'properties.location.lat' or 'properties.location.lon' not found, enable debug log level to see full stacktrace"); - if (logger.isDebugEnabled()) { - logger.debug("Cannot evaluate condition", e); - } + LOGGER.warn("Cannot evaluate condition, properties 'properties.location.lat' or 'properties.location.lon' not found, enable debug log level to see full stacktrace"); + LOGGER.debug("Cannot evaluate condition", e); } return false; } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionEvaluator.java index d4f1ca887..32f5b9468 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionEvaluator.java @@ -18,8 +18,8 @@ import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import java.util.Collection; import java.util.Map; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java index ee8c1e884..cab1c35fe 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java @@ -19,8 +19,8 @@ import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import java.util.Map; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionEvaluator.java index 1bbba6358..2a6a112b1 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionEvaluator.java @@ -22,8 +22,8 @@ import org.apache.unomi.api.Profile; import org.apache.unomi.api.Session; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,7 +31,7 @@ public class NestedConditionEvaluator implements ConditionEvaluator { - private static final Logger logger = LoggerFactory.getLogger(NestedConditionEvaluator.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(NestedConditionEvaluator.class.getName()); PropertyConditionEvaluator propertyConditionEvaluator; @@ -67,7 +67,7 @@ public boolean eval(Condition condition, Item item, Map context, } } } catch (Exception e) { - logger.error("Failed to evaluated nested condition", e); + LOGGER.error("Failed to evaluated nested condition", e); return false; } return false; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java index 5522f3196..9296214bb 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionEvaluator.java @@ -19,8 +19,8 @@ import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import java.util.Map; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java index 6c40f9f87..401726f7e 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java @@ -20,10 +20,10 @@ import org.apache.unomi.api.Event; import org.apache.unomi.api.Profile; import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.api.conditions.ConditionType; import org.apache.unomi.api.services.DefinitionsService; import org.apache.unomi.api.services.SegmentService; -import org.apache.unomi.api.utils.ConditionBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; import org.apache.unomi.persistence.spi.PersistenceService; @@ -88,8 +88,7 @@ public QueryBuilder buildQuery(Condition condition, Map context, // TODO see for deprecation, this should not happen anymore each past event condition should have a generatedPropertyKey Condition eventCondition = getEventCondition(condition, context, null, definitionsService, scriptExecutor); Set ids = getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, maximumEventCount); - ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); - return dispatcher.buildFilter(conditionBuilder.condition("idsCondition").parameter("ids", ids).parameter("match", eventsOccurred).build(), context); + return dispatcher.buildFilter(getProfileIdsCondition(ids, eventsOccurred), context); } } @@ -112,8 +111,7 @@ public long count(Condition condition, Map context, ConditionESQ } Set profileIds = getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, maximumEventCount); - ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); - return eventsOccurred ? profileIds.size() : persistenceService.queryCount(conditionBuilder.condition("idsCondition").parameter("ids", profileIds).parameter("match", false).build(), Profile.ITEM_TYPE); + return eventsOccurred ? profileIds.size() : persistenceService.queryCount(getProfileIdsCondition(profileIds, false), Profile.ITEM_TYPE); } } @@ -124,38 +122,44 @@ protected static boolean getStrategyFromOperator(String operator) { return operator == null || operator.equals("eventsOccurred"); } + private Condition getProfileIdsCondition(Set ids, boolean shouldMatch) { + Condition idsCondition = new Condition(); + idsCondition.setConditionType(definitionsService.getConditionType("idsCondition")); + idsCondition.setParameter("ids", ids); + idsCondition.setParameter("match", shouldMatch); + return idsCondition; + } + private Condition getProfileConditionForCounter(String generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount, boolean eventsOccurred) { + String generatedPropertyName = "systemProperties.pastEvents." + generatedPropertyKey; + ConditionType profilePropertyConditionType = definitionsService.getConditionType("profilePropertyCondition"); if (eventsOccurred) { - return createEventOccurredCondition(generatedPropertyKey, minimumEventCount, maximumEventCount); + Condition counterIsBetweenBoundaries = new Condition(); + counterIsBetweenBoundaries.setConditionType(profilePropertyConditionType); + counterIsBetweenBoundaries.setParameter("propertyName", generatedPropertyName); + counterIsBetweenBoundaries.setParameter("comparisonOperator", "between"); + counterIsBetweenBoundaries.setParameter("propertyValuesInteger", Arrays.asList(minimumEventCount, maximumEventCount)); + return counterIsBetweenBoundaries; } else { - return createEventNotOccurredCondition(generatedPropertyKey); + Condition counterMissing = new Condition(); + counterMissing.setConditionType(profilePropertyConditionType); + counterMissing.setParameter("propertyName", generatedPropertyName); + counterMissing.setParameter("comparisonOperator", "missing"); + + Condition counterZero = new Condition(); + counterZero.setConditionType(profilePropertyConditionType); + counterZero.setParameter("propertyName", generatedPropertyName); + counterZero.setParameter("comparisonOperator", "equals"); + counterZero.setParameter("propertyValueInteger", 0); + + Condition counterCondition = new Condition(); + counterCondition.setConditionType(definitionsService.getConditionType("booleanCondition")); + counterCondition.setParameter("operator", "or"); + counterCondition.setParameter("subConditions", Arrays.asList(counterMissing, counterZero)); + return counterCondition; } } - private Condition createEventOccurredCondition(String generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount) { - ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); - ConditionBuilder.ConditionItem subConditionCount = conditionBuilder.profileProperty("systemProperties.pastEvents.count").between(minimumEventCount, maximumEventCount); - ConditionBuilder.ConditionItem subConditionKey = conditionBuilder.profileProperty("systemProperties.pastEvents.key").equalTo(generatedPropertyKey); - ConditionBuilder.ConditionItem booleanCondition = conditionBuilder.and(subConditionCount, subConditionKey); - return conditionBuilder.nested(booleanCondition, "systemProperties.pastEvents").build(); - } - - private Condition createEventNotOccurredCondition(String generatedPropertyKey) { - ConditionBuilder.ConditionItem counterMissing = createPastEventMustNotExistCondition(generatedPropertyKey); - ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); - ConditionBuilder.ConditionItem counterZero = conditionBuilder.profileProperty("systemProperties.pastEvents.count").equalTo(0); - ConditionBuilder.ConditionItem keyEquals = conditionBuilder.profileProperty("systemProperties.pastEvents.key").equalTo(generatedPropertyKey); - ConditionBuilder.ConditionItem keyExistsAndCounterZero = conditionBuilder.and(counterZero, keyEquals); - ConditionBuilder.ConditionItem nestedKeyExistsAndCounterZero = conditionBuilder.nested(keyExistsAndCounterZero, "systemProperties.pastEvents"); - return conditionBuilder.or(counterMissing, nestedKeyExistsAndCounterZero).build(); - } - - private ConditionBuilder.ConditionItem createPastEventMustNotExistCondition(String generatedPropertyKey) { - ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); - ConditionBuilder.ConditionItem keyEquals = conditionBuilder.profileProperty("systemProperties.pastEvents.key").equalTo(generatedPropertyKey); - return conditionBuilder.not(keyEquals); - } - private Set getProfileIdsMatchingEventCount(Condition eventCondition, int minimumEventCount, int maximumEventCount) { boolean noBoundaries = minimumEventCount == 1 && maximumEventCount == Integer.MAX_VALUE; if (pastEventsDisablePartitions) { @@ -250,6 +254,4 @@ private static Condition getTimeStampCondition(String operator, String propertyV endDateCondition.setParameter(propertyValueParameter, propertyValue); return endDateCondition; } - - } diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java index f14f768f6..8caf01322 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java @@ -22,9 +22,9 @@ import org.apache.unomi.api.Profile; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.services.DefinitionsService; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; import org.apache.unomi.persistence.spi.PersistenceService; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import org.apache.unomi.scripting.ScriptExecutor; import java.util.ArrayList; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java index a7df6c7a4..d923d76ad 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java @@ -19,7 +19,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; import org.elasticsearch.common.geo.GeoPoint; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java index 06b32bc7c..c6e117305 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java @@ -26,9 +26,9 @@ import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessor; import org.apache.unomi.scripting.ExpressionFilterFactory; import org.apache.unomi.scripting.SecureFilteringClassLoader; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionContextHelper; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import org.apache.unomi.persistence.spi.PropertyHelper; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.joda.Joda; @@ -49,7 +49,7 @@ */ public class PropertyConditionEvaluator implements ConditionEvaluator { - private static final Logger logger = LoggerFactory.getLogger(PropertyConditionEvaluator.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(PropertyConditionEvaluator.class.getName()); private static final SimpleDateFormat yearMonthDayDateFormat = new SimpleDateFormat("yyyyMMdd"); @@ -71,7 +71,7 @@ public void setExpressionFilterFactory(ExpressionFilterFactory expressionFilterF public void init() { if (!useOGNLScripting) { - logger.info("OGNL Script disabled, properties using OGNL won't be evaluated"); + LOGGER.info("OGNL Script disabled, properties using OGNL won't be evaluated"); } } @@ -91,7 +91,8 @@ private int compare(Object actualValue, String expectedValue, Object expectedVal } else if (expectedValueDateExpr != null) { return getDate(actualValue).compareTo(getDate(expectedValueDateExpr)); } else { - return actualValue.toString().compareTo(expectedValue); + // We use toLowerCase here to match the behavior of the analyzer configuration in the persistence configuration + return actualValue.toString().toLowerCase().compareTo(expectedValue); } } @@ -187,7 +188,7 @@ public boolean eval(Condition condition, Item item, Map context, actualValue = getPropertyValue(item, name); time = System.nanoTime() - time; if (time > 5000000L) { - logger.info("eval took {} ms for {} {}", time / 1000000L, item.getClass().getName(), name); + LOGGER.info("eval took {} ms for {} {}", time / 1000000L, item.getClass().getName(), name); } } catch (NullPointerException e) { // property not found @@ -196,10 +197,8 @@ public boolean eval(Condition condition, Item item, Map context, if (!(e instanceof OgnlException) || (!StringUtils.startsWith(e.getMessage(), "source is null for getProperty(null"))) { - logger.warn("Error evaluating value for {} {}. See debug level for more information", item.getClass().getName(), name); - if (logger.isDebugEnabled()) { - logger.debug("Error evaluating value for {} {}", item.getClass().getName(), name, e); - } + LOGGER.warn("Error evaluating value for {} {}. See debug level for more information", item.getClass().getName(), name); + if (LOGGER.isDebugEnabled()) LOGGER.debug("Error evaluating value for {} {}", item.getClass().getName(), name, e); } actualValue = null; } @@ -336,10 +335,8 @@ protected Object getHardcodedPropertyValue(Item item, String expression) { protected Object getOGNLPropertyValue(Item item, String expression) throws Exception { if (expressionFilterFactory.getExpressionFilter("ognl").filter(expression) == null) { - logger.warn("OGNL expression filtered because not allowed on item: {}. See debug log level for more information", item.getClass().getName()); - if (logger.isDebugEnabled()) { - logger.debug("OGNL expression filtered because not allowed: {}", expression); - } + LOGGER.warn("OGNL expression filtered because not allowed on item: {}. See debug log level for more information", item.getClass().getName()); + LOGGER.debug("OGNL expression filtered because not allowed: {}", expression); return null; } OgnlContext ognlContext = getOgnlContext(secureFilteringClassLoader); @@ -348,11 +345,8 @@ protected Object getOGNLPropertyValue(Item item, String expression) throws Excep try { return accessor.get(ognlContext, item); } catch (Throwable t) { - logger.error("Error evaluating expression on item {}. See debug level for more information", item.getClass().getName()); - if (logger.isDebugEnabled()) { - logger.debug("Error evaluating expression {} on item {}.", expression, item.getClass().getName(), t); - } - + LOGGER.error("Error evaluating expression on item {}. See debug level for more information", item.getClass().getName()); + LOGGER.debug("Error evaluating expression {} on item {}.", expression, item.getClass().getName(), t); return null; } } @@ -391,10 +385,8 @@ public boolean isAccessible(OgnlContext ognlContext, Object target, Member membe accessible = Modifier.isPublic(modifiers); } if (!accessible) { - logger.warn("OGNL security filtered target, member for property. See debug log level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("OGNL security filtered: Target {} and member {} for property {}. Not allowed", target, member, propertyName); - } + LOGGER.warn("OGNL security filtered target, member for property. See debug log level for more information"); + LOGGER.debug("OGNL security filtered: Target {} and member {} for property {}. Not allowed", target, member, propertyName); } return accessible; } @@ -426,23 +418,23 @@ private ExpressionAccessor getPropertyAccessor(Item item, String expression, Ogn if (accessor != null) { expressions.put(expression, accessor); } else { - logger.warn("Unable to compile expression for {}. See debug log level for more information", clazz); - if (logger.isDebugEnabled()) { - logger.debug("Unable to compile expression: {} for: {}", expression, clazz); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Unable to compile expression: {} for: {}", expression, clazz); + } else { + LOGGER.warn("Unable to compile expression for {}. See debug log level for more information", clazz); } } - time = System.nanoTime() - time; - if (logger.isDebugEnabled()) { - logger.debug("Expression compilation for item={} expression={} took {}", item.getClass().getName(), expression, time / 1000000L); - } else if (logger.isInfoEnabled()) { - logger.info("Expression compilation for item={} took {}. See debug log level for more information", item.getClass().getName(), time / 1000000L); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Expression compilation for item={} expression={} took {}", item.getClass().getName(), expression, (System.nanoTime() - time) / 1000000L); + } else { + LOGGER.info("Expression compilation for item={} took {}. See debug log level for more information", item.getClass().getName(), (System.nanoTime() - time) / 1000000L); } } return accessor; } - protected static Date getDate(Object value) { + public static Date getDate(Object value) { if (value == null) { return null; } @@ -453,10 +445,8 @@ protected static Date getDate(Object value) { try { return Date.from(parser.parse(value.toString(), System::currentTimeMillis)); } catch (ElasticsearchParseException e) { - logger.warn("unable to parse date. See debug log level for full stacktrace"); - if (logger.isDebugEnabled()) { - logger.debug("unable to parse date {}", value.toString(), e); - } + LOGGER.warn("unable to parse date. See debug log level for full stacktrace"); + LOGGER.debug("unable to parse date {}", value, e); } } return null; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java index 19bbca7c6..f21b201c2 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionEvaluator.java @@ -22,8 +22,8 @@ import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.conditions.ConditionType; import org.apache.unomi.api.services.DefinitionsService; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluator; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; +import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; import java.util.ArrayList; import java.util.HashMap; @@ -89,4 +89,4 @@ public DefinitionsService getDefinitionsService() { public void setDefinitionsService(DefinitionsService definitionsService) { this.definitionsService = definitionsService; } -} \ No newline at end of file +} diff --git a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 9f7dc8c92..67a2c537c 100644 --- a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -134,21 +134,21 @@ - + - + - + @@ -158,27 +158,27 @@ - + - + - + - + @@ -188,7 +188,7 @@ + interface="org.apache.unomi.persistence.spi.conditions.ConditionEvaluator"> @@ -199,7 +199,7 @@ - + diff --git a/pom.xml b/pom.xml index 3574234d5..16bb07a41 100644 --- a/pom.xml +++ b/pom.xml @@ -61,15 +61,16 @@ 4.2.15 UTF-8 3.3.11 - 2.11.4 - 2.11.4 - 2.11.4 + 2.13.5 + 2.13.5 + 2.13.5 4.2.15 4.2.1 4.13.5 7.4.2 7.11.0 8.2.0 + 2.18.0 4.0.21 1.4.0 1.1.0.Final @@ -99,6 +100,7 @@ 4.5.0 4.5.14 4.4.16 + 33.3.1-jre v16.20.2 v1.22.19 @@ -992,6 +994,7 @@ persistence-spi lifecycle-watcher persistence-elasticsearch + persistence-opensearch services rest graphql @@ -1020,7 +1023,7 @@ org.apache.felix maven-bundle-plugin - 4.2.1 + 5.1.1 true @@ -1178,6 +1181,14 @@ + + + org.apache.maven.extensions + maven-build-cache-extension + 1.2.0 + + + diff --git a/rest/pom.xml b/rest/pom.xml index 432129fa2..6fa17166d 100644 --- a/rest/pom.xml +++ b/rest/pom.xml @@ -37,6 +37,11 @@ ${project.version} provided + + org.apache.unomi + unomi-persistence-spi + ${project.version} + org.apache.unomi unomi-json-schema-services @@ -82,6 +87,10 @@ cxf-rt-transports-http provided + + org.apache.cxf + cxf-rt-rs-security-cors + com.fasterxml.jackson.jaxrs jackson-jaxrs-json-provider @@ -128,6 +137,13 @@ org.apache.cxf cxf-rt-rs-security-cors + ${cxf.version} + provided + + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${cxf.version} provided @@ -139,6 +155,10 @@ commons-beanutils commons-beanutils + + commons-collections + commons-collections + org.apache.karaf.jaas org.apache.karaf.jaas.boot diff --git a/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java b/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java index cdd92741b..b9f3aef15 100644 --- a/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java +++ b/rest/src/main/java/org/apache/unomi/rest/service/impl/RestServiceUtilsImpl.java @@ -26,8 +26,8 @@ import org.apache.unomi.rest.exception.InvalidRequestException; import org.apache.unomi.rest.service.RestServiceUtils; import org.apache.unomi.schema.api.SchemaService; -import org.apache.unomi.utils.HttpUtils; import org.apache.unomi.utils.EventsRequestContext; +import org.apache.unomi.utils.HttpUtils; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; @@ -40,14 +40,13 @@ import java.util.Date; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; @Component(service = RestServiceUtils.class) public class RestServiceUtilsImpl implements RestServiceUtils { private static final String DEFAULT_CLIENT_ID = "defaultClientId"; - private static final Logger logger = LoggerFactory.getLogger(RestServiceUtilsImpl.class.getName()); + private static final Logger LOGGER = LoggerFactory.getLogger(RestServiceUtilsImpl.class.getName()); @Reference private ConfigSharingService configSharingService; @@ -97,7 +96,7 @@ public EventsRequestContext initEventsRequest(String scope, String sessionId, St if (personaId != null) { PersonaWithSessions personaWithSessions = profileService.loadPersonaWithSessions(personaId); if (personaWithSessions == null) { - logger.error("Couldn't find persona, please check your personaId parameter"); + LOGGER.error("Couldn't find persona, please check your personaId parameter"); } else { eventsRequestContext.setProfile(personaWithSessions.getPersona()); eventsRequestContext.setSession(personaWithSessions.getLastSession()); @@ -110,10 +109,8 @@ public EventsRequestContext initEventsRequest(String scope, String sessionId, St } if (profileId == null && sessionId == null && personaId == null) { - logger.warn("Couldn't find profileId, sessionId or personaId in incoming request! Stopped processing request. See debug level for more information"); - if (logger.isDebugEnabled()) { - logger.debug("Request dump: {}", HttpUtils.dumpRequestInfo(request)); - } + LOGGER.warn("Couldn't find profileId, sessionId or personaId in incoming request! Stopped processing request. See debug level for more information"); + if (LOGGER.isDebugEnabled()) LOGGER.debug("Request dump: {}", HttpUtils.dumpRequestInfo(request)); throw new BadRequestException("Couldn't find profileId, sessionId or personaId in incoming request!"); } @@ -148,7 +145,13 @@ public EventsRequestContext initEventsRequest(String scope, String sessionId, St // Session user has been switched, profile id in cookie is not up to date // We must reload the profile with the session ID as some properties could be missing from the session profile // #personalIdentifier - eventsRequestContext.setProfile(profileService.load(sessionProfile.getItemId())); + Profile sessionProfileWithId = profileService.load(sessionProfile.getItemId()); + if (sessionProfileWithId != null) { + eventsRequestContext.setProfile(sessionProfileWithId); + } else { + LOGGER.warn("Couldn't find profile ID {} referenced from session with ID {}, so we re-create it", sessionProfile.getItemId(), sessionId); + eventsRequestContext.setProfile(createNewProfile(sessionProfile.getItemId(), timestamp)); + } } // Handle anonymous situation @@ -168,10 +171,14 @@ public EventsRequestContext initEventsRequest(String scope, String sessionId, St } else if (!requireAnonymousBrowsing && !anonymousSessionProfile) { // User does not want to browse anonymously, use the real profile. Check that session contains the current profile. sessionProfile = eventsRequestContext.getProfile(); - if (!eventsRequestContext.getSession().getProfileId().equals(sessionProfile.getItemId())) { - eventsRequestContext.addChanges(EventService.SESSION_UPDATED); + if (sessionProfile != null) { + if (!eventsRequestContext.getSession().getProfileId().equals(sessionProfile.getItemId())) { + eventsRequestContext.addChanges(EventService.SESSION_UPDATED); + } + eventsRequestContext.getSession().setProfile(sessionProfile); + } else { + LOGGER.warn("Null profile in event request context"); } - eventsRequestContext.getSession().setProfile(sessionProfile); } } } @@ -196,10 +203,8 @@ public EventsRequestContext initEventsRequest(String scope, String sessionId, St } event.getAttributes().put(Event.HTTP_REQUEST_ATTRIBUTE, request); event.getAttributes().put(Event.HTTP_RESPONSE_ATTRIBUTE, response); - if (logger.isDebugEnabled()) { - logger.debug("Received event {} for profile={} session={} target={} timestamp={}", event.getEventType(), - eventsRequestContext.getProfile().getItemId(), eventsRequestContext.getSession().getItemId(), event.getTarget(), timestamp); - } + if (LOGGER.isDebugEnabled()) LOGGER.debug("Received event {} for profile={} session={} target={} timestamp={}", event.getEventType(), + eventsRequestContext.getProfile().getItemId(), eventsRequestContext.getSession().getItemId(), event.getTarget(), timestamp); eventsRequestContext.addChanges(eventService.send(event)); } } @@ -215,12 +220,10 @@ public EventsRequestContext initEventsRequest(String scope, String sessionId, St profileUpdated.getAttributes().put(Event.HTTP_RESPONSE_ATTRIBUTE, response); profileUpdated.getAttributes().put(Event.CLIENT_ID_ATTRIBUTE, DEFAULT_CLIENT_ID); - if (logger.isDebugEnabled()) { - logger.debug("Received event {} for profile={} {} target={} timestamp={}", profileUpdated.getEventType(), - eventsRequestContext.getProfile().getItemId(), - " session=" + (eventsRequestContext.getSession() != null ? eventsRequestContext.getSession().getItemId() : null), - profileUpdated.getTarget(), timestamp); - } + if (LOGGER.isDebugEnabled()) LOGGER.debug("Received event {} for profile={} {} target={} timestamp={}", profileUpdated.getEventType(), + eventsRequestContext.getProfile().getItemId(), + " session=" + (eventsRequestContext.getSession() != null ? eventsRequestContext.getSession().getItemId() : null), + profileUpdated.getTarget(), timestamp); eventsRequestContext.addChanges(eventService.send(profileUpdated)); } } @@ -247,7 +250,7 @@ public EventsRequestContext performEventsRequest(List events, EventsReque event.getTarget(), event.getProperties(), eventsRequestContext.getTimestamp(), event.isPersistent()); eventToSend.setFlattenedProperties(event.getFlattenedProperties()); if (!eventService.isEventAllowed(event, thirdPartyId)) { - logger.warn("Event is not allowed : {}", event.getEventType()); + LOGGER.warn("Event is not allowed : {}", event.getEventType()); continue; } if (thirdPartyId != null && event.getItemId() != null) { @@ -256,7 +259,7 @@ public EventsRequestContext performEventsRequest(List events, EventsReque eventToSend.setFlattenedProperties(event.getFlattenedProperties()); } if (filteredEventTypes != null && filteredEventTypes.contains(event.getEventType())) { - logger.debug("Profile is filtering event type {}", event.getEventType()); + LOGGER.debug("Profile is filtering event type {}", event.getEventType()); continue; } if (eventsRequestContext.getProfile().isAnonymousProfile()) { @@ -266,9 +269,10 @@ public EventsRequestContext performEventsRequest(List events, EventsReque eventToSend.getAttributes().put(Event.HTTP_REQUEST_ATTRIBUTE, eventsRequestContext.getRequest()); eventToSend.getAttributes().put(Event.HTTP_RESPONSE_ATTRIBUTE, eventsRequestContext.getResponse()); - logger.debug("Received event " + event.getEventType() + " for profile=" + eventsRequestContext.getProfile().getItemId() + " session=" + ( - eventsRequestContext.getSession() != null ? eventsRequestContext.getSession().getItemId() : null) + - " target=" + event.getTarget() + " timestamp=" + eventsRequestContext.getTimestamp()); + LOGGER.debug("Received event {} for profile={} session={} target={} timestamp={}", event.getEventType(), + eventsRequestContext.getProfile().getItemId(), + eventsRequestContext.getSession() != null ? eventsRequestContext.getSession().getItemId() : null, + event.getTarget(), eventsRequestContext.getTimestamp()); eventsRequestContext.addChanges(eventService.send(eventToSend)); // If the event execution changes the profile we need to update it so the next event use the right profile if ((eventsRequestContext.getChanges() & EventService.PROFILE_UPDATED) == EventService.PROFILE_UPDATED) { @@ -281,7 +285,7 @@ public EventsRequestContext performEventsRequest(List events, EventsReque if ((eventsRequestContext.getChanges() & EventService.ERROR) == EventService.ERROR) { //Don't count the event that failed eventsRequestContext.setProcessedItems(eventsRequestContext.getProcessedItems() - 1); - logger.error("Error processing events. Total number of processed events: {}/{}", eventsRequestContext.getProcessedItems(), eventsRequestContext.getTotalItems()); + LOGGER.error("Error processing events. Total number of processed events: {}/{}", eventsRequestContext.getProcessedItems(), eventsRequestContext.getTotalItems()); break; } } diff --git a/services/src/main/java/org/apache/unomi/services/sorts/FilterPersonalizationStrategy.java b/services/src/main/java/org/apache/unomi/services/sorts/FilterPersonalizationStrategy.java index a79bc62bf..dac29f3b0 100644 --- a/services/src/main/java/org/apache/unomi/services/sorts/FilterPersonalizationStrategy.java +++ b/services/src/main/java/org/apache/unomi/services/sorts/FilterPersonalizationStrategy.java @@ -55,9 +55,11 @@ public PersonalizationResult personalizeList(Profile profile, Session session, P } } - String fallback = (String) personalizationRequest.getStrategyOptions().get("fallback"); - if (fallback != null && !sortedContent.contains(fallback)) { - sortedContent.add(fallback); + if (personalizationRequest.getStrategyOptions() != null) { + String fallback = (String) personalizationRequest.getStrategyOptions().get("fallback"); + if (fallback != null && !sortedContent.contains(fallback)) { + sortedContent.add(fallback); + } } return new PersonalizationResult(sortedContent); diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java index 5909d9934..caf962277 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java @@ -17,6 +17,7 @@ package org.apache.unomi.shell.actions; import org.apache.karaf.shell.api.action.Action; +import org.apache.karaf.shell.api.action.Argument; import org.apache.karaf.shell.api.action.Command; import org.apache.karaf.shell.api.action.lifecycle.Reference; import org.apache.karaf.shell.api.action.lifecycle.Service; @@ -29,8 +30,17 @@ public class Start implements Action { @Reference UnomiManagementService unomiManagementService; + @Argument(name = "persistence", description = "Persistence implementation to use (elasticsearch/opensearch)", valueToShowInHelp = "elasticsearch") + private String selectedPersistenceImplementation = "elasticsearch"; + public Object execute() throws Exception { - unomiManagementService.startUnomi(); + if (!selectedPersistenceImplementation.equals("elasticsearch") && + !selectedPersistenceImplementation.equals("opensearch")) { + System.err.println("Invalid value '"+selectedPersistenceImplementation+"' specified for persistence implementation, will default to elasticsearch"); + selectedPersistenceImplementation = "elasticsearch"; + } + System.out.println("Starting Apache Unomi with persistence implementation: " + selectedPersistenceImplementation); + unomiManagementService.startUnomi(selectedPersistenceImplementation); return null; } diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java index ebb8ba436..46a805d75 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java @@ -28,7 +28,7 @@ public interface UnomiManagementService { * This method will start Apache Unomi * @throws BundleException if there was an error starting Unomi's bundles */ - void startUnomi() throws BundleException; + void startUnomi(String selectedPersistenceImplementation) throws BundleException; /** * This method will stop Apache Unomi diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java index defe72091..ad6d9d355 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java @@ -28,23 +28,26 @@ import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; +import java.util.*; /** + * TODO We really should replace this with Karaf Features that we activate. We could still keep the starting mechanism + * to work properly with the migration process but we should remove the hardcoded list of packages in this class. * @author dgaillard */ @Component(service = UnomiManagementService.class, immediate = true) public class UnomiManagementServiceImpl implements UnomiManagementService { private BundleContext bundleContext; - + @Reference(cardinality = ReferenceCardinality.MANDATORY) private MigrationService migrationService; - + private final List bundleSymbolicNames = new ArrayList<>(); private List reversedBundleSymbolicNames; + private Map persistenceImplementations = new HashMap<>(); + private Map persistenceConditions = new HashMap<>(); + private String selectedPersistenceImplementation = "elasticsearch"; @Activate public void init(ComponentContext componentContext) throws Exception { @@ -57,13 +60,24 @@ public void init(ComponentContext componentContext) throws Exception { if (StringUtils.isNotBlank(bundleContext.getProperty("unomi.autoStart")) && bundleContext.getProperty("unomi.autoStart").equals("true")) { - startUnomi(); + startUnomi(selectedPersistenceImplementation); } } @Override - public void startUnomi() throws BundleException { + public void startUnomi(String selectedPersistenceImplementation) throws BundleException { + if (selectedPersistenceImplementation != null) { + this.selectedPersistenceImplementation = selectedPersistenceImplementation; + } for (String bundleSymbolicName : bundleSymbolicNames) { + if (bundleSymbolicName.equals("${persistenceImplementationName}")) { + bundleSymbolicName = persistenceImplementations.get(selectedPersistenceImplementation); + } else if (bundleSymbolicName.equals("${persistenceConditionsName}")) { + bundleSymbolicName = persistenceConditions.get(selectedPersistenceImplementation); + if (bundleSymbolicName == null) { + continue; + } + } for (Bundle bundle : bundleContext.getBundles()) { if (bundle.getSymbolicName().equals(bundleSymbolicName)) { if (bundle.getState() == Bundle.RESOLVED) { @@ -78,6 +92,14 @@ public void startUnomi() throws BundleException { @Override public void stopUnomi() throws BundleException { for (String bundleSymbolicName : reversedBundleSymbolicNames) { + if (bundleSymbolicName.equals("${persistenceImplementationName}")) { + bundleSymbolicName = persistenceImplementations.get(selectedPersistenceImplementation); + } else if (bundleSymbolicName.equals("${persistenceConditionsName}")) { + bundleSymbolicName = persistenceConditions.get(selectedPersistenceImplementation); + if (bundleSymbolicName == null) { + continue; + } + } for (Bundle bundle : bundleContext.getBundles()) { if (bundle.getSymbolicName().equals(bundleSymbolicName)) { if (bundle.getState() == Bundle.ACTIVE) { @@ -90,6 +112,11 @@ public void stopUnomi() throws BundleException { } public void initReversedBundleSymbolicNames() { + persistenceImplementations.clear(); + persistenceImplementations.put("elasticsearch", "org.apache.unomi.persistence-elasticsearch-core"); + persistenceImplementations.put("opensearch", "org.apache.unomi.persistence-opensearch-core"); + persistenceConditions.clear(); + persistenceConditions.put("opensearch", "org.apache.unomi.persistence-opensearch-conditions"); bundleSymbolicNames.clear(); bundleSymbolicNames.add("org.apache.unomi.lifecycle-watcher"); bundleSymbolicNames.add("org.apache.unomi.api"); @@ -97,7 +124,8 @@ public void initReversedBundleSymbolicNames() { bundleSymbolicNames.add("org.apache.unomi.scripting"); bundleSymbolicNames.add("org.apache.unomi.metrics"); bundleSymbolicNames.add("org.apache.unomi.persistence-spi"); - bundleSymbolicNames.add("org.apache.unomi.persistence-elasticsearch-core"); + bundleSymbolicNames.add("${persistenceImplementationName}"); + bundleSymbolicNames.add("${persistenceConditionsName}"); bundleSymbolicNames.add("org.apache.unomi.services"); bundleSymbolicNames.add("org.apache.unomi.cxs-lists-extension-services"); bundleSymbolicNames.add("org.apache.unomi.cxs-lists-extension-rest"); From 542e185f3ddd41416822cc1501750491401e4fd9 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Thu, 5 Dec 2024 10:19:13 +0100 Subject: [PATCH 05/58] Merges from master --- .github/workflows/unomi-ci-build-tests.yml | 17 +- api/pom.xml | 2 +- .../unomi/api/services/RulesService.java | 2 +- common/pom.xml | 4 +- docker/pom.xml | 2 +- extensions/geonames/pom.xml | 2 +- extensions/geonames/rest/pom.xml | 2 +- extensions/geonames/services/pom.xml | 2 +- extensions/groovy-actions/karaf-kar/pom.xml | 2 +- extensions/groovy-actions/pom.xml | 2 +- extensions/groovy-actions/rest/pom.xml | 2 +- extensions/groovy-actions/services/pom.xml | 2 +- extensions/healthcheck/pom.xml | 2 +- .../unomi/healthcheck/HealthCheckConfig.java | 4 + .../unomi/healthcheck/HealthCheckService.java | 33 +- extensions/json-schema/pom.xml | 2 +- extensions/json-schema/rest/pom.xml | 2 +- extensions/json-schema/services/pom.xml | 2 +- extensions/lists-extension/actions/pom.xml | 2 +- extensions/lists-extension/pom.xml | 2 +- extensions/lists-extension/rest/pom.xml | 2 +- extensions/lists-extension/services/pom.xml | 2 +- extensions/log4j-extension/pom.xml | 2 +- extensions/pom.xml | 2 +- extensions/privacy-extension/pom.xml | 2 +- extensions/privacy-extension/rest/pom.xml | 2 +- extensions/privacy-extension/services/pom.xml | 4 +- extensions/router/pom.xml | 2 +- extensions/router/router-api/pom.xml | 2 +- extensions/router/router-core/pom.xml | 2 +- .../router/router-karaf-feature/pom.xml | 2 +- extensions/router/router-rest/pom.xml | 2 +- extensions/router/router-service/pom.xml | 2 +- .../salesforce-connector/actions/pom.xml | 2 +- .../salesforce-connector/karaf-kar/pom.xml | 2 +- extensions/salesforce-connector/pom.xml | 2 +- extensions/salesforce-connector/rest/pom.xml | 2 +- .../salesforce-connector/services/pom.xml | 2 +- extensions/weather-update/core/pom.xml | 2 +- extensions/weather-update/karaf-kar/pom.xml | 2 +- extensions/weather-update/pom.xml | 2 +- extensions/web-tracker/pom.xml | 2 +- extensions/web-tracker/wab/pom.xml | 2 +- extensions/web-tracker/wab/yarn.lock | 444 +-- graphql/README.md | 2 +- graphql/cxs-impl/pom.xml | 2 +- .../main/resources/assets/styles/index.less | 25 + graphql/graphql-ui/yarn.lock | 3196 +++++++++++++++++ graphql/karaf-feature/pom.xml | 2 +- .../src/main/feature/feature.xml | 2 +- graphql/pom.xml | 4 +- .../apache/unomi/itests/HealthCheckIT.java | 10 +- kar/pom.xml | 2 +- lifecycle-watcher/pom.xml | 2 +- .../unomi/lifecycle/BundleWatcherImpl.java | 2 +- manual/pom.xml | 2 +- manual/src/main/asciidoc/graphql.adoc | 14 +- metrics/pom.xml | 2 +- package/pom.xml | 4 +- .../resources/etc/custom.system.properties | 4 +- persistence-elasticsearch/core/pom.xml | 2 +- persistence-elasticsearch/pom.xml | 2 +- plugins/baseplugin/pom.xml | 2 +- plugins/hover-event/pom.xml | 2 +- plugins/kafka-injector/pom.xml | 2 +- plugins/mail/pom.xml | 2 +- plugins/optimization-test/pom.xml | 2 +- plugins/past-event/pom.xml | 2 +- plugins/pom.xml | 2 +- plugins/request/pom.xml | 2 +- plugins/tracked-event/pom.xml | 2 +- pom.xml | 3 +- rest/pom.xml | 2 +- samples/graphql-providers-feature/pom.xml | 2 +- samples/graphql-providers/pom.xml | 2 +- samples/groovy-actions/pom.xml | 2 +- samples/login-integration/pom.xml | 2 +- samples/pom.xml | 2 +- samples/trainingplugin/pom.xml | 4 +- samples/tweet-button-plugin/pom.xml | 2 +- scripting/pom.xml | 4 +- services/pom.xml | 2 +- .../resources/assemblies/source-shared.xml | 6 +- tools/pom.xml | 2 +- tools/shell-commands/pom.xml | 2 +- .../shell/migration/utils/HttpUtils.java | 2 +- .../shell/migration/utils/MigrationUtils.java | 51 +- .../migration/migrate-2.0.0-01-aliases.groovy | 4 +- .../migrate-2.0.0-15-eventsReindex.groovy | 4 +- .../migration/migrate-2.0.0-20-scopes.groovy | 15 +- .../migrate-2.4.0-15-viewEventPagePath.groovy | 2 +- .../migrate-2.5.0-10-loginEventScope.groovy | 2 +- .../2.0.0/scope_search_by_item_id.json | 8 + tools/shell-dev-commands/pom.xml | 2 +- wab/pom.xml | 2 +- wab/src/main/webapp/index.html | 2 +- 96 files changed, 3645 insertions(+), 365 deletions(-) create mode 100644 graphql/graphql-ui/src/main/resources/assets/styles/index.less create mode 100644 graphql/graphql-ui/yarn.lock create mode 100644 tools/shell-commands/src/main/resources/requestBody/2.0.0/scope_search_by_item_id.json diff --git a/.github/workflows/unomi-ci-build-tests.yml b/.github/workflows/unomi-ci-build-tests.yml index aaafa2d79..a96651251 100644 --- a/.github/workflows/unomi-ci-build-tests.yml +++ b/.github/workflows/unomi-ci-build-tests.yml @@ -13,15 +13,16 @@ jobs: unit-tests: name: Execute unit tests runs-on: ubuntu-latest + timeout-minutes: 15 steps: - - uses: actions/checkout@v4 - - name: Set up JDK 11 - uses: actions/setup-java@v1 - with: - java-version: 11 - cache: maven - - name: Build and Unit tests - run: mvn -U -ntp -e clean install + - uses: actions/checkout@v4 + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + cache: maven + - name: Build and Unit tests + run: mvn -U -ntp -e clean install integration-tests: name: Execute integration tests diff --git a/api/pom.xml b/api/pom.xml index ea3176905..3ed267975 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-api diff --git a/api/src/main/java/org/apache/unomi/api/services/RulesService.java b/api/src/main/java/org/apache/unomi/api/services/RulesService.java index 52a97ee34..dd5a44786 100644 --- a/api/src/main/java/org/apache/unomi/api/services/RulesService.java +++ b/api/src/main/java/org/apache/unomi/api/services/RulesService.java @@ -37,7 +37,7 @@ public interface RulesService { /** * Retrieves the metadata for all known rules. - * + * Note that it only includes the rules in memory, not those persisted in storage. * @return the Set of known metadata */ Set getRuleMetadatas(); diff --git a/common/pom.xml b/common/pom.xml index 255bb2672..e202af18d 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-common @@ -58,7 +58,7 @@ org.apache.unomi unomi-api - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT test diff --git a/docker/pom.xml b/docker/pom.xml index 4021f40d2..57502de25 100644 --- a/docker/pom.xml +++ b/docker/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-docker diff --git a/extensions/geonames/pom.xml b/extensions/geonames/pom.xml index 732d791d0..f83aaccbb 100644 --- a/extensions/geonames/pom.xml +++ b/extensions/geonames/pom.xml @@ -27,7 +27,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT cxs-geonames diff --git a/extensions/geonames/rest/pom.xml b/extensions/geonames/rest/pom.xml index 8bd79d067..34b3f1ce3 100644 --- a/extensions/geonames/rest/pom.xml +++ b/extensions/geonames/rest/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi cxs-geonames - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/geonames/services/pom.xml b/extensions/geonames/services/pom.xml index 2f9595ae1..0fe65c5b9 100644 --- a/extensions/geonames/services/pom.xml +++ b/extensions/geonames/services/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi cxs-geonames - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/groovy-actions/karaf-kar/pom.xml b/extensions/groovy-actions/karaf-kar/pom.xml index 20fe1fce2..ff874dc6d 100644 --- a/extensions/groovy-actions/karaf-kar/pom.xml +++ b/extensions/groovy-actions/karaf-kar/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-groovy-actions-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/groovy-actions/pom.xml b/extensions/groovy-actions/pom.xml index 2a8030290..53892b110 100644 --- a/extensions/groovy-actions/pom.xml +++ b/extensions/groovy-actions/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-groovy-actions-root diff --git a/extensions/groovy-actions/rest/pom.xml b/extensions/groovy-actions/rest/pom.xml index 71dc94bdc..de1052262 100644 --- a/extensions/groovy-actions/rest/pom.xml +++ b/extensions/groovy-actions/rest/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-groovy-actions-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/groovy-actions/services/pom.xml b/extensions/groovy-actions/services/pom.xml index e0d5576fb..3d4de386e 100644 --- a/extensions/groovy-actions/services/pom.xml +++ b/extensions/groovy-actions/services/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-groovy-actions-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/healthcheck/pom.xml b/extensions/healthcheck/pom.xml index aa399e370..8b5f9253b 100644 --- a/extensions/healthcheck/pom.xml +++ b/extensions/healthcheck/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT healthcheck diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java index a36501fda..e86018dc3 100644 --- a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java @@ -65,6 +65,10 @@ public String get(String configKey) { return this.config.get(configKey); } + public int getSize() { + return this.config.size(); + } + public boolean isEnabled() { return enabled; } diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java index 54a288063..9da585e14 100644 --- a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckService.java @@ -49,31 +49,28 @@ public class HealthCheckService { @Reference protected HttpService httpService; - @Reference(cardinality = ReferenceCardinality.MANDATORY, updated = "updated") private HealthCheckConfig config; public HealthCheckService() { LOGGER.info("Building healthcheck service..."); } - public void setConfig(HealthCheckConfig config) { - this.config = config; - } - @Activate public void activate() throws ServletException, NamespaceException { - if (config.isEnabled()) { - LOGGER.info("Activating healthcheck service..."); - executor = Executors.newSingleThreadExecutor(); - httpService.registerServlet("/health/check", new HealthCheckServlet(this), null, - new HealthCheckHttpContext(config.get(CONFIG_AUTH_REALM))); - this.registered = true; - } else { - LOGGER.info("Healthcheck service is disabled"); + LOGGER.info("Activating healthcheck service..."); + executor = Executors.newSingleThreadExecutor(); + if (!registered) { + setConfig(config); } } - public void updated() throws ServletException, NamespaceException { + @Reference(service = HealthCheckConfig.class, policy = ReferencePolicy.DYNAMIC, updated = "setConfig") + private void setConfig(HealthCheckConfig config) throws ServletException, NamespaceException { + this.config = config; + if (httpService == null ) { + LOGGER.info("Healthcheck config with {} entrie(s) did not update the service as not fully started yet.", config.getSize()); + return; + } if (config.isEnabled()) { LOGGER.info("Updating healthcheck service..."); if (registered) { @@ -84,10 +81,16 @@ public void updated() throws ServletException, NamespaceException { new HealthCheckHttpContext(config.get(CONFIG_AUTH_REALM))); registered = true; } else { + httpService.unregister("/health/check"); + registered = false; LOGGER.info("Healthcheck service is disabled"); } } + private void unsetConfig(HealthCheckConfig config) { + this.config = null; + } + @Deactivate public void deactivate() { LOGGER.info("Deactivating healthcheck service..."); @@ -112,7 +115,7 @@ protected void unbind(HealthCheckProvider provider) { } public List check() throws RejectedExecutionException { - if (config.isEnabled()) { + if (config !=null && config.isEnabled()) { LOGGER.debug("Health check called"); if (busy) { throw new RejectedExecutionException("Health check already in progress"); diff --git a/extensions/json-schema/pom.xml b/extensions/json-schema/pom.xml index aa80be000..a38969f6a 100644 --- a/extensions/json-schema/pom.xml +++ b/extensions/json-schema/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-json-schema-root diff --git a/extensions/json-schema/rest/pom.xml b/extensions/json-schema/rest/pom.xml index 261869b06..a9d9094d6 100644 --- a/extensions/json-schema/rest/pom.xml +++ b/extensions/json-schema/rest/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-json-schema-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/json-schema/services/pom.xml b/extensions/json-schema/services/pom.xml index 196aaa6a5..4538c8846 100644 --- a/extensions/json-schema/services/pom.xml +++ b/extensions/json-schema/services/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-json-schema-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/lists-extension/actions/pom.xml b/extensions/lists-extension/actions/pom.xml index 85b05a9a6..e6a1f753d 100644 --- a/extensions/lists-extension/actions/pom.xml +++ b/extensions/lists-extension/actions/pom.xml @@ -20,7 +20,7 @@ cxs-lists-extension org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/lists-extension/pom.xml b/extensions/lists-extension/pom.xml index 250e15d6c..426d9f4ff 100644 --- a/extensions/lists-extension/pom.xml +++ b/extensions/lists-extension/pom.xml @@ -28,7 +28,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT cxs-lists-extension diff --git a/extensions/lists-extension/rest/pom.xml b/extensions/lists-extension/rest/pom.xml index 825a404e7..2ef53bcba 100644 --- a/extensions/lists-extension/rest/pom.xml +++ b/extensions/lists-extension/rest/pom.xml @@ -20,7 +20,7 @@ cxs-lists-extension org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/lists-extension/services/pom.xml b/extensions/lists-extension/services/pom.xml index 7e1aa783b..7cabb2a02 100644 --- a/extensions/lists-extension/services/pom.xml +++ b/extensions/lists-extension/services/pom.xml @@ -20,7 +20,7 @@ cxs-lists-extension org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/log4j-extension/pom.xml b/extensions/log4j-extension/pom.xml index a4231adf0..007010d3b 100644 --- a/extensions/log4j-extension/pom.xml +++ b/extensions/log4j-extension/pom.xml @@ -23,7 +23,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT ../pom.xml diff --git a/extensions/pom.xml b/extensions/pom.xml index fc756fbd4..707f8b78a 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-extensions diff --git a/extensions/privacy-extension/pom.xml b/extensions/privacy-extension/pom.xml index deb5955c0..e11174c96 100644 --- a/extensions/privacy-extension/pom.xml +++ b/extensions/privacy-extension/pom.xml @@ -27,7 +27,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT cxs-privacy-extension diff --git a/extensions/privacy-extension/rest/pom.xml b/extensions/privacy-extension/rest/pom.xml index 7cd66c70c..e55837ace 100644 --- a/extensions/privacy-extension/rest/pom.xml +++ b/extensions/privacy-extension/rest/pom.xml @@ -20,7 +20,7 @@ cxs-privacy-extension org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/privacy-extension/services/pom.xml b/extensions/privacy-extension/services/pom.xml index 14e77b7f5..ff8b64442 100644 --- a/extensions/privacy-extension/services/pom.xml +++ b/extensions/privacy-extension/services/pom.xml @@ -20,14 +20,14 @@ cxs-privacy-extension org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 cxs-privacy-extension-services Apache Unomi :: Extensions :: Privacy :: Services Privacy management extension service implementation for the Apache Unomi Context Server - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT bundle diff --git a/extensions/router/pom.xml b/extensions/router/pom.xml index 2aff5302d..952614678 100644 --- a/extensions/router/pom.xml +++ b/extensions/router/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-router diff --git a/extensions/router/router-api/pom.xml b/extensions/router/router-api/pom.xml index 27b2c3ac7..ef5a6d63c 100644 --- a/extensions/router/router-api/pom.xml +++ b/extensions/router/router-api/pom.xml @@ -19,7 +19,7 @@ unomi-router org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/router/router-core/pom.xml b/extensions/router/router-core/pom.xml index 6035cd6a0..a8ce97fd4 100644 --- a/extensions/router/router-core/pom.xml +++ b/extensions/router/router-core/pom.xml @@ -19,7 +19,7 @@ unomi-router org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/router/router-karaf-feature/pom.xml b/extensions/router/router-karaf-feature/pom.xml index 4762bc1aa..1ef821ef1 100644 --- a/extensions/router/router-karaf-feature/pom.xml +++ b/extensions/router/router-karaf-feature/pom.xml @@ -19,7 +19,7 @@ unomi-router org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/router/router-rest/pom.xml b/extensions/router/router-rest/pom.xml index c97ae54d6..341594b03 100644 --- a/extensions/router/router-rest/pom.xml +++ b/extensions/router/router-rest/pom.xml @@ -19,7 +19,7 @@ unomi-router org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/router/router-service/pom.xml b/extensions/router/router-service/pom.xml index 59d9eaae0..c24e9e2d6 100644 --- a/extensions/router/router-service/pom.xml +++ b/extensions/router/router-service/pom.xml @@ -19,7 +19,7 @@ unomi-router org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/salesforce-connector/actions/pom.xml b/extensions/salesforce-connector/actions/pom.xml index f75adbff1..e3d7c2b7c 100644 --- a/extensions/salesforce-connector/actions/pom.xml +++ b/extensions/salesforce-connector/actions/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-salesforce-connector - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/salesforce-connector/karaf-kar/pom.xml b/extensions/salesforce-connector/karaf-kar/pom.xml index 011bfd538..5bf6caff2 100644 --- a/extensions/salesforce-connector/karaf-kar/pom.xml +++ b/extensions/salesforce-connector/karaf-kar/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-salesforce-connector - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/salesforce-connector/pom.xml b/extensions/salesforce-connector/pom.xml index 6f1084d04..b759f7d5b 100644 --- a/extensions/salesforce-connector/pom.xml +++ b/extensions/salesforce-connector/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-salesforce-connector diff --git a/extensions/salesforce-connector/rest/pom.xml b/extensions/salesforce-connector/rest/pom.xml index 121d38892..d40ff5314 100644 --- a/extensions/salesforce-connector/rest/pom.xml +++ b/extensions/salesforce-connector/rest/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-salesforce-connector - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/salesforce-connector/services/pom.xml b/extensions/salesforce-connector/services/pom.xml index cbbff2378..5ab56663c 100644 --- a/extensions/salesforce-connector/services/pom.xml +++ b/extensions/salesforce-connector/services/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-salesforce-connector - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/weather-update/core/pom.xml b/extensions/weather-update/core/pom.xml index d57267cda..df00b96b0 100755 --- a/extensions/weather-update/core/pom.xml +++ b/extensions/weather-update/core/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-weather-update - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-weather-update-core diff --git a/extensions/weather-update/karaf-kar/pom.xml b/extensions/weather-update/karaf-kar/pom.xml index c61943c40..5a7a1ab49 100644 --- a/extensions/weather-update/karaf-kar/pom.xml +++ b/extensions/weather-update/karaf-kar/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-weather-update - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/extensions/weather-update/pom.xml b/extensions/weather-update/pom.xml index 9607b7214..6324cd0ec 100644 --- a/extensions/weather-update/pom.xml +++ b/extensions/weather-update/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-weather-update diff --git a/extensions/web-tracker/pom.xml b/extensions/web-tracker/pom.xml index ffc388e50..3f962a423 100644 --- a/extensions/web-tracker/pom.xml +++ b/extensions/web-tracker/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-extensions - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-web-tracker diff --git a/extensions/web-tracker/wab/pom.xml b/extensions/web-tracker/wab/pom.xml index 207d2da12..b7b2633d0 100644 --- a/extensions/web-tracker/wab/pom.xml +++ b/extensions/web-tracker/wab/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-web-tracker - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-web-tracker-wab diff --git a/extensions/web-tracker/wab/yarn.lock b/extensions/web-tracker/wab/yarn.lock index 1ba5f474a..879c19dd7 100644 --- a/extensions/web-tracker/wab/yarn.lock +++ b/extensions/web-tracker/wab/yarn.lock @@ -4,7 +4,7 @@ "@ampproject/remapping@^2.1.0": version "2.2.0" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: "@jridgewell/gen-mapping" "^0.1.0" @@ -12,19 +12,19 @@ "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9" integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg== "@babel/core@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b" integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw== dependencies: "@ampproject/remapping" "^2.1.0" @@ -45,7 +45,7 @@ "@babel/generator@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== dependencies: "@babel/types" "^7.19.0" @@ -54,14 +54,14 @@ "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== dependencies: "@babel/helper-explode-assignable-expression" "^7.18.6" @@ -69,7 +69,7 @@ "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c" integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg== dependencies: "@babel/compat-data" "^7.19.1" @@ -79,7 +79,7 @@ "@babel/helper-create-class-features-plugin@^7.18.6": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -92,7 +92,7 @@ "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -100,7 +100,7 @@ "@babel/helper-define-polyfill-provider@^0.3.3": version "0.3.3" - resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== dependencies: "@babel/helper-compilation-targets" "^7.17.7" @@ -112,19 +112,19 @@ "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== "@babel/helper-explode-assignable-expression@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== dependencies: "@babel/types" "^7.18.6" "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: "@babel/template" "^7.18.10" @@ -132,28 +132,28 @@ "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== dependencies: "@babel/types" "^7.18.9" "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -167,19 +167,19 @@ "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -189,7 +189,7 @@ "@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -200,43 +200,43 @@ "@babel/helper-simple-access@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== dependencies: "@babel/types" "^7.18.6" "@babel/helper-skip-transparent-expression-wrappers@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw== dependencies: "@babel/types" "^7.18.9" "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-string-parser@^7.18.10": version "7.18.10" - resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== "@babel/helper-validator-identifier@^7.18.6": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== "@babel/helper-validator-option@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== "@babel/helper-wrap-function@^7.18.9": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== dependencies: "@babel/helper-function-name" "^7.19.0" @@ -246,7 +246,7 @@ "@babel/helpers@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== dependencies: "@babel/template" "^7.18.10" @@ -255,7 +255,7 @@ "@babel/highlight@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== dependencies: "@babel/helper-validator-identifier" "^7.18.6" @@ -264,19 +264,19 @@ "@babel/parser@^7.18.10", "@babel/parser@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c" integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -285,7 +285,7 @@ "@babel/plugin-proposal-async-generator-functions@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7" integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -295,7 +295,7 @@ "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -303,7 +303,7 @@ "@babel/plugin-proposal-class-static-block@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -312,7 +312,7 @@ "@babel/plugin-proposal-dynamic-import@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -320,7 +320,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -328,7 +328,7 @@ "@babel/plugin-proposal-json-strings@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -336,7 +336,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -344,7 +344,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -352,7 +352,7 @@ "@babel/plugin-proposal-numeric-separator@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -360,7 +360,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7" integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q== dependencies: "@babel/compat-data" "^7.18.8" @@ -371,7 +371,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -379,7 +379,7 @@ "@babel/plugin-proposal-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -388,7 +388,7 @@ "@babel/plugin-proposal-private-methods@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -396,7 +396,7 @@ "@babel/plugin-proposal-private-property-in-object@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -406,7 +406,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -414,119 +414,119 @@ "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-async-to-generator@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: "@babel/helper-module-imports" "^7.18.6" @@ -535,21 +535,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-block-scoping@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d" integrity sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-classes@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -564,21 +564,21 @@ "@babel/plugin-transform-computed-properties@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-destructuring@^7.18.13": version "7.18.13" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -586,14 +586,14 @@ "@babel/plugin-transform-duplicate-keys@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-exponentiation-operator@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" @@ -601,14 +601,14 @@ "@babel/plugin-transform-for-of@^7.18.8": version "7.18.8" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-function-name@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== dependencies: "@babel/helper-compilation-targets" "^7.18.9" @@ -617,21 +617,21 @@ "@babel/plugin-transform-literals@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-member-expression-literals@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-modules-amd@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21" integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -640,7 +640,7 @@ "@babel/plugin-transform-modules-commonjs@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -650,7 +650,7 @@ "@babel/plugin-transform-modules-systemjs@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f" integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A== dependencies: "@babel/helper-hoist-variables" "^7.18.6" @@ -661,7 +661,7 @@ "@babel/plugin-transform-modules-umd@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -669,7 +669,7 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.19.0" @@ -677,14 +677,14 @@ "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-object-super@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -692,21 +692,21 @@ "@babel/plugin-transform-parameters@^7.18.8": version "7.18.8" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a" integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-regenerator@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -714,21 +714,21 @@ "@babel/plugin-transform-reserved-words@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-shorthand-properties@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-spread@^7.19.0": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== dependencies: "@babel/helper-plugin-utils" "^7.19.0" @@ -736,35 +736,35 @@ "@babel/plugin-transform-sticky-regex@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-template-literals@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-typeof-symbol@^7.18.9": version "7.18.9" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-escapes@^7.18.10": version "7.18.10" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-regex@^7.18.6": version "7.18.6" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -772,7 +772,7 @@ "@babel/preset-env@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.1.tgz#9f04c916f9c0205a48ebe5cc1be7768eb1983f67" integrity sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA== dependencies: "@babel/compat-data" "^7.19.1" @@ -853,7 +853,7 @@ "@babel/preset-modules@^0.1.5": version "0.1.5" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" + resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -864,21 +864,21 @@ "@babel/runtime@^7.18.9": version "7.24.7" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" "@babel/runtime@^7.8.4": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== dependencies: regenerator-runtime "^0.13.4" "@babel/template@^7.18.10": version "7.18.10" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== dependencies: "@babel/code-frame" "^7.18.6" @@ -887,7 +887,7 @@ "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1": version "7.19.1" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347" integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA== dependencies: "@babel/code-frame" "^7.18.6" @@ -903,7 +903,7 @@ "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4": version "7.19.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== dependencies: "@babel/helper-string-parser" "^7.18.10" @@ -912,7 +912,7 @@ "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== dependencies: "@jridgewell/set-array" "^1.0.0" @@ -920,7 +920,7 @@ "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" - resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -929,17 +929,17 @@ "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.2": version "0.3.2" - resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== dependencies: "@jridgewell/gen-mapping" "^0.3.0" @@ -947,12 +947,12 @@ "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== dependencies: "@jridgewell/resolve-uri" "^3.0.3" @@ -960,7 +960,7 @@ "@rollup/plugin-babel@^5.3.1": version "5.3.1" - resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz" + resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q== dependencies: "@babel/helper-module-imports" "^7.10.4" @@ -968,7 +968,7 @@ "@rollup/plugin-commonjs@^22.0.2": version "22.0.2" - resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz" + resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz#ee8ca8415cda30d383b4096aad5222435b4b69b6" integrity sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -981,7 +981,7 @@ "@rollup/plugin-inject@^4.0.0": version "4.0.4" - resolved "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-4.0.4.tgz" + resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-4.0.4.tgz#fbeee66e9a700782c4f65c8b0edbafe58678fbc2" integrity sha512-4pbcU4J/nS+zuHk+c+OL3WtmEQhqxlZ9uqfjQMQDOHOPld7PsCd8k5LWs8h5wjwJN7MgnAn768F2sDxEP4eNFQ== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -990,7 +990,7 @@ "@rollup/plugin-node-resolve@^14.1.0": version "14.1.0" - resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz#f2fa475405cd7fed6420bf438fe393f988a9bc96" integrity sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -1002,7 +1002,7 @@ "@rollup/pluginutils@^3.0.9", "@rollup/pluginutils@^3.1.0": version "3.1.0" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== dependencies: "@types/estree" "0.0.39" @@ -1011,41 +1011,41 @@ "@types/estree@*": version "1.0.0" - resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== "@types/estree@0.0.39": version "0.0.39" - resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/node@*": version "18.7.18" - resolved "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.18.tgz#633184f55c322e4fb08612307c274ee6d5ed3154" integrity sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg== "@types/resolve@1.17.1": version "1.17.1" - resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== dependencies: "@types/node" "*" acorn@^8.5.0: version "8.8.0" - resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" apache-unomi-tracker@^1.1.0: version "1.4.0" - resolved "https://registry.npmjs.org/apache-unomi-tracker/-/apache-unomi-tracker-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/apache-unomi-tracker/-/apache-unomi-tracker-1.4.0.tgz#50707986531fc4f5dec28cdf06a18e48610bcb78" integrity sha512-5mYm1GQDrzUNxYcQymmGYYkk7AKjGakI5T3wUH4apjiRzKwPMiMyRvc45HvYNmcCGZoPlP1AEcimVu+2t0M7PA== dependencies: "@babel/runtime" "^7.18.9" @@ -1053,19 +1053,19 @@ apache-unomi-tracker@^1.1.0: atob@^2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" babel-plugin-polyfill-corejs2@^0.3.3: version "0.3.3" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== dependencies: "@babel/compat-data" "^7.17.7" @@ -1074,7 +1074,7 @@ babel-plugin-polyfill-corejs2@^0.3.3: babel-plugin-polyfill-corejs3@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" @@ -1082,19 +1082,19 @@ babel-plugin-polyfill-corejs3@^0.6.0: babel-plugin-polyfill-regenerator@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1102,7 +1102,7 @@ brace-expansion@^1.1.7: browserslist@^4.21.3, browserslist@^4.21.4: version "4.21.4" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== dependencies: caniuse-lite "^1.0.30001400" @@ -1112,17 +1112,17 @@ browserslist@^4.21.3, browserslist@^4.21.4: buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== builtin-modules@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1130,12 +1130,12 @@ call-bind@^1.0.2: caniuse-lite@^1.0.30001400: version "1.0.30001407" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz#92281a6ee67cb90bfd8a6a1201fcc2dc19b60a15" integrity sha512-4ydV+t4P7X3zH83fQWNDX/mQEzYomossfpViCOx9zHBSMV+rIe3LFqglHHtVyvNl1FhTNxPxs3jei82iqOW04w== chalk@^2.0.0: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1144,65 +1144,65 @@ chalk@^2.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== commander@^2.20.0: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^1.7.0: version "1.8.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" core-js-compat@^3.25.1: version "3.25.2" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.2.tgz" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.2.tgz#7875573586809909c69e03ef310810c1969ee138" integrity sha512-TxfyECD4smdn3/CjWxczVtJqVLEEC2up7/82t7vC0AzNogr+4nQ8vyF7abxAuTXWvjTClSbvGhU0RgqA4ToQaQ== dependencies: browserslist "^4.21.4" debug@^4.1.0, debug@^4.1.1: version "4.3.4" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== deepmerge@^4.2.2: version "4.2.2" - resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== define-properties@^1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: has-property-descriptors "^1.0.0" @@ -1210,62 +1210,62 @@ define-properties@^1.1.4: electron-to-chromium@^1.4.251: version "1.4.255" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz#dc52d1095b876ed8acf25865db10265b02b1d6e1" integrity sha512-H+mFNKow6gi2P5Gi2d1Fvd3TUEJlB9CF7zYaIV9T83BE3wP1xZ0mRPbNTm0KUjyd1QiVy7iKXuIcjlDtBQMiAQ== es6-crawler-detect@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/es6-crawler-detect/-/es6-crawler-detect-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/es6-crawler-detect/-/es6-crawler-detect-3.3.0.tgz#3a05cd3f2739099145bf40b012a6ad472cbbfb49" integrity sha512-ptGU13H76+HNr5n0kvi5aO+RuqRHaIET/60Srv4+BgVWsuVVf3x9seDhz/IEcmuQMXJvrU2g+DbrKVrliUkTJQ== escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== estree-walker@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== estree-walker@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.3" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== dependencies: function-bind "^1.1.1" @@ -1274,7 +1274,7 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: glob@^7.1.6: version "7.2.3" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1286,41 +1286,41 @@ glob@^7.1.6: globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: get-intrinsic "^1.1.1" has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -1328,38 +1328,38 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== is-builtin-module@^3.1.0: version "3.2.0" - resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0" integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw== dependencies: builtin-modules "^3.3.0" is-core-module@^2.9.0: version "2.10.0" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== dependencies: has "^1.0.3" is-module@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== is-reference@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== dependencies: "@types/estree" "*" jest-worker@^26.2.1: version "26.6.2" - resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: "@types/node" "*" @@ -1368,66 +1368,66 @@ jest-worker@^26.2.1: js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== json5@^2.2.1: version "2.2.1" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== magic-string@^0.25.7: version "0.25.9" - resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== dependencies: sourcemap-codec "^1.4.8" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== minimatch@^3.1.1: version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== node-releases@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.0: version "4.1.4" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -1437,70 +1437,70 @@ object.assign@^4.1.0: once@^1.3.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== picocolors@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.2.2: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" regenerate-unicode-properties@^10.1.0: version "10.1.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== dependencies: regenerate "^1.4.2" regenerate@^1.4.2: version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: version "0.13.11" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regenerator-runtime@^0.14.0: version "0.14.1" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regenerator-transform@^0.15.0: version "0.15.0" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== dependencies: "@babel/runtime" "^7.8.4" regexpu-core@^5.1.0: version "5.2.1" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139" integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ== dependencies: regenerate "^1.4.2" @@ -1512,19 +1512,19 @@ regexpu-core@^5.1.0: regjsgen@^0.7.1: version "0.7.1" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== regjsparser@^0.9.1: version "0.9.1" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0: version "1.22.1" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: is-core-module "^2.9.0" @@ -1533,14 +1533,14 @@ resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0: rollup-plugin-polyfill-node@^0.10.2: version "0.10.2" - resolved "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.10.2.tgz" + resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.10.2.tgz#b2128646851fcb9475ddfd5bc22ca1a8c568738d" integrity sha512-5GMywXiLiuQP6ZzED/LO/Q0HyDi2W6b8VN+Zd3oB0opIjyRs494Me2ZMaqKWDNbGiW4jvvzl6L2n4zRgxS9cSQ== dependencies: "@rollup/plugin-inject" "^4.0.0" rollup-plugin-sourcemaps@^0.6.3: version "0.6.3" - resolved "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz" + resolved "https://registry.yarnpkg.com/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz#bf93913ffe056e414419607f1d02780d7ece84ed" integrity sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw== dependencies: "@rollup/pluginutils" "^3.0.9" @@ -1548,7 +1548,7 @@ rollup-plugin-sourcemaps@^0.6.3: rollup-plugin-terser@^7.0.2: version "7.0.2" - resolved "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== dependencies: "@babel/code-frame" "^7.10.4" @@ -1558,36 +1558,36 @@ rollup-plugin-terser@^7.0.2: rollup@^2.79.0: version "2.79.0" - resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.0.tgz#9177992c9f09eb58c5e56cbfa641607a12b57ce2" integrity sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA== optionalDependencies: fsevents "~2.3.2" safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== serialize-javascript@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: randombytes "^2.1.0" source-map-resolve@^0.6.0: version "0.6.0" - resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== dependencies: atob "^2.1.2" @@ -1595,7 +1595,7 @@ source-map-resolve@^0.6.0: source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -1603,36 +1603,36 @@ source-map-support@~0.5.20: source-map@^0.6.0: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sourcemap-codec@^1.4.8: version "1.4.8" - resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.0.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== terser@^5.0.0: version "5.15.0" - resolved "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== dependencies: "@jridgewell/source-map" "^0.3.2" @@ -1642,17 +1642,17 @@ terser@^5.0.0: to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: unicode-canonical-property-names-ecmascript "^2.0.0" @@ -1660,17 +1660,17 @@ unicode-match-property-ecmascript@^2.0.0: unicode-match-property-value-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== update-browserslist-db@^1.0.9: version "1.0.9" - resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg== dependencies: escalade "^3.1.1" @@ -1678,5 +1678,5 @@ update-browserslist-db@^1.0.9: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== diff --git a/graphql/README.md b/graphql/README.md index 269f002e1..ee39d64b3 100644 --- a/graphql/README.md +++ b/graphql/README.md @@ -30,7 +30,7 @@ You can then access the GraphQL endpoint at the following URL: http://localhost:8181/graphql -The Graphql Playground is available at the following URL: +The Graphql UI is available at the following URL: http://localhost:8181/graphql-ui diff --git a/graphql/cxs-impl/pom.xml b/graphql/cxs-impl/pom.xml index fd9ffb663..03efbc46f 100644 --- a/graphql/cxs-impl/pom.xml +++ b/graphql/cxs-impl/pom.xml @@ -19,7 +19,7 @@ org.apache.unomi unomi-graphql - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/graphql/graphql-ui/src/main/resources/assets/styles/index.less b/graphql/graphql-ui/src/main/resources/assets/styles/index.less new file mode 100644 index 000000000..5d614bc75 --- /dev/null +++ b/graphql/graphql-ui/src/main/resources/assets/styles/index.less @@ -0,0 +1,25 @@ +@import "~graphiql/graphiql.css"; + +html, body { + height: 100%; + margin: 0; +} + +#root { + height: 100%; +} + +#root .docExplorerResizer { + position: relative; +} + +.loading { + font-size: 32px; + font-weight: 200; + color: rgba(255, 255, 255, .6); + margin-left: 20px; +} + +.loading .title { + font-weight: 400; +} diff --git a/graphql/graphql-ui/yarn.lock b/graphql/graphql-ui/yarn.lock new file mode 100644 index 000000000..ef1f31db1 --- /dev/null +++ b/graphql/graphql-ui/yarn.lock @@ -0,0 +1,3196 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + +"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== + +"@babel/core@^7.10.4": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.10" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.12.10", "@babel/generator@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== + dependencies: + "@babel/types" "^7.12.11" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== + dependencies: + "@babel/types" "^7.12.10" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helper-compilation-targets@^7.12.5": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== + dependencies: + "@babel/compat-data" "^7.12.5" + "@babel/helper-validator-option" "^7.12.1" + browserslist "^4.14.5" + semver "^5.5.0" + +"@babel/helper-create-class-features-plugin@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-member-expression-to-functions" "^7.12.1" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + +"@babel/helper-create-regexp-features-plugin@^7.12.1": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + regexpu-core "^4.7.1" + +"@babel/helper-define-map@^7.10.4": + version "7.10.5" + resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/types" "^7.10.5" + lodash "^4.17.19" + +"@babel/helper-explode-assignable-expression@^7.10.4": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.10" + "@babel/template" "^7.12.7" + "@babel/types" "^7.12.11" + +"@babel/helper-get-function-arity@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== + dependencies: + "@babel/types" "^7.12.10" + +"@babel/helper-hoist-variables@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== + dependencies: + "@babel/types" "^7.10.4" + +"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== + dependencies: + "@babel/types" "^7.12.7" + +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== + dependencies: + "@babel/types" "^7.12.5" + +"@babel/helper-module-transforms@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-simple-access" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/helper-validator-identifier" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.1" + "@babel/types" "^7.12.1" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== + dependencies: + "@babel/types" "^7.12.10" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== + +"@babel/helper-remap-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-wrap-function" "^7.10.4" + "@babel/types" "^7.12.1" + +"@babel/helper-replace-supers@^7.12.1": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.7" + "@babel/helper-optimise-call-expression" "^7.12.10" + "@babel/traverse" "^7.12.10" + "@babel/types" "^7.12.11" + +"@babel/helper-simple-access@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-skip-transparent-expression-wrappers@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== + dependencies: + "@babel/types" "^7.12.1" + +"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== + dependencies: + "@babel/types" "^7.12.11" + +"@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + +"@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== + +"@babel/helper-wrap-function@^7.10.4": + version "7.12.3" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.10.4" + "@babel/types" "^7.10.4" + +"@babel/helpers@^7.12.5": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== + dependencies: + "@babel/template" "^7.10.4" + "@babel/traverse" "^7.12.5" + "@babel/types" "^7.12.5" + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== + +"@babel/plugin-proposal-async-generator-functions@^7.12.1": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-dynamic-import@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + +"@babel/plugin-proposal-export-namespace-from@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + +"@babel/plugin-proposal-json-strings@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-logical-assignment-operators@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-numeric-separator@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + +"@babel/plugin-proposal-object-rest-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-transform-parameters" "^7.12.1" + +"@babel/plugin-proposal-optional-catch-binding@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-private-methods@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-export-namespace-from@^7.8.3": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.10.4": + version "7.10.4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-arrow-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-async-to-generator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== + dependencies: + "@babel/helper-module-imports" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-remap-async-to-generator" "^7.12.1" + +"@babel/plugin-transform-block-scoped-functions@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-block-scoping@^7.12.11": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-classes@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-define-map" "^7.10.4" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-optimise-call-expression" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + "@babel/helper-split-export-declaration" "^7.10.4" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-destructuring@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-duplicate-keys@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-exponentiation-operator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-for-of@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-function-name@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== + dependencies: + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-member-expression-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-modules-amd@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-commonjs@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-simple-access" "^7.12.1" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-systemjs@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== + dependencies: + "@babel/helper-hoist-variables" "^7.10.4" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-identifier" "^7.10.4" + babel-plugin-dynamic-import-node "^2.3.3" + +"@babel/plugin-transform-modules-umd@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== + dependencies: + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + +"@babel/plugin-transform-new-target@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-object-super@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-replace-supers" "^7.12.1" + +"@babel/plugin-transform-parameters@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-property-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-react-display-name@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" + integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-react-jsx-development@^7.12.7": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" + integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== + dependencies: + "@babel/plugin-transform-react-jsx" "^7.12.12" + +"@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" + integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.12.10" + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-syntax-jsx" "^7.12.1" + "@babel/types" "^7.12.12" + +"@babel/plugin-transform-react-pure-annotations@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" + integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.10.4" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-regenerator@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== + dependencies: + regenerator-transform "^0.14.2" + +"@babel/plugin-transform-reserved-words@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-shorthand-properties@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-spread@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" + +"@babel/plugin-transform-sticky-regex@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-template-literals@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-typeof-symbol@^7.12.10": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-escapes@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-transform-unicode-regex@^7.12.1": + version "7.12.1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.12.1" + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/preset-env@^7.10.4": + version "7.12.11" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== + dependencies: + "@babel/compat-data" "^7.12.7" + "@babel/helper-compilation-targets" "^7.12.5" + "@babel/helper-module-imports" "^7.12.5" + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/helper-validator-option" "^7.12.11" + "@babel/plugin-proposal-async-generator-functions" "^7.12.1" + "@babel/plugin-proposal-class-properties" "^7.12.1" + "@babel/plugin-proposal-dynamic-import" "^7.12.1" + "@babel/plugin-proposal-export-namespace-from" "^7.12.1" + "@babel/plugin-proposal-json-strings" "^7.12.1" + "@babel/plugin-proposal-logical-assignment-operators" "^7.12.1" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.12.1" + "@babel/plugin-proposal-numeric-separator" "^7.12.7" + "@babel/plugin-proposal-object-rest-spread" "^7.12.1" + "@babel/plugin-proposal-optional-catch-binding" "^7.12.1" + "@babel/plugin-proposal-optional-chaining" "^7.12.7" + "@babel/plugin-proposal-private-methods" "^7.12.1" + "@babel/plugin-proposal-unicode-property-regex" "^7.12.1" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-class-properties" "^7.12.1" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.12.1" + "@babel/plugin-transform-arrow-functions" "^7.12.1" + "@babel/plugin-transform-async-to-generator" "^7.12.1" + "@babel/plugin-transform-block-scoped-functions" "^7.12.1" + "@babel/plugin-transform-block-scoping" "^7.12.11" + "@babel/plugin-transform-classes" "^7.12.1" + "@babel/plugin-transform-computed-properties" "^7.12.1" + "@babel/plugin-transform-destructuring" "^7.12.1" + "@babel/plugin-transform-dotall-regex" "^7.12.1" + "@babel/plugin-transform-duplicate-keys" "^7.12.1" + "@babel/plugin-transform-exponentiation-operator" "^7.12.1" + "@babel/plugin-transform-for-of" "^7.12.1" + "@babel/plugin-transform-function-name" "^7.12.1" + "@babel/plugin-transform-literals" "^7.12.1" + "@babel/plugin-transform-member-expression-literals" "^7.12.1" + "@babel/plugin-transform-modules-amd" "^7.12.1" + "@babel/plugin-transform-modules-commonjs" "^7.12.1" + "@babel/plugin-transform-modules-systemjs" "^7.12.1" + "@babel/plugin-transform-modules-umd" "^7.12.1" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.12.1" + "@babel/plugin-transform-new-target" "^7.12.1" + "@babel/plugin-transform-object-super" "^7.12.1" + "@babel/plugin-transform-parameters" "^7.12.1" + "@babel/plugin-transform-property-literals" "^7.12.1" + "@babel/plugin-transform-regenerator" "^7.12.1" + "@babel/plugin-transform-reserved-words" "^7.12.1" + "@babel/plugin-transform-shorthand-properties" "^7.12.1" + "@babel/plugin-transform-spread" "^7.12.1" + "@babel/plugin-transform-sticky-regex" "^7.12.7" + "@babel/plugin-transform-template-literals" "^7.12.1" + "@babel/plugin-transform-typeof-symbol" "^7.12.10" + "@babel/plugin-transform-unicode-escapes" "^7.12.1" + "@babel/plugin-transform-unicode-regex" "^7.12.1" + "@babel/preset-modules" "^0.1.3" + "@babel/types" "^7.12.11" + core-js-compat "^3.8.0" + semver "^5.5.0" + +"@babel/preset-modules@^0.1.3": + version "0.1.4" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" + "@babel/plugin-transform-dotall-regex" "^7.4.4" + "@babel/types" "^7.4.4" + esutils "^2.0.2" + +"@babel/preset-react@^7.10.4": + version "7.12.10" + resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + "@babel/plugin-transform-react-display-name" "^7.12.1" + "@babel/plugin-transform-react-jsx" "^7.12.10" + "@babel/plugin-transform-react-jsx-development" "^7.12.7" + "@babel/plugin-transform-react-pure-annotations" "^7.12.1" + +"@babel/runtime@^7.8.4": + version "7.12.5" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.10.4", "@babel/template@^7.12.7": + version "7.12.7" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== + dependencies: + "@babel/code-frame" "^7.12.11" + "@babel/generator" "^7.12.11" + "@babel/helper-function-name" "^7.12.11" + "@babel/helper-split-export-declaration" "^7.12.11" + "@babel/parser" "^7.12.11" + "@babel/types" "^7.12.12" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": + version "7.12.12" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@discoveryjs/json-ext@^0.5.0": + version "0.5.7" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== + +"@emotion/is-prop-valid@^0.8.2": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== + dependencies: + "@emotion/memoize" "0.7.4" + +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + +"@floating-ui/core@^1.0.0": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a" + integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg== + dependencies: + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/dom@^1.0.0": + version "1.6.5" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" + integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== + dependencies: + "@floating-ui/core" "^1.0.0" + "@floating-ui/utils" "^0.2.0" + +"@floating-ui/react-dom@^2.0.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.0.tgz#4f0e5e9920137874b2405f7d6c862873baf4beff" + integrity sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.0": + version "0.2.2" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" + integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== + +"@graphiql/react@0.22.3", "@graphiql/react@^0.22.3": + version "0.22.3" + resolved "https://registry.yarnpkg.com/@graphiql/react/-/react-0.22.3.tgz#aa0cd4260ad8e98dc00e0fc9c54cb1b3e227d980" + integrity sha512-rZGs0BbJ4ImFy6l489aXUEB3HzGVoD7hI8CycydNRXR6+qYgp/fuNFCXMJe+q9gDyC/XhBXni8Pdugk8HxJ05g== + dependencies: + "@graphiql/toolkit" "^0.9.1" + "@headlessui/react" "^1.7.15" + "@radix-ui/react-dialog" "^1.0.4" + "@radix-ui/react-dropdown-menu" "^2.0.5" + "@radix-ui/react-tooltip" "^1.0.6" + "@radix-ui/react-visually-hidden" "^1.0.3" + "@types/codemirror" "^5.60.8" + clsx "^1.2.1" + codemirror "^5.65.3" + codemirror-graphql "^2.0.12" + copy-to-clipboard "^3.2.0" + framer-motion "^6.5.1" + graphql-language-service "^5.2.1" + markdown-it "^14.1.0" + set-value "^4.1.0" + +"@graphiql/toolkit@^0.9.1": + version "0.9.1" + resolved "https://registry.yarnpkg.com/@graphiql/toolkit/-/toolkit-0.9.1.tgz#44bfa83aed79c8c18affac49efbb81f8e87bade3" + integrity sha512-LVt9pdk0830so50ZnU2Znb2rclcoWznG8r8asqAENzV0U1FM1kuY0sdPpc/rBc9MmmNgnB6A+WZzDhq6dbhTHA== + dependencies: + "@n1ru4l/push-pull-async-iterable-iterator" "^3.1.0" + meros "^1.1.4" + +"@headlessui/react@^1.7.15": + version "1.7.19" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40" + integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw== + dependencies: + "@tanstack/react-virtual" "^3.0.0-beta.60" + client-only "^0.0.1" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.20": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@motionone/animation@^10.12.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.18.0.tgz#868d00b447191816d5d5cf24b1cafa144017922b" + integrity sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw== + dependencies: + "@motionone/easing" "^10.18.0" + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/dom@10.12.0": + version "10.12.0" + resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.12.0.tgz#ae30827fd53219efca4e1150a5ff2165c28351ed" + integrity sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw== + dependencies: + "@motionone/animation" "^10.12.0" + "@motionone/generators" "^10.12.0" + "@motionone/types" "^10.12.0" + "@motionone/utils" "^10.12.0" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@motionone/easing@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.18.0.tgz#7b82f6010dfee3a1bb0ee83abfbaff6edae0c708" + integrity sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg== + dependencies: + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/generators@^10.12.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.18.0.tgz#fe09ab5cfa0fb9a8884097feb7eb60abeb600762" + integrity sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg== + dependencies: + "@motionone/types" "^10.17.1" + "@motionone/utils" "^10.18.0" + tslib "^2.3.1" + +"@motionone/types@^10.12.0", "@motionone/types@^10.17.1": + version "10.17.1" + resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.17.1.tgz#cf487badbbdc9da0c2cb86ffc1e5d11147c6e6fb" + integrity sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A== + +"@motionone/utils@^10.12.0", "@motionone/utils@^10.18.0": + version "10.18.0" + resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.18.0.tgz#a59ff8932ed9009624bca07c56b28ef2bb2f885e" + integrity sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw== + dependencies: + "@motionone/types" "^10.17.1" + hey-listen "^1.0.8" + tslib "^2.3.1" + +"@n1ru4l/push-pull-async-iterable-iterator@^3.1.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz#c15791112db68dd9315d329d652b7e797f737655" + integrity sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q== + +"@radix-ui/primitive@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== + +"@radix-ui/react-arrow@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a" + integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/react-collection@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" + integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + +"@radix-ui/react-context@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== + +"@radix-ui/react-dialog@^1.0.4": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.0.tgz#9d354a8c7f534d49fffd2544fb7b371cb49da71c" + integrity sha512-oiSJcsjbdC8JqbXrOuhOd7oaEaPp3x2L2zn6V7ie6SSpEjrAha/WabDX4po6laGwbhAu9DT0XxHL0DmcIXrR0A== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-portal" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== + +"@radix-ui/react-dismissable-layer@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz#2cd0a49a732372513733754e6032d3fb7988834e" + integrity sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" + +"@radix-ui/react-dropdown-menu@^2.0.5": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.0.tgz#9e4693f3b300cd54e553a486ddd7a5df355b78ba" + integrity sha512-8fAz27yxVaYTkXMm5dVOcKCHOiio9b4nl7rO1HmK8rpzcEl0kSSmwFQsYDyJxB/Em48PvXTez/iaBj3VEd2N4g== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-menu" "2.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-focus-guards@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13" + integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw== + +"@radix-ui/react-focus-scope@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz#ebe2891a298e0a33ad34daab2aad8dea31caf0b2" + integrity sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-menu@2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.0.tgz#383d078f3e3708f4134e2d61a66c39b40c41c99c" + integrity sha512-0AxIUQJpimipHDgTVISZbdOY+wZzgICKAsqfI1rF2Hp0Jh3YSv9e9J1tYYyurPBONe5vKi3hZPtVt2E85Sac7A== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-roving-focus" "1.1.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.7" + +"@radix-ui/react-popper@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a" + integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-portal@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.0.tgz#7d8591034d85478c172a91b1b879df8cf8b60bf0" + integrity sha512-0tXZ5O6qAVvuN9SWP0X+zadHf9hzHiMf/vxOU+kXO+fbtS8lS57MXa6EmikDxk9s/Bmkk80+dcxgbvisIyeqxg== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/react-presence@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-primitive@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== + dependencies: + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-roving-focus@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" + integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + +"@radix-ui/react-slot@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + +"@radix-ui/react-tooltip@^1.0.6": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.0.tgz#861c268b9c73472a32a312dbc0135ea581262ca6" + integrity sha512-DZZvEn5WUJyd9+JzVT/cTjt7m0rymjxpzJZMmb09lCWo8kRqOp4rsckFrGgocD5cR8e3gtaNINvWWqFMccvV/w== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.0" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" + +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== + dependencies: + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/react-visually-hidden@1.1.0", "@radix-ui/react-visually-hidden@^1.0.3": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2" + integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ== + dependencies: + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== + +"@tanstack/react-virtual@^3.0.0-beta.60": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.5.1.tgz#1ce466f530a10f781871360ed2bf7ff83e664f85" + integrity sha512-jIsuhfgy8GqA67PdWqg73ZB2LFE+HD9hjWL1L6ifEIZVyZVAKpYmgUG4WsKQ005aEyImJmbuimPiEvc57IY0Aw== + dependencies: + "@tanstack/virtual-core" "3.5.1" + +"@tanstack/virtual-core@3.5.1": + version "3.5.1" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.5.1.tgz#f519149bce9156d0e7954b9531df15f446f2fc12" + integrity sha512-046+AUSiDru/V9pajE1du8WayvBKeCvJ2NmKPy/mR8/SbKKrqmSbj7LJBfXE+nSq4f5TBXvnCzu0kcYebI9WdQ== + +"@types/codemirror@^0.0.90": + version "0.0.90" + resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.90.tgz#9c5edafce2a780b4f8bc5e3b699fe1f4727c8f17" + integrity sha512-8Z9+tSg27NPRGubbUPUCrt5DDG/OWzLph5BvcDykwR5D7RyZh5mhHG0uS1ePKV1YFCA+/cwc4Ey2AJAEFfV3IA== + dependencies: + "@types/tern" "*" + +"@types/codemirror@^5.60.8": + version "5.60.15" + resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.15.tgz#0f82be6f4126d1e59cf4c4830e56dcd49d3c3e8a" + integrity sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA== + dependencies: + "@types/tern" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.7" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== + dependencies: + "@types/eslint" "*" + "@types/estree" "*" + +"@types/eslint@*": + version "8.56.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" + integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + +"@types/estree@*", "@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== + +"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": + version "7.0.7" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== + +"@types/node@*": + version "20.14.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.6.tgz#f3c19ffc98c2220e18de259bb172dd4d892a6075" + integrity sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw== + dependencies: + undici-types "~5.26.4" + +"@types/tern@*": + version "0.23.9" + resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.9.tgz#6f6093a4a9af3e6bb8dde528e024924d196b367c" + integrity sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw== + dependencies: + "@types/estree" "*" + +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== + dependencies: + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== + +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== + +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== + +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== + dependencies: + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== + +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" + +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@xtuc/long" "4.2.2" + +"@webpack-cli/configtest@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== + +"@webpack-cli/info@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== + +"@webpack-cli/serve@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + +acorn@^8.7.1: + version "8.12.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" + integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== + +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + +ajv-keywords@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + +ajv@^6.12.4, ajv@^6.12.5: + version "6.12.6" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.0, ajv@^8.9.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== + dependencies: + fast-deep-equal "^3.1.3" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.4.1" + +ansi-regex@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" + integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +aria-hidden@^1.1.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" + integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== + dependencies: + tslib "^2.0.0" + +babel-loader@^8.1.0: + version "8.2.2" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" + integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== + dependencies: + find-cache-dir "^3.3.1" + loader-utils "^1.4.0" + make-dir "^3.1.0" + schema-utils "^2.6.5" + +babel-plugin-dynamic-import-node@^2.3.3: + version "2.3.3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== + dependencies: + object.assign "^4.1.0" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +browserslist@^4.14.5, browserslist@^4.16.1: + version "4.16.3" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== + dependencies: + caniuse-lite "^1.0.30001181" + colorette "^1.2.1" + electron-to-chromium "^1.3.649" + escalade "^3.1.1" + node-releases "^1.1.70" + +browserslist@^4.21.10: + version "4.23.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== + dependencies: + caniuse-lite "^1.0.30001629" + electron-to-chromium "^1.4.796" + node-releases "^2.0.14" + update-browserslist-db "^1.0.16" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-lite@^1.0.30001181: + version "1.0.30001183" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz#7a57ba9d6584119bb5f2bc76d3cc47ba9356b3e2" + integrity sha512-7JkwTEE1hlRKETbCFd8HDZeLiQIUcl8rC6JgNjvHCNaxOeNmQ9V4LvQXRUsKIV2CC73qKxljwVhToaA3kLRqTw== + +caniuse-lite@^1.0.30001629: + version "1.0.30001636" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz#b15f52d2bdb95fad32c2f53c0b68032b85188a78" + integrity sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg== + +chalk@^2.0.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + +codemirror-graphql@^2.0.12: + version "2.0.12" + resolved "https://registry.yarnpkg.com/codemirror-graphql/-/codemirror-graphql-2.0.12.tgz#75492b41f271a64eb207c923a4a536c3134d05c9" + integrity sha512-5UCqhWzck1jClCmRewFb8aSiabnAqiaRfsvIPfmbf6WJvOb8oiefJeHilclPPiZBzY8v/Et6EBMtOeKnWCoyng== + dependencies: + "@types/codemirror" "^0.0.90" + graphql-language-service "5.2.1" + +codemirror@^5.65.3: + version "5.65.16" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.16.tgz#efc0661be6bf4988a6a1c2fe6893294638cdb334" + integrity sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +colorette@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + +colorette@^2.0.14: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +commander@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== + +commander@^2.20.0: + version "2.20.3" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +copy-anything@^2.0.1: + version "2.0.6" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480" + integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw== + dependencies: + is-what "^3.14.1" + +copy-to-clipboard@^3.2.0: + version "3.3.1" + resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" + integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== + dependencies: + toggle-selection "^1.0.6" + +core-js-compat@^3.8.0: + version "3.8.3" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== + dependencies: + browserslist "^4.16.1" + semver "7.0.0" + +cosmiconfig@^8.3.5: + version "8.3.6" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== + dependencies: + import-fresh "^3.3.0" + js-yaml "^4.1.0" + parse-json "^5.2.0" + path-type "^4.0.0" + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-loader@^3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.32" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.2.0" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.1.0" + schema-utils "^2.7.0" + semver "^6.3.0" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +debug@^4.1.0: + version "4.3.1" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + +electron-to-chromium@^1.3.649: + version "1.3.650" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.650.tgz#24e821fff2ed61fd71fee092f2a0631b3c0c22a6" + integrity sha512-j6pRuNylFBbroG6NB8Lw/Im9oDY74s2zWHBP5TmdYg73cBuL6cz//SMgolVa0gIJk/DSL+kO7baJ1DSXW1FUZg== + +electron-to-chromium@^1.4.796: + version "1.4.807" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.807.tgz#4d6c5ea1516f0164ac5bfd487ccd4ee9507c8f01" + integrity sha512-kSmJl2ZwhNf/bcIuCH/imtNOKlpkLDn2jqT5FJ+/0CXjhnFaOa9cOe9gHKKy71eM49izwuQjZhKk+lWQ1JxB7A== + +emojis-list@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== + +enhanced-resolve@^5.17.0: + version "5.17.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" + integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + +envinfo@^7.7.3: + version "7.13.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + +errno@^0.1.1: + version "0.1.8" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== + dependencies: + prr "~1.0.1" + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-module-lexer@^1.2.1: + version "1.5.3" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz#25969419de9c0b1fbe54279789023e8a9a788412" + integrity sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escalade@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-scope@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +events@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastest-levenshtein@^1.0.12: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + +file-loader@^6.0.0: + version "6.2.0" + resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== + dependencies: + loader-utils "^2.0.0" + schema-utils "^3.0.0" + +find-cache-dir@^3.3.1: + version "3.3.1" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +framer-motion@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7" + integrity sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw== + dependencies: + "@motionone/dom" "10.12.0" + framesync "6.0.1" + hey-listen "^1.0.8" + popmotion "11.0.3" + style-value-types "5.0.0" + tslib "^2.1.0" + optionalDependencies: + "@emotion/is-prop-valid" "^0.8.2" + +framesync@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" + integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== + dependencies: + tslib "^2.1.0" + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.2" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-intrinsic@^1.0.2: + version "1.1.0" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz#892e62931e6938c8a23ea5aaebcfb67bd97da97e" + integrity sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + +glob-to-regexp@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +graceful-fs@^4.1.2: + version "4.2.4" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== + +graceful-fs@^4.2.11, graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphiql@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/graphiql/-/graphiql-3.3.1.tgz#60fc405c56492792c60d107c1f191aa6cf244034" + integrity sha512-UA29FQ418Pcxat54CvM//S5G+7DKG7XQ7s9UyAEdb7zMAKPANIDd222XEYNxG2I/FgAxsiq3ZTBpxwvPbB9Mcw== + dependencies: + "@graphiql/react" "^0.22.3" + "@graphiql/toolkit" "^0.9.1" + graphql-language-service "^5.2.1" + markdown-it "^14.1.0" + +graphql-language-service@5.2.1, graphql-language-service@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/graphql-language-service/-/graphql-language-service-5.2.1.tgz#8929cf93deadecc0fbb78fe8a0c55d178ffa7833" + integrity sha512-8ewD6otGO43vg2TiEGjoLz3CweTwfaf4ZnqfNREqZXS2JSJGXtsRBOMMknCxMfFVh4x14ql3jyDrXcyAAtbmkQ== + dependencies: + nullthrows "^1.0.0" + vscode-languageserver-types "^3.17.1" + +graphql-ws@^5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.16.0.tgz#849efe02f384b4332109329be01d74c345842729" + integrity sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A== + +graphql@^16.8.2: + version "16.8.2" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.2.tgz#54771c7ff195da913f5e70af8044a026d32eca2a" + integrity sha512-cvVIBILwuoSyD54U4cF/UXDh5yAobhNV/tPygI4lZhgOIJQE/WLWC4waBRb4I6bDVYb3OVx3lfHbaQOEoUD5sg== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + +hey-listen@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== + +iconv-lite@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + +image-size@~0.5.0: + version "0.5.5" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ== + +import-fresh@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +interpret@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== + +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-primitive@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-3.0.1.tgz#98c4db1abff185485a657fc2905052b940524d05" + integrity sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w== + +is-what@^3.14.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" + integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jiti@^1.20.0: + version "1.21.6" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +less-loader@^11.1.3: + version "11.1.4" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.4.tgz#e8a070844efaefbe59b978acaf57b9d3e868cf08" + integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A== + +less@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/less/-/less-4.2.0.tgz#cbefbfaa14a4cd388e2099b2b51f956e1465c450" + integrity sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA== + dependencies: + copy-anything "^2.0.1" + parse-node-version "^1.0.1" + tslib "^2.3.0" + optionalDependencies: + errno "^0.1.1" + graceful-fs "^4.1.2" + image-size "~0.5.0" + make-dir "^2.1.0" + mime "^1.4.1" + needle "^3.1.0" + source-map "~0.6.0" + +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +linkify-it@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== + dependencies: + uc.micro "^2.0.0" + +loader-runner@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== + +loader-utils@^1.2.3, loader-utils@^1.4.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^1.0.1" + +loader-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== + dependencies: + big.js "^5.2.2" + emojis-list "^3.0.0" + json5 "^2.1.2" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +loose-envify@^1.0.0, loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.2, make-dir@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +markdown-it@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" + integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== + dependencies: + argparse "^2.0.1" + entities "^4.4.0" + linkify-it "^5.0.0" + mdurl "^2.0.0" + punycode.js "^2.3.1" + uc.micro "^2.1.0" + +mdurl@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +meros@^1.1.4: + version "1.3.0" + resolved "https://registry.yarnpkg.com/meros/-/meros-1.3.0.tgz#c617d2092739d55286bf618129280f362e6242f2" + integrity sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.27: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@^1.4.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mini-css-extract-plugin@^2.7.6: + version "2.9.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" + integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== + dependencies: + schema-utils "^4.0.0" + tapable "^2.2.1" + +minimist@1.2.6, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + +needle@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-3.3.1.tgz#63f75aec580c2e77e209f3f324e2cdf3d29bd049" + integrity sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q== + dependencies: + iconv-lite "^0.6.3" + sax "^1.2.4" + +neo-async@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + +node-releases@^1.1.70: + version "1.1.70" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" + integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +nullthrows@^1.0.0: + version "1.1.1" + resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.0: + version "4.1.2" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse-node-version@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== + +picocolors@^1.0.0, picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pkg-dir@^4.1.0, pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +popmotion@11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" + integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== + dependencies: + framesync "6.0.1" + hey-listen "^1.0.8" + style-value-types "5.0.0" + tslib "^2.1.0" + +postcss-loader@^7.3.3: + version "7.3.4" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" + integrity sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A== + dependencies: + cosmiconfig "^8.3.5" + jiti "^1.20.0" + semver "^7.5.4" + +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + +postcss-modules-local-by-default@^3.0.2: + version "3.0.3" + resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.32" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.1.0" + +postcss-modules-scope@^2.2.0: + version "2.2.0" + resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: + version "6.0.4" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== + +postcss@7.0.39, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309" + integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA== + dependencies: + picocolors "^0.2.1" + source-map "^0.6.1" + +postcss@^8.4.28: + version "8.4.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.2.0" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +punycode.js@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +react-dom@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== + dependencies: + loose-envify "^1.1.0" + scheduler "^0.23.2" + +react-remove-scroll-bar@^2.3.4: + version "2.3.6" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" + integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== + dependencies: + react-style-singleton "^2.2.1" + tslib "^2.0.0" + +react-remove-scroll@2.5.7: + version "2.5.7" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" + integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== + dependencies: + react-remove-scroll-bar "^2.3.4" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + +react-style-singleton@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" + integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== + dependencies: + get-nonce "^1.0.0" + invariant "^2.2.4" + tslib "^2.0.0" + +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== + dependencies: + loose-envify "^1.1.0" + +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + +regenerate-unicode-properties@^8.2.0: + version "8.2.0" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.2" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== + +regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + +regenerator-transform@^0.14.2: + version "0.14.5" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== + dependencies: + "@babel/runtime" "^7.8.4" + +regexpu-core@^4.7.1: + version "4.7.1" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.2.0" + regjsgen "^0.5.1" + regjsparser "^0.6.4" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.2.0" + +regjsgen@^0.5.1: + version "0.5.2" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== + +regjsparser@^0.6.4: + version "0.6.7" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz#c00164e1e6713c2e3ee641f1701c4b7aa0a7f86c" + integrity sha512-ib77G0uxsA2ovgiYbCVGx4Pv3PSttAx2vIwidqQzbL2U5S4Q+j00HdSAneSBuyVcMvEnTXMjiGgB+DlXozVhpQ== + dependencies: + jsesc "~0.5.0" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"safer-buffer@>= 2.1.2 < 3.0.0": + version "2.1.2" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== + +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== + dependencies: + loose-envify "^1.1.0" + +schema-utils@^2.6.5, schema-utils@^2.7.0: + version "2.7.1" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + +schema-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== + dependencies: + "@types/json-schema" "^7.0.6" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^3.1.1, schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + +schema-utils@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.9.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.1.0" + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.5.4: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-value@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.1.0.tgz#aa433662d87081b75ad88a4743bd450f044e7d09" + integrity sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw== + dependencies: + is-plain-object "^2.0.4" + is-primitive "^3.0.1" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +source-map-js@^1.0.2, source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + +source-map-loader@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.2.tgz#1b378721b65adb21e874928a9fb22e8a340d06a5" + integrity sha512-oYwAqCuL0OZhBoSgmdrLa7mv9MjommVMiQIWgcztf+eS4+8BfcUee6nenFnDhKOhzAVnk5gpZdfnz1iiBv+5sg== + dependencies: + iconv-lite "^0.6.3" + source-map-js "^1.0.2" + +source-map-support@~0.5.12: + version "0.5.19" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +style-loader@^1.2.1: + version "1.3.0" + resolved "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" + integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== + dependencies: + loader-utils "^2.0.0" + schema-utils "^2.7.0" + +style-value-types@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" + integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== + dependencies: + hey-listen "^1.0.8" + tslib "^2.1.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== + dependencies: + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" + schema-utils "^3.1.1" + serialize-javascript "^6.0.1" + terser "^5.26.0" + +terser@4.8.1, terser@^5.26.0: + version "4.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f" + integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +toggle-selection@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= + +tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== + +uc.micro@^2.0.0, uc.micro@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.1.0" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +update-browserslist-db@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" + integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + +uri-js@^4.2.2, uri-js@^4.4.1: + version "4.4.1" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +use-callback-ref@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" + integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== + dependencies: + tslib "^2.0.0" + +use-sidecar@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" + integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +util-deprecate@^1.0.2: + version "1.0.2" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +vscode-languageserver-types@^3.17.1: + version "3.17.5" + resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== + +watchpack@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== + dependencies: + glob-to-regexp "^0.4.1" + graceful-fs "^4.1.2" + +webpack-cli@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== + dependencies: + "@discoveryjs/json-ext" "^0.5.0" + "@webpack-cli/configtest" "^2.1.1" + "@webpack-cli/info" "^2.0.2" + "@webpack-cli/serve" "^2.0.5" + colorette "^2.0.14" + commander "^10.0.1" + cross-spawn "^7.0.3" + envinfo "^7.7.3" + fastest-levenshtein "^1.0.12" + import-local "^3.0.2" + interpret "^3.1.1" + rechoir "^0.8.0" + webpack-merge "^5.7.3" + +webpack-merge@^5.7.3: + version "5.10.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== + dependencies: + clone-deep "^4.0.1" + flat "^5.0.2" + wildcard "^2.0.0" + +webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== + +webpack@^5.88.2: + version "5.92.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.92.1.tgz#eca5c1725b9e189cffbd86e8b6c3c7400efc5788" + integrity sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA== + dependencies: + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" + acorn "^8.7.1" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" + chrome-trace-event "^1.0.2" + enhanced-resolve "^5.17.0" + es-module-lexer "^1.2.1" + eslint-scope "5.1.1" + 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.2.0" + mime-types "^2.1.27" + neo-async "^2.6.2" + schema-utils "^3.2.0" + tapable "^2.1.1" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" + webpack-sources "^3.2.3" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== diff --git a/graphql/karaf-feature/pom.xml b/graphql/karaf-feature/pom.xml index 1e4b40abc..d18139e9b 100644 --- a/graphql/karaf-feature/pom.xml +++ b/graphql/karaf-feature/pom.xml @@ -19,7 +19,7 @@ org.apache.unomi unomi-graphql - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 kar diff --git a/graphql/karaf-feature/src/main/feature/feature.xml b/graphql/karaf-feature/src/main/feature/feature.xml index 31f339590..19203e810 100644 --- a/graphql/karaf-feature/src/main/feature/feature.xml +++ b/graphql/karaf-feature/src/main/feature/feature.xml @@ -50,6 +50,6 @@ mvn:org.eclipse.jetty/jetty-server/${jetty.websocket.version} mvn:org.eclipse.jetty/jetty-http/${jetty.websocket.version} mvn:org.apache.unomi/cdp-graphql-api-impl/${project.version} - mvn:org.apache.unomi/unomi-graphql-playground/${project.version} + mvn:org.apache.unomi/unomi-graphql-ui/${project.version} diff --git a/graphql/pom.xml b/graphql/pom.xml index 2be6d5386..f0d3d8f75 100644 --- a/graphql/pom.xml +++ b/graphql/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-graphql @@ -42,7 +42,7 @@ cxs-impl - graphql-playground + graphql-ui karaf-feature diff --git a/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java b/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java index c3ed5c0d8..2ef00efa8 100644 --- a/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java @@ -110,15 +110,7 @@ public void testHealthCheck() { LOGGER.info("health check response: {}", response); Assert.assertEquals(5, response.size()); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("karaf") && r.getStatus() == HealthCheckResponse.Status.LIVE)); - Assert.assertTrue(response.stream().anyMatch(r -> { - if (r.getName().equals("elasticsearch") && r.getStatus() == HealthCheckResponse.Status.LIVE) { - Map data = r.getData(); - String clusterName = (String) data.get("clusterName"); - String expectedClusterName = isOpenSearch() ? "docker-cluster" : "contextElasticSearchITests"; - return clusterName != null && clusterName.equals(expectedClusterName); - } - return false; - })); + Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("elasticsearch") && r.getStatus() == HealthCheckResponse.Status.LIVE)); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("unomi") && r.getStatus() == HealthCheckResponse.Status.LIVE)); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("cluster") && r.getStatus() == HealthCheckResponse.Status.LIVE)); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("persistence") && r.getStatus() == HealthCheckResponse.Status.LIVE)); diff --git a/kar/pom.xml b/kar/pom.xml index aa71063f9..fe83d6744 100644 --- a/kar/pom.xml +++ b/kar/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-kar diff --git a/lifecycle-watcher/pom.xml b/lifecycle-watcher/pom.xml index 4ce9d452f..444db2f3a 100644 --- a/lifecycle-watcher/pom.xml +++ b/lifecycle-watcher/pom.xml @@ -20,7 +20,7 @@ unomi-root org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java index 6bff1e8dc..d64f3ac31 100644 --- a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java +++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java @@ -272,7 +272,7 @@ private void prepareGraphQLFeatureToInstall() { if (Boolean.parseBoolean(bundleContext.getProperty("org.apache.unomi.graphql.feature.activated"))) { featuresToInstall.add(CDP_GRAPHQL_FEATURE); requiredBundlesFromFeatures.put("org.apache.unomi.cdp-graphql-api-impl", false); - requiredBundlesFromFeatures.put("org.apache.unomi.graphql-playground", false); + requiredBundlesFromFeatures.put("org.apache.unomi.graphql-ui", false); } } diff --git a/manual/pom.xml b/manual/pom.xml index 7326fbd5a..55467ebe7 100644 --- a/manual/pom.xml +++ b/manual/pom.xml @@ -20,7 +20,7 @@ unomi-root org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/manual/src/main/asciidoc/graphql.adoc b/manual/src/main/asciidoc/graphql.adoc index ed3ec9af6..55bffebdb 100644 --- a/manual/src/main/asciidoc/graphql.adoc +++ b/manual/src/main/asciidoc/graphql.adoc @@ -13,10 +13,10 @@ // === Introduction -First introduced in Apache Unomi 2.0, a GraphQL API is available as an alternative to REST for interacting with the platform. +First introduced in Apache Unomi 2.0, a GraphQL API is available as an alternative to REST for interacting with the platform. Disabled by default, the GraphQL API is currently considered a beta feature. -We look forward for this new GraphQL API to be used, feel free to open discussion on +We look forward for this new GraphQL API to be used, feel free to open discussion on https://the-asf.slack.com/messages/CBP2Z98Q7/[Unomi Slack channel] or https://issues.apache.org/jira/projects/UNOMI/issues[create tickets on Jira] === Enabling the API @@ -32,18 +32,18 @@ The GraphQL API must be enabled using a system property (or environment variable org.apache.unomi.graphql.feature.activated=${env:UNOMI_GRAPHQL_FEATURE_ACTIVATED:-false} ---- -You can either modify the `org.apache.unomi.graphql.feature.activated` property or specify the `UNOMI_GRAPHQL_FEATURE_ACTIVATED` +You can either modify the `org.apache.unomi.graphql.feature.activated` property or specify the `UNOMI_GRAPHQL_FEATURE_ACTIVATED` environment variable (if using Docker for example). === Endpoints Two endpoints were introduced for Apache Unomi 2 GraphQL API: * `/graphql` is the primary endpoint for interacting programatically with the API and aims at receiving POST requests. -* `/graphql-ui` provides access to the GraphQL Playground UI and aims at being accessed by a Web Browser. +* `/graphql-ui` provides access to the GraphQL UI and aims at being accessed by a Web Browser. === GraphQL Schema -Thanks to GraphQL introspection, there is no dedicated documentation per-se as the Schema itself serves as documentation. +Thanks to GraphQL introspection, there is no dedicated documentation per-se as the Schema itself serves as documentation. -You can easily view the schema by navigrating to `/graphql-ui`, depending on your setup (localhost, public host, ...), -you might need to adjust the URL to point GraphQL Playground to the `/graphql` endpoint. +You can easily view the schema by navigrating to `/graphql-ui`, depending on your setup (localhost, public host, ...), +you might need to adjust the URL to point GraphQL UI to the `/graphql` endpoint. diff --git a/metrics/pom.xml b/metrics/pom.xml index dd55cc91b..dd9dca0f5 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-metrics diff --git a/package/pom.xml b/package/pom.xml index 0a5b1ac02..2a97c02ab 100644 --- a/package/pom.xml +++ b/package/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi @@ -345,7 +345,7 @@ - mvn:org.apache.unomi/log4j-extension/2.6.0-SNAPSHOT + mvn:org.apache.unomi/log4j-extension/${project.version} wrapper diff --git a/package/src/main/resources/etc/custom.system.properties b/package/src/main/resources/etc/custom.system.properties index 50a5e1014..04b3234a5 100644 --- a/package/src/main/resources/etc/custom.system.properties +++ b/package/src/main/resources/etc/custom.system.properties @@ -264,9 +264,9 @@ org.apache.unomi.segment.update.batchSize=${env:UNOMI_SEGMENT_UPDATE_BATCHSIZE:- # Run Batch request separately for updating segments in profiles org.apache.unomi.segment.batch.update=${env:UNOMI_SEGMENT_BATCH_PROFILE_UPDATE:-false} # Send Profile Updated Event for every profile segment update -org.apache.unomi.segment.send.profile.update.event=${env: UNOMI_SEGMENT_SEND_PROFILE_UPDATE_EVENT:-true} +org.apache.unomi.segment.send.profile.update.event=${env:UNOMI_SEGMENT_SEND_PROFILE_UPDATE_EVENT:-true} # Daily hour once a day to recalculate segment with dateExpr condition -org.apache.unomi.segment.daily.dateexpr.evaluation.hourutc=${env: UNOMI_SEGMENT_DAILY_DATEEXPR_EVALUATION_HOUR_UTC:-5} +org.apache.unomi.segment.daily.dateexpr.evaluation.hourutc=${env:UNOMI_SEGMENT_DAILY_DATEEXPR_EVALUATION_HOUR_UTC:-5} # When performing segment updates, can retry an update in case of an error to a single profile org.apache.unomi.services.segment.max.retries.update.profile.segment=${env:UNOMI_SEGMENT_UPDATE_MAX_RETRIES:-0} # When performing retry of segment update after a request was failed, delay of requests diff --git a/persistence-elasticsearch/core/pom.xml b/persistence-elasticsearch/core/pom.xml index 0c1470bf0..ee5afc77f 100644 --- a/persistence-elasticsearch/core/pom.xml +++ b/persistence-elasticsearch/core/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-persistence-elasticsearch - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-persistence-elasticsearch-core diff --git a/persistence-elasticsearch/pom.xml b/persistence-elasticsearch/pom.xml index 17931fc55..01aa88967 100644 --- a/persistence-elasticsearch/pom.xml +++ b/persistence-elasticsearch/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-persistence-elasticsearch diff --git a/plugins/baseplugin/pom.xml b/plugins/baseplugin/pom.xml index cd78499d6..e072e1887 100644 --- a/plugins/baseplugin/pom.xml +++ b/plugins/baseplugin/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-base diff --git a/plugins/hover-event/pom.xml b/plugins/hover-event/pom.xml index bebfb41c0..15bbe3fea 100644 --- a/plugins/hover-event/pom.xml +++ b/plugins/hover-event/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-hover-event diff --git a/plugins/kafka-injector/pom.xml b/plugins/kafka-injector/pom.xml index 634154ec5..59660ab60 100644 --- a/plugins/kafka-injector/pom.xml +++ b/plugins/kafka-injector/pom.xml @@ -20,7 +20,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT kafka-extension diff --git a/plugins/mail/pom.xml b/plugins/mail/pom.xml index 99d0ddc2f..40c931225 100644 --- a/plugins/mail/pom.xml +++ b/plugins/mail/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-mail diff --git a/plugins/optimization-test/pom.xml b/plugins/optimization-test/pom.xml index bbcfb8a32..e5def900e 100644 --- a/plugins/optimization-test/pom.xml +++ b/plugins/optimization-test/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-optimization-test diff --git a/plugins/past-event/pom.xml b/plugins/past-event/pom.xml index 88fe646e6..c22a797b4 100644 --- a/plugins/past-event/pom.xml +++ b/plugins/past-event/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-past-event diff --git a/plugins/pom.xml b/plugins/pom.xml index 1a3384e44..c810f306e 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins diff --git a/plugins/request/pom.xml b/plugins/request/pom.xml index 41310e16b..0e1ed3874 100644 --- a/plugins/request/pom.xml +++ b/plugins/request/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-request diff --git a/plugins/tracked-event/pom.xml b/plugins/tracked-event/pom.xml index e0af82019..fb9279d18 100644 --- a/plugins/tracked-event/pom.xml +++ b/plugins/tracked-event/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-plugins - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-plugins-tracked-event diff --git a/pom.xml b/pom.xml index 16bb07a41..1afd5dd23 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ event tracking server. https://unomi.apache.org - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT pom @@ -511,6 +511,7 @@ **/keystore **/*.css + **/*.less **/*.ssp **/*.conf **/*.min.js diff --git a/rest/pom.xml b/rest/pom.xml index 6fa17166d..54d7ff574 100644 --- a/rest/pom.xml +++ b/rest/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-rest diff --git a/samples/graphql-providers-feature/pom.xml b/samples/graphql-providers-feature/pom.xml index 411e1ac87..7a6475aaf 100644 --- a/samples/graphql-providers-feature/pom.xml +++ b/samples/graphql-providers-feature/pom.xml @@ -20,7 +20,7 @@ samples org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT graphql-providers-sample-feature diff --git a/samples/graphql-providers/pom.xml b/samples/graphql-providers/pom.xml index 15f592b26..0d9fc89b2 100644 --- a/samples/graphql-providers/pom.xml +++ b/samples/graphql-providers/pom.xml @@ -20,7 +20,7 @@ samples org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT graphql-providers-sample diff --git a/samples/groovy-actions/pom.xml b/samples/groovy-actions/pom.xml index 588810800..c9f07a5d1 100644 --- a/samples/groovy-actions/pom.xml +++ b/samples/groovy-actions/pom.xml @@ -21,7 +21,7 @@ samples org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT test-groovy-action-sample diff --git a/samples/login-integration/pom.xml b/samples/login-integration/pom.xml index b04f60d97..5dde3922d 100644 --- a/samples/login-integration/pom.xml +++ b/samples/login-integration/pom.xml @@ -21,7 +21,7 @@ samples org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT login-integration-sample diff --git a/samples/pom.xml b/samples/pom.xml index e2d2a2e41..2ae966fd2 100644 --- a/samples/pom.xml +++ b/samples/pom.xml @@ -19,7 +19,7 @@ unomi-root org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT 4.0.0 diff --git a/samples/trainingplugin/pom.xml b/samples/trainingplugin/pom.xml index a865201ab..8b648f1e2 100644 --- a/samples/trainingplugin/pom.xml +++ b/samples/trainingplugin/pom.xml @@ -19,7 +19,7 @@ samples org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT training-plugin Apache Unomi :: Samples :: Training plugin @@ -31,7 +31,7 @@ org.apache.unomi unomi-api - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT provided diff --git a/samples/tweet-button-plugin/pom.xml b/samples/tweet-button-plugin/pom.xml index e3d06ae0e..6664bb79b 100644 --- a/samples/tweet-button-plugin/pom.xml +++ b/samples/tweet-button-plugin/pom.xml @@ -21,7 +21,7 @@ samples org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT tweet-button-plugin diff --git a/scripting/pom.xml b/scripting/pom.xml index aca5fb1c8..a4569828a 100644 --- a/scripting/pom.xml +++ b/scripting/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-scripting @@ -50,7 +50,7 @@ org.apache.unomi unomi-api - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT test diff --git a/services/pom.xml b/services/pom.xml index 5d69fbe29..c4cf7e4da 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-services diff --git a/src/main/resources/assemblies/source-shared.xml b/src/main/resources/assemblies/source-shared.xml index 8249b8cd7..1bc82a7d8 100644 --- a/src/main/resources/assemblies/source-shared.xml +++ b/src/main/resources/assemblies/source-shared.xml @@ -93,8 +93,8 @@ **/extensions/web-tracker/wab/node/**/* **/extensions/web-tracker/wab/node_modules/**/* - **/graphql/graphql-playground/node/**/* - **/graphql/graphql-playground/node_modules/**/* + **/graphql/graphql-ui/node/**/* + **/graphql/graphql-ui/node_modules/**/* @@ -105,4 +105,4 @@ - \ No newline at end of file + diff --git a/tools/pom.xml b/tools/pom.xml index 4768ab711..41b1b3e01 100644 --- a/tools/pom.xml +++ b/tools/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-tools diff --git a/tools/shell-commands/pom.xml b/tools/shell-commands/pom.xml index 8dcd89f79..707c9f806 100644 --- a/tools/shell-commands/pom.xml +++ b/tools/shell-commands/pom.xml @@ -21,7 +21,7 @@ unomi-tools org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT shell-commands diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java index 503714a18..faa341e8a 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/HttpUtils.java @@ -124,7 +124,7 @@ public static String executePostRequest(CloseableHttpClient httpClient, String u httpPost.addHeader("accept", "application/json"); if (jsonData != null) { - StringEntity input = new StringEntity(jsonData); + StringEntity input = new StringEntity(jsonData, "UTF-8"); input.setContentType("application/json"); httpPost.setEntity(input); } diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java index 2059f1dc8..e08cbb733 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java @@ -123,7 +123,11 @@ public static void cleanAllIndexWithRollover(CloseableHttpClient httpClient, Bun }); String matchAllBodyRequest = resourceAsString(bundleContext, "requestBody/2.2.0/match_all_body_request.json"); - HttpUtils.executePostRequest(httpClient, esAddress + "/" + lastIndexName + "/_delete_by_query", matchAllBodyRequest, null); + try { + deleteByQuery(httpClient, esAddress, lastIndexName, matchAllBodyRequest); + } catch (Exception e) { + throw new RuntimeException(e); + } } } @@ -290,10 +294,48 @@ public static void waitForYellowStatus(CloseableHttpClient httpClient, String es } + /** + * Updates documents in an index based on a specified query. + * + *

This method sends a request to update documents that match the provided query in the specified index. The update operation is + * performed asynchronously, and the method waits for the task to complete before returning.

+ * + * @param httpClient the CloseableHttpClient used to send the request to the Elasticsearch server + * @param esAddress the address of the Elasticsearch server + * @param indexName the name of the index where documents should be updated + * @param requestBody the JSON body containing the query and update instructions for the documents + * @throws Exception if there is an error during the HTTP request or while waiting for the task to finish + */ + public static void updateByQuery(CloseableHttpClient httpClient, String esAddress, String indexName, String requestBody) throws Exception { + JSONObject task = new JSONObject(HttpUtils.executePostRequest(httpClient, esAddress + "/" + indexName + "/_update_by_query?wait_for_completion=false", requestBody, null)); + + //Wait for the deletion task to finish + waitForTaskToFinish(httpClient, esAddress, task.getString("task"), null); + } + + /** + * Deletes documents from an index based on a specified query. + * + *

This method sends a request to the Elasticsearch cluster to delete documents + * that match the provided query in the specified index. The deletion operation is + * performed asynchronously, and the method waits for the task to complete before returning.

+ * + * @param httpClient the CloseableHttpClient used to send the request to the Elasticsearch server + * @param esAddress the address of the Elasticsearch server + * @param indexName the name of the index from which documents should be deleted + * @param requestBody the JSON body containing the query that defines which documents to delete + * @throws Exception if there is an error during the HTTP request or while waiting for the task to finish + */ + public static void deleteByQuery(CloseableHttpClient httpClient, String esAddress, String indexName, String requestBody) throws Exception { + JSONObject task = new JSONObject(HttpUtils.executePostRequest(httpClient, esAddress + "/" + indexName + "/_delete_by_query?wait_for_completion=false", requestBody, null)); + //Wait for the deletion task to finish + waitForTaskToFinish(httpClient, esAddress, task.getString("task"), null); + } + public static void waitForTaskToFinish(CloseableHttpClient httpClient, String esAddress, String taskId, MigrationContext migrationContext) throws IOException { while (true) { final JSONObject status = new JSONObject( - HttpUtils.executeGetRequest(httpClient, esAddress + "/_tasks/" + taskId + "?wait_for_completion=true&timeout=15s", + HttpUtils.executeGetRequest(httpClient, esAddress + "/_tasks/" + taskId, null)); if (status.has("completed") && status.getBoolean("completed")) { if (migrationContext != null) { @@ -312,6 +354,11 @@ public static void waitForTaskToFinish(CloseableHttpClient httpClient, String es } else { LOGGER.info("Waiting for Task {} to complete", taskId); } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } } diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-01-aliases.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-01-aliases.groovy index 685d44288..ad6863682 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-01-aliases.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-01-aliases.groovy @@ -91,5 +91,5 @@ context.performMigrationStep("2.0.0-create-aliases-for-existing-merged-profiles" context.performMigrationStep("2.0.0-delete-existing-merged-profiles", () -> { String profileMergedDeleteRequest = MigrationUtils.resourceAsString(bundleContext,"requestBody/2.0.0/profile_merged_delete.json") - HttpUtils.executePostRequest(context.getHttpClient(), esAddress + "/" + profileIndex + "/_delete_by_query", profileMergedDeleteRequest, null) -}) \ No newline at end of file + MigrationUtils.deleteByQuery(context.getHttpClient(), esAddress, profileIndex, profileMergedDeleteRequest) +}) diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy index cb9f5ba1a..85a25df87 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy @@ -25,7 +25,7 @@ String indexPrefix = context.getConfigString("indexPrefix") context.performMigrationStep("2.0.0-remove-events-not-persisted-anymore", () -> { String removeInternalEventsRequest = MigrationUtils.resourceAsString(bundleContext, "requestBody/2.0.0/event_delete_by_query.json") - HttpUtils.executePostRequest(context.getHttpClient(), "${esAddress}/${indexPrefix}-event-*/_delete_by_query", removeInternalEventsRequest, null) + MigrationUtils.deleteByQuery(context.getHttpClient(), esAddress, "${indexPrefix}-event-*", removeInternalEventsRequest) }) // Reindex the rest of the events @@ -36,4 +36,4 @@ String newIndexSettings = MigrationUtils.buildIndexCreationRequest(baseSettings, Set eventIndices = MigrationUtils.getIndexesPrefixedBy(context.getHttpClient(), esAddress, "${indexPrefix}-event-date-") eventIndices.each { eventIndex -> MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, eventIndex, newIndexSettings, reIndexScript, context) -} \ No newline at end of file +} diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-20-scopes.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-20-scopes.groovy index 7b291abcd..053090b54 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-20-scopes.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-20-scopes.groovy @@ -25,6 +25,7 @@ MigrationContext context = migrationContext def jsonSlurper = new JsonSlurper() String searchScopesRequest = MigrationUtils.resourceAsString(bundleContext,"requestBody/2.0.0/scope_search.json") String saveScopeRequestBulk = MigrationUtils.resourceAsString(bundleContext, "requestBody/2.0.0/scope_save_bulk.ndjson") +String searchScopeById = MigrationUtils.resourceAsString(bundleContext, "requestBody/2.0.0/scope_search_by_item_id.json") String esAddress = context.getConfigString("esAddress") String indexPrefix = context.getConfigString("indexPrefix") String scopeIndex = indexPrefix + "-scope" @@ -52,20 +53,22 @@ context.performMigrationStep("2.0.0-create-scopes-from-existing-events", () -> { bucket -> { // Filter empty scope from existing events if (bucket.key) { + def scopeKey = bucket.key.replaceAll(" ", "-") // check that the scope doesn't already exists def scopeAlreadyExists = false try { - def existingScope = jsonSlurper.parseText(HttpUtils.executeGetRequest(context.getHttpClient(), esAddress + "/" + scopeIndex + "/_doc/" + bucket.key, null)); - scopeAlreadyExists = existingScope.found + context.printMessage("Check if " + scopeKey + " exists") + def existingScope = jsonSlurper.parseText(HttpUtils.executePostRequest(context.getHttpClient(), esAddress + "/" + scopeIndex + "/_search/", searchScopeById.replace("##scope##", scopeKey), null)); + scopeAlreadyExists = existingScope.hits.total.value > 0 } catch (HttpRequestException e) { // can happen in case response code > 400 due to item not exist in ElasticSearch } if (!scopeAlreadyExists) { - context.printMessage("Scope: " + bucket.key + " will be created") - bulkSaveRequest.append(saveScopeRequestBulk.replace("##scope##", bucket.key)) + context.printMessage("Scope: " + scopeKey + " will be created") + bulkSaveRequest.append(saveScopeRequestBulk.replace("##scope##", scopeKey)) } else { - context.printMessage("Scope: " + bucket.key + " already exists, won't be created") + context.printMessage("Scope: " + scopeKey + " already exists, won't be created") } } } @@ -77,4 +80,4 @@ context.performMigrationStep("2.0.0-create-scopes-from-existing-events", () -> { HttpUtils.executeGetRequest(context.getHttpClient(), esAddress + "/" + scopeIndex + "/_refresh", null) } } -}) \ No newline at end of file +}) diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.4.0-15-viewEventPagePath.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.4.0-15-viewEventPagePath.groovy index 8eb0de38d..1ac1776b5 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.4.0-15-viewEventPagePath.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.4.0-15-viewEventPagePath.groovy @@ -28,6 +28,6 @@ context.performMigrationStep("2.4.0-migrate-view-event-page-path", () -> { String updatePathScript = MigrationUtils.getFileWithoutComments(bundleContext, "requestBody/2.4.0/view_event_page_path_migrate.painless") String baseSettings = MigrationUtils.resourceAsString(bundleContext, "requestBody/2.4.0/base_update_by_query_request.json") eventIndices.each { eventIndex -> - HttpUtils.executePostRequest(context.getHttpClient(), "${esAddress}/${eventIndex}/_update_by_query", baseSettings.replace('#painless', updatePathScript), null) + MigrationUtils.updateByQuery(context.getHttpClient(), esAddress, eventIndex, baseSettings.replace('#painless', updatePathScript)); } }) diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy index 24e2042e6..967bc5714 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-10-loginEventScope.groovy @@ -28,6 +28,6 @@ context.performMigrationStep("2.5.0-migrate-login-event-scope", () -> { String updatePathScript = MigrationUtils.getFileWithoutComments(bundleContext, "requestBody/2.5.0/login_event_scope_migrate.painless") String baseSettings = MigrationUtils.resourceAsString(bundleContext, "requestBody/2.5.0/scope_update_by_query_request.json") eventIndices.each { eventIndex -> - HttpUtils.executePostRequest(context.getHttpClient(), "${esAddress}/${eventIndex}/_update_by_query", baseSettings.replace('#painless', updatePathScript), null) + MigrationUtils.updateByQuery(context.getHttpClient(), esAddress, eventIndex, baseSettings.replace('#painless', updatePathScript)); } }) diff --git a/tools/shell-commands/src/main/resources/requestBody/2.0.0/scope_search_by_item_id.json b/tools/shell-commands/src/main/resources/requestBody/2.0.0/scope_search_by_item_id.json new file mode 100644 index 000000000..54362daf4 --- /dev/null +++ b/tools/shell-commands/src/main/resources/requestBody/2.0.0/scope_search_by_item_id.json @@ -0,0 +1,8 @@ +{ + "query": { + "size": 1, + "term": { + "itemId": "##scope##" + } + } +} diff --git a/tools/shell-dev-commands/pom.xml b/tools/shell-dev-commands/pom.xml index 50836fd78..d47ab9d75 100644 --- a/tools/shell-dev-commands/pom.xml +++ b/tools/shell-dev-commands/pom.xml @@ -21,7 +21,7 @@ unomi-tools org.apache.unomi - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT shell-dev-commands diff --git a/wab/pom.xml b/wab/pom.xml index dbf2d9061..f72628870 100644 --- a/wab/pom.xml +++ b/wab/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-wab diff --git a/wab/src/main/webapp/index.html b/wab/src/main/webapp/index.html index cb4a09592..b691e3553 100644 --- a/wab/src/main/webapp/index.html +++ b/wab/src/main/webapp/index.html @@ -68,7 +68,7 @@

Where to go from here

Try Apache Unomi's integrated tracker
  • - Access the GraphQL Playground UI to browse and test GraphQL API requests when the graphQL + Access the GraphQL UI to browse and test GraphQL API requests when the graphQL feature is installed.
  • From 9a2a6c45dd306aa68d01690462dc80a0149d0136 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Thu, 5 Dec 2024 10:20:45 +0100 Subject: [PATCH 06/58] Bump all versions to 2.7 --- graphql/graphql-playground/pom.xml | 2 +- itests/pom.xml | 2 +- persistence-opensearch/conditions/pom.xml | 2 +- persistence-opensearch/core/pom.xml | 2 +- persistence-opensearch/pom.xml | 2 +- persistence-spi/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/graphql/graphql-playground/pom.xml b/graphql/graphql-playground/pom.xml index 9e5799a49..73ec4e686 100644 --- a/graphql/graphql-playground/pom.xml +++ b/graphql/graphql-playground/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-graphql - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-graphql-playground diff --git a/itests/pom.xml b/itests/pom.xml index ecb75133c..592da8297 100644 --- a/itests/pom.xml +++ b/itests/pom.xml @@ -21,7 +21,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-itests Apache Unomi :: Integration Tests diff --git a/persistence-opensearch/conditions/pom.xml b/persistence-opensearch/conditions/pom.xml index 7512f8f04..ae970a3cf 100644 --- a/persistence-opensearch/conditions/pom.xml +++ b/persistence-opensearch/conditions/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-persistence-opensearch - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-persistence-opensearch-conditions diff --git a/persistence-opensearch/core/pom.xml b/persistence-opensearch/core/pom.xml index 8e5eb2fa8..d950d82fc 100644 --- a/persistence-opensearch/core/pom.xml +++ b/persistence-opensearch/core/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-persistence-opensearch - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-persistence-opensearch-core diff --git a/persistence-opensearch/pom.xml b/persistence-opensearch/pom.xml index 1f84083e0..bc69db1b7 100644 --- a/persistence-opensearch/pom.xml +++ b/persistence-opensearch/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-persistence-opensearch diff --git a/persistence-spi/pom.xml b/persistence-spi/pom.xml index c8f17a510..337004450 100644 --- a/persistence-spi/pom.xml +++ b/persistence-spi/pom.xml @@ -22,7 +22,7 @@ org.apache.unomi unomi-root - 2.6.0-SNAPSHOT + 2.7.0-SNAPSHOT unomi-persistence-spi From fd3d31539661a728ec8959f891bf48c217beba0a Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Sat, 7 Dec 2024 16:47:19 +0100 Subject: [PATCH 07/58] Fix interface in blueprint descriptor --- .../core/src/main/resources/OSGI-INF/blueprint/blueprint.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 87fbfdb29..5dab36ff6 100644 --- a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -162,7 +162,7 @@ From 157e19592bb95a70bff1a24c748479d05e622961 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Sat, 7 Dec 2024 16:47:30 +0100 Subject: [PATCH 08/58] Fix interface in blueprint descriptor --- manual/src/main/asciidoc/builtin-condition-types.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/src/main/asciidoc/builtin-condition-types.adoc b/manual/src/main/asciidoc/builtin-condition-types.adoc index 924e1d6e6..68a484ba7 100644 --- a/manual/src/main/asciidoc/builtin-condition-types.adoc +++ b/manual/src/main/asciidoc/builtin-condition-types.adoc @@ -76,7 +76,7 @@ From https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/res ... - + From aad652b99bee9a688d8f20170dcc62f104a56f2c Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Sat, 7 Dec 2024 16:49:37 +0100 Subject: [PATCH 09/58] Fix interface in blueprint descriptor --- manual/src/main/asciidoc/writing-plugins.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manual/src/main/asciidoc/writing-plugins.adoc b/manual/src/main/asciidoc/writing-plugins.adoc index 8d2783c2b..7b230499d 100644 --- a/manual/src/main/asciidoc/writing-plugins.adoc +++ b/manual/src/main/asciidoc/writing-plugins.adoc @@ -526,7 +526,7 @@ src/main/resources/OSGI-INF/blueprint/blueprint.xml - + From e3fc5590cee1ab83cd55f42c0f8c1b488035f748 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Tue, 17 Dec 2024 14:54:49 +0100 Subject: [PATCH 10/58] - Fix issues with integration tests, ES tests now work 100% - Changed Unomi startup to use features instead of bundles - Added new build script that integrates all the functionality of the other build scripts - Fix IPv6 address parsing - Merge latest changes from master branch - --- build.sh | 451 +++++++++ .../karaf-kar/src/main/feature/feature.xml | 18 +- .../src/main/feature/feature.xml | 35 +- .../karaf-kar/src/main/feature/feature.xml | 11 +- .../karaf-kar/src/main/feature/feature.xml | 7 +- extensions/web-tracker/wab/yarn.lock | 444 ++++----- .../SegmentProfileEventsConditionParser.java | 13 +- .../META-INF/cxs/rules/cdpSessionEvent.json | 24 + .../META-INF/cxs/rules/updateConsent.json | 20 + .../META-INF/cxs/rules/updateLists.json | 24 + graphql/graphql-ui/yarn.lock | 886 +++++++++--------- .../src/main/feature/feature.xml | 65 +- itests/pom.xml | 6 + .../java/org/apache/unomi/itests/BaseIT.java | 52 +- .../unomi/itests/ProfileImportActorsIT.java | 10 +- .../itests/migration/Migrate16xTo220IT.java | 50 +- .../migration/snapshots_repository.zip | Bin 3872664 -> 7743842 bytes .../resources/org.apache.unomi.router.cfg | 6 - kar/src/main/feature/feature.xml | 138 +-- lifecycle-watcher/pom.xml | 6 - .../apache/unomi/lifecycle/BundleWatcher.java | 4 + .../unomi/lifecycle/BundleWatcherImpl.java | 80 +- .../OSGI-INF/blueprint/blueprint.xml | 3 - package/pom.xml | 27 +- .../ElasticsearchPersistenceTest.java | 175 ---- persistence-spi/pom.xml | 5 + .../persistence/spi/CustomObjectMapper.java | 1 + .../PastEventConditionESQueryBuilder.java | 70 +- pom.xml | 7 + .../impl/events/EventServiceImpl.java | 24 +- tools/shell-commands/pom.xml | 20 + .../org/apache/unomi/shell/actions/Start.java | 6 +- .../migration/service/MigrationConfig.java | 34 +- .../shell/migration/utils/MigrationUtils.java | 12 +- .../services/UnomiManagementService.java | 6 +- .../UnomiManagementServiceConfiguration.java | 34 + .../internal/UnomiManagementServiceImpl.java | 264 ++++-- .../migrate-2.0.0-05-globalReindex.groovy | 2 +- .../migrate-2.0.0-10-profileReindex.groovy | 2 +- .../migrate-2.0.0-15-eventsReindex.groovy | 3 +- ...5.0-00-cleanPastEventProfileSession.groovy | 7 +- .../main/resources/org.apache.unomi.start.cfg | 18 + .../2.5.0/login_event_scope_migrate.painless | 26 + .../2.5.0/remove_pastEvents_session.painless | 22 + .../OSGI-INF/blueprint/blueprint.xml | 9 +- 45 files changed, 1849 insertions(+), 1278 deletions(-) create mode 100755 build.sh create mode 100644 graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json create mode 100644 graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json create mode 100644 graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json delete mode 100644 persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/ElasticsearchPersistenceTest.java create mode 100644 tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceConfiguration.java create mode 100644 tools/shell-commands/src/main/resources/org.apache.unomi.start.cfg create mode 100644 tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless create mode 100644 tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..01d3d3938 --- /dev/null +++ b/build.sh @@ -0,0 +1,451 @@ +#!/bin/bash +################################################################################ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ + +set -e # Exit on error +trap 'handle_error $? $LINENO $BASH_LINENO "$BASH_COMMAND" $(printf "::%s" ${FUNCNAME[@]:-})' ERR + +# Error handling function +handle_error() { + local exit_code=$1 + local line_no=$2 + local bash_lineno=$3 + local last_command=$4 + local func_trace=$5 + + cat << "EOF" + _____ ____ ____ ___ ____ + | ____| _ \| _ \ / _ \| _ \ + | _| | |_) | |_) | | | | |_) | + | |___| _ <| _ <| |_| | _ < + |_____|_| \_\_| \_\\___/|_| \_\ + +EOF + echo "Error occurred in:" + echo " Command: $last_command" + echo " Line: $line_no" + echo " Exit code: $exit_code" + if [ ! -z "$func_trace" ]; then + echo " Function trace: $func_trace" + fi + exit $exit_code +} + +echo "-----------------------------------------------------------------------------------------------" +echo "Apache Unomi Build Script" +echo "-----------------------------------------------------------------------------------------------" +echo + +# Default values +SKIP_TESTS=false +RUN_INTEGRATION_TESTS=false +DEPLOY=false +DEBUG=false +USE_MAVEN_CACHE=true +PURGE_MAVEN_CACHE=false +MAVEN_DEBUG=false +MAVEN_OFFLINE=false +SEARCH_ENGINE="elasticsearch" +KARAF_DEBUG_PORT=5005 +KARAF_DEBUG_SUSPEND=n + +# Function to display usage +usage() { + cat << "EOF" + _ _ _____ _ ____ + | | | | ___| | | _ \ + | |__| | |__ | | | |_) | + | __ | __|| | | __/ + | | | | |___| |____| | + |_| |_\_____|______|_| + +EOF + echo "Usage: $0 [options]" + echo "Options:" + echo " -h, --help Show this help message" + echo " -s, --skip-tests Skip all tests" + echo " -i, --integration-tests Run integration tests" + echo " -d, --deploy Deploy after build" + echo " -X, --maven-debug Enable Maven debug output" + echo " -o, --offline Run Maven in offline mode" + echo " --debug Run Karaf in debug mode" + echo " --debug-port PORT Set debug port (default: 5005)" + echo " --debug-suspend Suspend JVM until debugger connects" + echo " --no-maven-cache Disable Maven build cache" + echo " --purge-maven-cache Purge local Maven cache before building" + echo " --search-engine ENGINE Set search engine (elasticsearch|opensearch)" + echo " --karaf-home PATH Set Karaf home directory for deployment" + echo "" + echo "Examples:" + echo " $0 --integration-tests --search-engine opensearch" + echo " $0 --debug --debug-port 5006 --debug-suspend" + echo " $0 --deploy --karaf-home ~/apache-karaf" + echo " $0 --purge-maven-cache --no-maven-cache" + echo " $0 -X --integration-tests Run tests with Maven debug output" + echo " $0 -o -X Run offline with Maven debug output" + exit 1 +} + +# Parse command line arguments +while [ "$1" != "" ]; do + case $1 in + -h | --help) + usage + ;; + -X | --maven-debug) + MAVEN_DEBUG=true + ;; + -o | --offline) + MAVEN_OFFLINE=true + ;; + -s | --skip-tests) + SKIP_TESTS=true + ;; + -i | --integration-tests) + RUN_INTEGRATION_TESTS=true + ;; + -d | --deploy) + DEPLOY=true + ;; + --debug) + DEBUG=true + ;; + --debug-port) + shift + KARAF_DEBUG_PORT=$1 + ;; + --debug-suspend) + KARAF_DEBUG_SUSPEND=y + ;; + --no-maven-cache) + USE_MAVEN_CACHE=false + ;; + --purge-maven-cache) + PURGE_MAVEN_CACHE=true + ;; + --search-engine) + shift + SEARCH_ENGINE=$1 + ;; + --karaf-home) + shift + CONTEXT_SERVER_KARAF_HOME=$1 + ;; + *) + echo "Unknown option: $1" + usage + ;; + esac + shift +done + +# Set environment +DIRNAME=`dirname "$0"` +PROGNAME=`basename "$0"` +if [ -f "$DIRNAME/setenv.sh" ]; then + . "$DIRNAME/setenv.sh" +fi + +# Purge Maven cache if requested +if [ "$PURGE_MAVEN_CACHE" = true ]; then + echo "Purging Maven cache..." + rm -rf ~/.m2/build-cache ~/.m2/dependency-cache ~/.m2/dependency-cache_v2 + echo "Maven cache purged." +fi + +# Validate search engine value +if [ "$SEARCH_ENGINE" != "elasticsearch" ] && [ "$SEARCH_ENGINE" != "opensearch" ]; then + echo "Invalid search engine: $SEARCH_ENGINE. Must be 'elasticsearch' or 'opensearch'" + exit 1 +fi + +# Function to check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Function to check required tools +check_requirements() { + local missing_tools=() + + for tool in mvn java tar gzip; do + if ! command_exists "$tool"; then + missing_tools+=("$tool") + fi + done + + if [ ${#missing_tools[@]} -ne 0 ]; then + echo "Error: Required tools are missing:" + printf ' - %s\n' "${missing_tools[@]}" + exit 1 + fi +} + +# Check requirements early +check_requirements + +# Construct Maven command +MVN_CMD="mvn" +MVN_OPTS="" + +# Add Maven debug option +if [ "$MAVEN_DEBUG" = true ]; then + MVN_OPTS="$MVN_OPTS -X" + echo "Maven debug output enabled" +fi + +# Add Maven offline option +if [ "$MAVEN_OFFLINE" = true ]; then + MVN_OPTS="$MVN_OPTS -o" + echo "Maven offline mode enabled" + + # Warn if purge cache is enabled with offline mode + if [ "$PURGE_MAVEN_CACHE" = true ]; then + echo "Warning: Purging Maven cache while in offline mode may cause build failures" + read -p "Continue anyway? (y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi + fi +fi + +# Add Maven cache option +if [ "$USE_MAVEN_CACHE" = false ]; then + MVN_OPTS="$MVN_OPTS -Dmaven.build.cache.enabled=false" +fi + +# Verify Maven settings +if [ ! -f ~/.m2/settings.xml ]; then + echo "Warning: Maven settings.xml not found at ~/.m2/settings.xml" + read -p "Continue anyway? (y/N) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Add profile options +PROFILES="" +if [ "$RUN_INTEGRATION_TESTS" = true ]; then + PROFILES="$PROFILES,integration-tests,$SEARCH_ENGINE" +else + if [ "$SKIP_TESTS" = true ]; then + PROFILES="$PROFILES,!integration-tests,!run-tests" + MVN_OPTS="$MVN_OPTS -DskipTests" + fi +fi + +if [ ! -z "$PROFILES" ]; then + # Remove leading comma if present + PROFILES=${PROFILES#,} + MVN_OPTS="$MVN_OPTS -P$PROFILES" +fi + +# Progress tracking functions +start_timer() { + start_time=$(date +%s) +} + +get_elapsed_time() { + local end_time=$(date +%s) + local elapsed=$((end_time - start_time)) + printf "%02d:%02d" $((elapsed/60)) $((elapsed%60)) +} + +print_progress() { + local step=$1 + local total=$2 + local msg=$3 + local elapsed=$(get_elapsed_time) + local width=50 + local progress=$((width * step / total)) + printf "\r[" + printf "%${progress}s" | tr ' ' '#' + printf "%$((width-progress))s" | tr ' ' '-' + printf "] %d%% %s (%s)" $((100 * step / total)) "$msg" "$elapsed" +} + +# Build command +cat << "EOF" + ____ _ _ _____ _ ____ + | _ \| | | |_ _| | | _ \ + | |_) | | | | | | | | | | | | + | _ <| | | | | | | | | | | | + | |_) | |__| |_| |_| |____| |_| | + |____/ \____/|_____|______|____/ + +EOF +echo "Building..." +echo "Estimated time: 3-5 minutes for build, 50-60 minutes with integration tests" +start_timer + +# Build phases +total_steps=2 +current_step=0 + +print_progress $((++current_step)) $total_steps "Cleaning previous build..." +$MVN_CMD clean $MVN_OPTS + +print_progress $((++current_step)) $total_steps "Compiling, testing and installing artifacts..." +$MVN_CMD install $MVN_OPTS + +echo -e "\nBuild completed in $(get_elapsed_time)" + +if [ "$DEPLOY" = true ]; then + # Validate Karaf home directory + if [ -z "$CONTEXT_SERVER_KARAF_HOME" ]; then + echo "Error: Karaf home directory not set. Use --karaf-home option." + exit 1 + fi + if [ ! -d "$CONTEXT_SERVER_KARAF_HOME" ]; then + echo "Error: Karaf home directory does not exist: $CONTEXT_SERVER_KARAF_HOME" + exit 1 + fi + if [ ! -w "$CONTEXT_SERVER_KARAF_HOME/deploy" ]; then + echo "Error: No write permission to Karaf deploy directory: $CONTEXT_SERVER_KARAF_HOME/deploy" + exit 1 + fi + + cat << "EOF" + ____ _____ ____ _ _____ __ + | _ \| ____| _ \| | / _ \ \ / / + | | | | _| | |_) | | | | | \ V / + | |_| | |___| __/| |__| |_| || | + |____/|_____|_| |_____\___/ |_| + +EOF + start_timer + total_deploy_steps=3 + current_step=0 + + print_progress $((++current_step)) $total_deploy_steps "Copying KAR package..." + if [ ! -f "kar/target/unomi-kar-$UNOMI_VERSION.kar" ]; then + echo "Error: KAR file not found: kar/target/unomi-kar-$UNOMI_VERSION.kar" + exit 1 + fi + cp -v kar/target/unomi-kar-$UNOMI_VERSION.kar $CONTEXT_SERVER_KARAF_HOME/deploy/ + if [ $? -ne 0 ]; then + echo "Error: Failed to copy KAR file to deploy directory" + exit 1 + fi + + print_progress $((++current_step)) $total_deploy_steps "Purging Karaf Maven repository..." + if [ -d "$CONTEXT_SERVER_KARAF_HOME/data/maven/repository" ]; then + rm -rf "$CONTEXT_SERVER_KARAF_HOME/data/maven/repository/"* || { + echo "Error: Failed to purge Karaf Maven repository" + exit 1 + } + fi + + print_progress $((++current_step)) $total_deploy_steps "Purging Karaf temporary files..." + if [ -d "$CONTEXT_SERVER_KARAF_HOME/data/tmp" ]; then + rm -rf "$CONTEXT_SERVER_KARAF_HOME/data/tmp/"* || { + echo "Error: Failed to purge Karaf temporary directory" + exit 1 + } + fi + + echo -e "\nDeployment completed in $(get_elapsed_time)" +fi + +if [ "$DEPLOY" = false ]; then + cat << "EOF" + _ __ _ ____ _ _____ + | |/ / / \ | _ \ / \ | ___| + | ' / / _ \ | |_) | / _ \ | |_ + | . \ / ___ \| _ < / ___ \| _| + |_|\_\/_/ \_\_| \_\/_/ \_\_| + +EOF + start_timer + total_karaf_steps=3 + current_step=0 + + pushd package/target || { + echo "Error: Failed to change directory to package/target" + exit 1 + } + + print_progress $((++current_step)) $total_karaf_steps "Uncompressing Unomi package..." + if [ ! -f "unomi-$UNOMI_VERSION.tar.gz" ]; then + echo "Error: Unomi package not found: unomi-$UNOMI_VERSION.tar.gz" + exit 1 + fi + tar zxvf unomi-$UNOMI_VERSION.tar.gz + + print_progress $((++current_step)) $total_karaf_steps "Installing optional databases..." + # Copy optional databases with error handling + if [ -f "../../GeoLite2-City.mmdb" ]; then + echo "Installing GeoLite2 City database..." + cp -v ../../GeoLite2-City.mmdb unomi-$UNOMI_VERSION/etc || { + echo "Error: Failed to copy GeoLite2 database" + exit 1 + } + fi + + if [ -f "../../allCountries.zip" ]; then + echo "Installing Geonames countries database..." + cp -v ../../allCountries.zip unomi-$UNOMI_VERSION/etc || { + echo "Error: Failed to copy Geonames database" + exit 1 + } + fi + + cd unomi-$UNOMI_VERSION/bin || { + echo "Error: Failed to change directory to Karaf bin directory" + exit 1 + } + + print_progress $((++current_step)) $total_karaf_steps "Starting Karaf..." + if [ "$DEBUG" = true ]; then + echo "Starting Karaf in debug mode (port: $KARAF_DEBUG_PORT, suspend: $KARAF_DEBUG_SUSPEND)" + # Check if debug port is already in use + if command_exists nc; then + if nc -z localhost $KARAF_DEBUG_PORT; then + echo "Error: Debug port $KARAF_DEBUG_PORT is already in use" + exit 1 + fi + fi + export KARAF_DEBUG=true + export JAVA_DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=$KARAF_DEBUG_SUSPEND,address=$KARAF_DEBUG_PORT" + fi + + if [ ! -x "./karaf" ]; then + echo "Error: Karaf executable not found or not executable" + exit 1 + fi + + echo "Apache Unomi features installed, use [unomi:start] to start it." + ./karaf || { + echo "Error: Karaf failed to start" + exit 1 + } + popd || true +fi + +cat << "EOF" + ____ ___ _ _ _____ _ + | _ \ / _ \| \ | | ____| | + | | | | | | | \| | _| | | + | |_| | |_| | |\ | |___|_| + |____/ \___/|_| \_|_____(_) + +EOF +echo "Operation completed successfully." diff --git a/extensions/groovy-actions/karaf-kar/src/main/feature/feature.xml b/extensions/groovy-actions/karaf-kar/src/main/feature/feature.xml index b3e0783cb..5c9e4915a 100644 --- a/extensions/groovy-actions/karaf-kar/src/main/feature/feature.xml +++ b/extensions/groovy-actions/karaf-kar/src/main/feature/feature.xml @@ -19,14 +19,14 @@
    ${project.description}
    wrap - unomi-kar - mvn:org.apache.groovy/groovy/${groovy.version} - mvn:org.apache.groovy/groovy-xml/${groovy.version} - mvn:org.apache.groovy/groovy-json/${groovy.version} - wrap:mvn:io.github.http-builder-ng/http-builder-ng-core/1.0.4 - mvn:org.jsoup/jsoup/1.13.1 - mvn:com.sun.activation/javax.activation/1.2.0 - mvn:org.apache.unomi/unomi-groovy-actions-services/${project.version} - mvn:org.apache.unomi/unomi-groovy-actions-rest/${project.version} + mvn:org.apache.unomi/unomi-groovy-actions-services/${project.version}/cfg/groovyactionscfg + mvn:org.apache.groovy/groovy/${groovy.version} + mvn:org.apache.groovy/groovy-xml/${groovy.version} + mvn:org.apache.groovy/groovy-json/${groovy.version} + wrap:mvn:io.github.http-builder-ng/http-builder-ng-core/1.0.4 + mvn:org.jsoup/jsoup/1.13.1 + mvn:com.sun.activation/javax.activation/1.2.0 + mvn:org.apache.unomi/unomi-groovy-actions-services/${project.version} + mvn:org.apache.unomi/unomi-groovy-actions-rest/${project.version}
    diff --git a/extensions/router/router-karaf-feature/src/main/feature/feature.xml b/extensions/router/router-karaf-feature/src/main/feature/feature.xml index 6d707cf67..b67306312 100644 --- a/extensions/router/router-karaf-feature/src/main/feature/feature.xml +++ b/extensions/router/router-karaf-feature/src/main/feature/feature.xml @@ -19,23 +19,22 @@
    Apache Karaf feature for the Apache Unomi Context Server extension
    wrap - unomi-kar - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsch/0.1.54_1 - mvn:commons-net/commons-net/${commons-net.version} - wrap:mvn:org.apache.kafka/kafka-clients/${kafka.client.version} - mvn:org.apache.camel/camel-core/${camel.version} - mvn:org.apache.camel/camel-core-osgi/${camel.version} - mvn:org.apache.camel/camel-blueprint/${camel.version} - mvn:org.apache.camel/camel-jackson/${camel.version} - mvn:org.apache.camel/camel-http-common/${camel.version} - mvn:org.apache.camel/camel-servlet/${camel.version} - mvn:org.apache.camel/camel-ftp/${camel.version} - mvn:org.apache.camel/camel-stream/${camel.version} - mvn:org.apache.camel/camel-kafka/${camel.version} - mvn:org.apache.cxf/cxf-rt-rs-security-cors/${cxf.version} - mvn:org.apache.unomi/unomi-router-api/${project.version} - mvn:org.apache.unomi/unomi-router-core/${project.version} - mvn:org.apache.unomi/unomi-router-service/${project.version} - mvn:org.apache.unomi/unomi-router-rest/${project.version} + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsch/0.1.54_1 + mvn:commons-net/commons-net/${commons-net.version} + wrap:mvn:org.apache.kafka/kafka-clients/${kafka.client.version} + mvn:org.apache.camel/camel-core/${camel.version} + mvn:org.apache.camel/camel-core-osgi/${camel.version} + mvn:org.apache.camel/camel-blueprint/${camel.version} + mvn:org.apache.camel/camel-jackson/${camel.version} + mvn:org.apache.camel/camel-http-common/${camel.version} + mvn:org.apache.camel/camel-servlet/${camel.version} + mvn:org.apache.camel/camel-ftp/${camel.version} + mvn:org.apache.camel/camel-stream/${camel.version} + mvn:org.apache.camel/camel-kafka/${camel.version} + mvn:org.apache.cxf/cxf-rt-rs-security-cors/${cxf.version} + mvn:org.apache.unomi/unomi-router-api/${project.version} + mvn:org.apache.unomi/unomi-router-core/${project.version} + mvn:org.apache.unomi/unomi-router-service/${project.version} + mvn:org.apache.unomi/unomi-router-rest/${project.version}
    diff --git a/extensions/salesforce-connector/karaf-kar/src/main/feature/feature.xml b/extensions/salesforce-connector/karaf-kar/src/main/feature/feature.xml index aa544d8a2..dbe796eec 100644 --- a/extensions/salesforce-connector/karaf-kar/src/main/feature/feature.xml +++ b/extensions/salesforce-connector/karaf-kar/src/main/feature/feature.xml @@ -18,12 +18,11 @@
    Apache Karaf feature for the Apache Unomi Context Server extension that integrates with Salesforce
    - unomi-kar mvn:org.apache.unomi/unomi-salesforce-connector-services/${project.version}/cfg/sfdccfg - mvn:org.apache.httpcomponents/httpcore-osgi/${httpcore-osgi.version} - mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-osgi.version} - mvn:org.apache.unomi/unomi-salesforce-connector-services/${project.version} - mvn:org.apache.unomi/unomi-salesforce-connector-rest/${project.version} - mvn:org.apache.unomi/unomi-salesforce-connector-actions/${project.version} + mvn:org.apache.httpcomponents/httpcore-osgi/${httpcore-osgi.version} + mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-osgi.version} + mvn:org.apache.unomi/unomi-salesforce-connector-services/${project.version} + mvn:org.apache.unomi/unomi-salesforce-connector-rest/${project.version} + mvn:org.apache.unomi/unomi-salesforce-connector-actions/${project.version}
    diff --git a/extensions/weather-update/karaf-kar/src/main/feature/feature.xml b/extensions/weather-update/karaf-kar/src/main/feature/feature.xml index f1db52bb4..86bdaf90e 100644 --- a/extensions/weather-update/karaf-kar/src/main/feature/feature.xml +++ b/extensions/weather-update/karaf-kar/src/main/feature/feature.xml @@ -20,10 +20,9 @@ description="Apache Unomi :: Extensions :: Weather update :: Apache Karaf Feature">
    Apache Karaf feature for the Apache Unomi Context Server extension that integrates Weather update
    - unomi-kar mvn:org.apache.unomi/unomi-weather-update-core/${project.version}/cfg/weatherupdatecfg - mvn:org.apache.httpcomponents/httpcore-osgi/${httpcore-osgi.version} - mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-osgi.version} - mvn:org.apache.unomi/unomi-weather-update-core/${project.version} + mvn:org.apache.httpcomponents/httpcore-osgi/${httpcore-osgi.version} + mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-osgi.version} + mvn:org.apache.unomi/unomi-weather-update-core/${project.version} diff --git a/extensions/web-tracker/wab/yarn.lock b/extensions/web-tracker/wab/yarn.lock index 879c19dd7..1ba5f474a 100644 --- a/extensions/web-tracker/wab/yarn.lock +++ b/extensions/web-tracker/wab/yarn.lock @@ -4,7 +4,7 @@ "@ampproject/remapping@^2.1.0": version "2.2.0" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz" integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: "@jridgewell/gen-mapping" "^0.1.0" @@ -12,19 +12,19 @@ "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" "@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8", "@babel/compat-data@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.19.1.tgz#72d647b4ff6a4f82878d184613353af1dd0290f9" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.1.tgz" integrity sha512-72a9ghR0gnESIa7jBN53U32FOVCEoztyIlKaNoU05zRhEecduGK9L9c3ww7Mp06JiR+0ls0GBPFJQwwtjn9ksg== "@babel/core@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.19.1.tgz#c8fa615c5e88e272564ace3d42fbc8b17bfeb22b" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.19.1.tgz" integrity sha512-1H8VgqXme4UXCRv7/Wa1bq7RVymKOzC7znjyFM8KiEzwFqcKUKYNoQef4GhdklgNvoBXyW4gYhuBNCM5o1zImw== dependencies: "@ampproject/remapping" "^2.1.0" @@ -45,7 +45,7 @@ "@babel/generator@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.0.tgz#785596c06425e59334df2ccee63ab166b738419a" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz" integrity sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg== dependencies: "@babel/types" "^7.19.0" @@ -54,14 +54,14 @@ "@babel/helper-annotate-as-pure@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz" integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz" integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== dependencies: "@babel/helper-explode-assignable-expression" "^7.18.6" @@ -69,7 +69,7 @@ "@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.19.0", "@babel/helper-compilation-targets@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz#7f630911d83b408b76fe584831c98e5395d7a17c" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.1.tgz" integrity sha512-LlLkkqhCMyz2lkQPvJNdIYU7O5YjWRgC2R4omjCTpZd8u8KMQzZvX4qce+/BluN1rcQiV7BoGUpmQ0LeHerbhg== dependencies: "@babel/compat-data" "^7.19.1" @@ -79,7 +79,7 @@ "@babel/helper-create-class-features-plugin@^7.18.6": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz#bfd6904620df4e46470bae4850d66be1054c404b" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz" integrity sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -92,7 +92,7 @@ "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz" integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -100,7 +100,7 @@ "@babel/helper-define-polyfill-provider@^0.3.3": version "0.3.3" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + resolved "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz" integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== dependencies: "@babel/helper-compilation-targets" "^7.17.7" @@ -112,19 +112,19 @@ "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== "@babel/helper-explode-assignable-expression@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz" integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== dependencies: "@babel/types" "^7.18.6" "@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz" integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: "@babel/template" "^7.18.10" @@ -132,28 +132,28 @@ "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz" integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: "@babel/types" "^7.18.6" "@babel/helper-member-expression-to-functions@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz" integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== dependencies: "@babel/types" "^7.18.9" "@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz" integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz#309b230f04e22c58c6a2c0c0c7e50b216d350c30" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz" integrity sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -167,19 +167,19 @@ "@babel/helper-optimise-call-expression@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz" integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz#4796bb14961521f0f8715990bee2fb6e51ce21bf" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz" integrity sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw== "@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz" integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -189,7 +189,7 @@ "@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz" integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -200,43 +200,43 @@ "@babel/helper-simple-access@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz" integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g== dependencies: "@babel/types" "^7.18.6" "@babel/helper-skip-transparent-expression-wrappers@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz" integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw== dependencies: "@babel/types" "^7.18.9" "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz" integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== dependencies: "@babel/types" "^7.18.6" "@babel/helper-string-parser@^7.18.10": version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56" + resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz" integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw== "@babel/helper-validator-identifier@^7.18.6": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== "@babel/helper-validator-option@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== "@babel/helper-wrap-function@^7.18.9": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz" integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== dependencies: "@babel/helper-function-name" "^7.19.0" @@ -246,7 +246,7 @@ "@babel/helpers@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.19.0.tgz#f30534657faf246ae96551d88dd31e9d1fa1fc18" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.0.tgz" integrity sha512-DRBCKGwIEdqY3+rPJgG/dKfQy9+08rHIAJx8q2p+HSWP87s2HCrQmaAMMyMll2kIXKCW0cO1RdQskx15Xakftg== dependencies: "@babel/template" "^7.18.10" @@ -255,7 +255,7 @@ "@babel/highlight@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz" integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== dependencies: "@babel/helper-validator-identifier" "^7.18.6" @@ -264,19 +264,19 @@ "@babel/parser@^7.18.10", "@babel/parser@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz" integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A== "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz" integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + resolved "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz" integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -285,7 +285,7 @@ "@babel/plugin-proposal-async-generator-functions@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz#34f6f5174b688529342288cd264f80c9ea9fb4a7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.19.1.tgz" integrity sha512-0yu8vNATgLy4ivqMNBIwb1HebCelqN7YX8SL3FDXORv/RqT0zEEWUCH4GH44JsSrvCu6GqnAdR5EBFAPeNBB4Q== dependencies: "@babel/helper-environment-visitor" "^7.18.9" @@ -295,7 +295,7 @@ "@babel/plugin-proposal-class-properties@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz" integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -303,7 +303,7 @@ "@babel/plugin-proposal-class-static-block@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz" integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -312,7 +312,7 @@ "@babel/plugin-proposal-dynamic-import@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz" integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -320,7 +320,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz" integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -328,7 +328,7 @@ "@babel/plugin-proposal-json-strings@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz" integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -336,7 +336,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz" integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -344,7 +344,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -352,7 +352,7 @@ "@babel/plugin-proposal-numeric-separator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz" integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -360,7 +360,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz" integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q== dependencies: "@babel/compat-data" "^7.18.8" @@ -371,7 +371,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz" integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -379,7 +379,7 @@ "@babel/plugin-proposal-optional-chaining@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz" integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== dependencies: "@babel/helper-plugin-utils" "^7.18.9" @@ -388,7 +388,7 @@ "@babel/plugin-proposal-private-methods@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz" integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: "@babel/helper-create-class-features-plugin" "^7.18.6" @@ -396,7 +396,7 @@ "@babel/plugin-proposal-private-property-in-object@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz" integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -406,7 +406,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz" integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -414,119 +414,119 @@ "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.13": version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz" integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== dependencies: "@babel/helper-plugin-utils" "^7.12.13" "@babel/plugin-syntax-class-static-block@^7.14.5": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz" integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-import-assertions@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz" integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-private-property-in-object@^7.14.5": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz" integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-top-level-await@^7.14.5": version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz" integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== dependencies: "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-transform-arrow-functions@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz" integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-async-to-generator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz" integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: "@babel/helper-module-imports" "^7.18.6" @@ -535,21 +535,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz" integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-block-scoping@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz" integrity sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-classes@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz#0e61ec257fba409c41372175e7c1e606dc79bb20" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz" integrity sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A== dependencies: "@babel/helper-annotate-as-pure" "^7.18.6" @@ -564,21 +564,21 @@ "@babel/plugin-transform-computed-properties@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz" integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-destructuring@^7.18.13": version "7.18.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz#9e03bc4a94475d62b7f4114938e6c5c33372cbf5" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz" integrity sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz" integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -586,14 +586,14 @@ "@babel/plugin-transform-duplicate-keys@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz" integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-exponentiation-operator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz" integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" @@ -601,14 +601,14 @@ "@babel/plugin-transform-for-of@^7.18.8": version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz" integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-function-name@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz" integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== dependencies: "@babel/helper-compilation-targets" "^7.18.9" @@ -617,21 +617,21 @@ "@babel/plugin-transform-literals@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz" integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-member-expression-literals@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz" integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-modules-amd@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz" integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -640,7 +640,7 @@ "@babel/plugin-transform-modules-commonjs@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz" integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -650,7 +650,7 @@ "@babel/plugin-transform-modules-systemjs@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz#5f20b471284430f02d9c5059d9b9a16d4b085a1f" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz" integrity sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A== dependencies: "@babel/helper-hoist-variables" "^7.18.6" @@ -661,7 +661,7 @@ "@babel/plugin-transform-modules-umd@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz" integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: "@babel/helper-module-transforms" "^7.18.6" @@ -669,7 +669,7 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz" integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.19.0" @@ -677,14 +677,14 @@ "@babel/plugin-transform-new-target@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz" integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-object-super@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz" integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -692,21 +692,21 @@ "@babel/plugin-transform-parameters@^7.18.8": version "7.18.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz" integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-property-literals@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz" integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-regenerator@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz" integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: "@babel/helper-plugin-utils" "^7.18.6" @@ -714,21 +714,21 @@ "@babel/plugin-transform-reserved-words@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz" integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-shorthand-properties@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz" integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-spread@^7.19.0": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz" integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== dependencies: "@babel/helper-plugin-utils" "^7.19.0" @@ -736,35 +736,35 @@ "@babel/plugin-transform-sticky-regex@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz" integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== dependencies: "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-transform-template-literals@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz" integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-typeof-symbol@^7.18.9": version "7.18.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz" integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-escapes@^7.18.10": version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz" integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== dependencies: "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-transform-unicode-regex@^7.18.6": version "7.18.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz" integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.18.6" @@ -772,7 +772,7 @@ "@babel/preset-env@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.19.1.tgz#9f04c916f9c0205a48ebe5cc1be7768eb1983f67" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.19.1.tgz" integrity sha512-c8B2c6D16Lp+Nt6HcD+nHl0VbPKVnNPTpszahuxJJnurfMtKeZ80A+qUv48Y7wqvS+dTFuLuaM9oYxyNHbCLWA== dependencies: "@babel/compat-data" "^7.19.1" @@ -853,7 +853,7 @@ "@babel/preset-modules@^0.1.5": version "0.1.5" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz" integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -864,21 +864,21 @@ "@babel/runtime@^7.18.9": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" "@babel/runtime@^7.8.4": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.19.0.tgz" integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== dependencies: regenerator-runtime "^0.13.4" "@babel/template@^7.18.10": version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz" integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== dependencies: "@babel/code-frame" "^7.18.6" @@ -887,7 +887,7 @@ "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1": version "7.19.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.1.tgz#0fafe100a8c2a603b4718b1d9bf2568d1d193347" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz" integrity sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA== dependencies: "@babel/code-frame" "^7.18.6" @@ -903,7 +903,7 @@ "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.4.4": version "7.19.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.0.tgz#75f21d73d73dc0351f3368d28db73465f4814600" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz" integrity sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA== dependencies: "@babel/helper-string-parser" "^7.18.10" @@ -912,7 +912,7 @@ "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== dependencies: "@jridgewell/set-array" "^1.0.0" @@ -920,7 +920,7 @@ "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz" integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== dependencies: "@jridgewell/set-array" "^1.0.1" @@ -929,17 +929,17 @@ "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + resolved "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== "@jridgewell/source-map@^0.3.2": version "0.3.2" - resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + resolved "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz" integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== dependencies: "@jridgewell/gen-mapping" "^0.3.0" @@ -947,12 +947,12 @@ "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== "@jridgewell/trace-mapping@^0.3.9": version "0.3.15" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz#aba35c48a38d3fd84b37e66c9c0423f9744f9774" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz" integrity sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g== dependencies: "@jridgewell/resolve-uri" "^3.0.3" @@ -960,7 +960,7 @@ "@rollup/plugin-babel@^5.3.1": version "5.3.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" + resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz" integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q== dependencies: "@babel/helper-module-imports" "^7.10.4" @@ -968,7 +968,7 @@ "@rollup/plugin-commonjs@^22.0.2": version "22.0.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz#ee8ca8415cda30d383b4096aad5222435b4b69b6" + resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-22.0.2.tgz" integrity sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -981,7 +981,7 @@ "@rollup/plugin-inject@^4.0.0": version "4.0.4" - resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-4.0.4.tgz#fbeee66e9a700782c4f65c8b0edbafe58678fbc2" + resolved "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-4.0.4.tgz" integrity sha512-4pbcU4J/nS+zuHk+c+OL3WtmEQhqxlZ9uqfjQMQDOHOPld7PsCd8k5LWs8h5wjwJN7MgnAn768F2sDxEP4eNFQ== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -990,7 +990,7 @@ "@rollup/plugin-node-resolve@^14.1.0": version "14.1.0" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz#f2fa475405cd7fed6420bf438fe393f988a9bc96" + resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-14.1.0.tgz" integrity sha512-5G2niJroNCz/1zqwXtk0t9+twOSDlG00k1Wfd7bkbbXmwg8H8dvgHdIWAun53Ps/rckfvOC7scDBjuGFg5OaWw== dependencies: "@rollup/pluginutils" "^3.1.0" @@ -1002,7 +1002,7 @@ "@rollup/pluginutils@^3.0.9", "@rollup/pluginutils@^3.1.0": version "3.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz" integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== dependencies: "@types/estree" "0.0.39" @@ -1011,41 +1011,41 @@ "@types/estree@*": version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.0.tgz" integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== "@types/estree@0.0.39": version "0.0.39" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/node@*": version "18.7.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.18.tgz#633184f55c322e4fb08612307c274ee6d5ed3154" + resolved "https://registry.npmjs.org/@types/node/-/node-18.7.18.tgz" integrity sha512-m+6nTEOadJZuTPkKR/SYK3A2d7FZrgElol9UP1Kae90VVU4a6mxnPuLiIW1m4Cq4gZ/nWb9GrdVXJCoCazDAbg== "@types/resolve@1.17.1": version "1.17.1" - resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" + resolved "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz" integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw== dependencies: "@types/node" "*" acorn@^8.5.0: version "8.8.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz" integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" apache-unomi-tracker@^1.1.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/apache-unomi-tracker/-/apache-unomi-tracker-1.4.0.tgz#50707986531fc4f5dec28cdf06a18e48610bcb78" + resolved "https://registry.npmjs.org/apache-unomi-tracker/-/apache-unomi-tracker-1.4.0.tgz" integrity sha512-5mYm1GQDrzUNxYcQymmGYYkk7AKjGakI5T3wUH4apjiRzKwPMiMyRvc45HvYNmcCGZoPlP1AEcimVu+2t0M7PA== dependencies: "@babel/runtime" "^7.18.9" @@ -1053,19 +1053,19 @@ apache-unomi-tracker@^1.1.0: atob@^2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" babel-plugin-polyfill-corejs2@^0.3.3: version "0.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz" integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== dependencies: "@babel/compat-data" "^7.17.7" @@ -1074,7 +1074,7 @@ babel-plugin-polyfill-corejs2@^0.3.3: babel-plugin-polyfill-corejs3@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz" integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" @@ -1082,19 +1082,19 @@ babel-plugin-polyfill-corejs3@^0.6.0: babel-plugin-polyfill-regenerator@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + resolved "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz" integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== dependencies: "@babel/helper-define-polyfill-provider" "^0.3.3" balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" @@ -1102,7 +1102,7 @@ brace-expansion@^1.1.7: browserslist@^4.21.3, browserslist@^4.21.4: version "4.21.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz" integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== dependencies: caniuse-lite "^1.0.30001400" @@ -1112,17 +1112,17 @@ browserslist@^4.21.3, browserslist@^4.21.4: buffer-from@^1.0.0: version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== builtin-modules@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" + resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== call-bind@^1.0.2: version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1130,12 +1130,12 @@ call-bind@^1.0.2: caniuse-lite@^1.0.30001400: version "1.0.30001407" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz#92281a6ee67cb90bfd8a6a1201fcc2dc19b60a15" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001407.tgz" integrity sha512-4ydV+t4P7X3zH83fQWNDX/mQEzYomossfpViCOx9zHBSMV+rIe3LFqglHHtVyvNl1FhTNxPxs3jei82iqOW04w== chalk@^2.0.0: version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1144,65 +1144,65 @@ chalk@^2.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== commander@^2.20.0: version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== concat-map@0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== convert-source-map@^1.7.0: version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== dependencies: safe-buffer "~5.1.1" core-js-compat@^3.25.1: version "3.25.2" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.25.2.tgz#7875573586809909c69e03ef310810c1969ee138" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.2.tgz" integrity sha512-TxfyECD4smdn3/CjWxczVtJqVLEEC2up7/82t7vC0AzNogr+4nQ8vyF7abxAuTXWvjTClSbvGhU0RgqA4ToQaQ== dependencies: browserslist "^4.21.4" debug@^4.1.0, debug@^4.1.1: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" decode-uri-component@^0.2.0: version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== deepmerge@^4.2.2: version "4.2.2" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== define-properties@^1.1.4: version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz" integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: has-property-descriptors "^1.0.0" @@ -1210,62 +1210,62 @@ define-properties@^1.1.4: electron-to-chromium@^1.4.251: version "1.4.255" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz#dc52d1095b876ed8acf25865db10265b02b1d6e1" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.255.tgz" integrity sha512-H+mFNKow6gi2P5Gi2d1Fvd3TUEJlB9CF7zYaIV9T83BE3wP1xZ0mRPbNTm0KUjyd1QiVy7iKXuIcjlDtBQMiAQ== es6-crawler-detect@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/es6-crawler-detect/-/es6-crawler-detect-3.3.0.tgz#3a05cd3f2739099145bf40b012a6ad472cbbfb49" + resolved "https://registry.npmjs.org/es6-crawler-detect/-/es6-crawler-detect-3.3.0.tgz" integrity sha512-ptGU13H76+HNr5n0kvi5aO+RuqRHaIET/60Srv4+BgVWsuVVf3x9seDhz/IEcmuQMXJvrU2g+DbrKVrliUkTJQ== escalade@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== estree-walker@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz" integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== estree-walker@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" + resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== gensync@^1.0.0-beta.2: version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz" integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== dependencies: function-bind "^1.1.1" @@ -1274,7 +1274,7 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: glob@^7.1.6: version "7.2.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" @@ -1286,41 +1286,41 @@ glob@^7.1.6: globals@^11.1.0: version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + resolved "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz" integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: get-intrinsic "^1.1.1" has-symbols@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has@^1.0.3: version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" inflight@^1.0.4: version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" @@ -1328,38 +1328,38 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== is-builtin-module@^3.1.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.0.tgz#bb0310dfe881f144ca83f30100ceb10cf58835e0" + resolved "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.0.tgz" integrity sha512-phDA4oSGt7vl1n5tJvTWooWWAsXLY+2xCnxNqvKhGEzujg+A43wPlPOyDg3C8XQHN+6k/JTQWJ/j0dQh/qr+Hw== dependencies: builtin-modules "^3.3.0" is-core-module@^2.9.0: version "2.10.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz" integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== dependencies: has "^1.0.3" is-module@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" + resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== is-reference@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7" + resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz" integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ== dependencies: "@types/estree" "*" jest-worker@^26.2.1: version "26.6.2" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz" integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== dependencies: "@types/node" "*" @@ -1368,66 +1368,66 @@ jest-worker@^26.2.1: js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== json5@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== lodash.debounce@^4.0.8: version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== magic-string@^0.25.7: version "0.25.9" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz" integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ== dependencies: sourcemap-codec "^1.4.8" merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== minimatch@^3.1.1: version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== node-releases@^2.0.6: version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.0: version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz" integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" @@ -1437,70 +1437,70 @@ object.assign@^4.1.0: once@^1.3.0: version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== picocolors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== picomatch@^2.2.2: version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" regenerate-unicode-properties@^10.1.0: version "10.1.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz" integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== dependencies: regenerate "^1.4.2" regenerate@^1.4.2: version "1.4.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== regenerator-runtime@^0.14.0: version "0.14.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz" integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== regenerator-transform@^0.15.0: version "0.15.0" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz" integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg== dependencies: "@babel/runtime" "^7.8.4" regexpu-core@^5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz" integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ== dependencies: regenerate "^1.4.2" @@ -1512,19 +1512,19 @@ regexpu-core@^5.1.0: regjsgen@^0.7.1: version "0.7.1" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz" integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== regjsparser@^0.9.1: version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz" integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0: version "1.22.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: is-core-module "^2.9.0" @@ -1533,14 +1533,14 @@ resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0: rollup-plugin-polyfill-node@^0.10.2: version "0.10.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.10.2.tgz#b2128646851fcb9475ddfd5bc22ca1a8c568738d" + resolved "https://registry.npmjs.org/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.10.2.tgz" integrity sha512-5GMywXiLiuQP6ZzED/LO/Q0HyDi2W6b8VN+Zd3oB0opIjyRs494Me2ZMaqKWDNbGiW4jvvzl6L2n4zRgxS9cSQ== dependencies: "@rollup/plugin-inject" "^4.0.0" rollup-plugin-sourcemaps@^0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz#bf93913ffe056e414419607f1d02780d7ece84ed" + resolved "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz" integrity sha512-paFu+nT1xvuO1tPFYXGe+XnQvg4Hjqv/eIhG8i5EspfYYPBKL57X7iVbfv55aNVASg3dzWvES9dmWsL2KhfByw== dependencies: "@rollup/pluginutils" "^3.0.9" @@ -1548,7 +1548,7 @@ rollup-plugin-sourcemaps@^0.6.3: rollup-plugin-terser@^7.0.2: version "7.0.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" + resolved "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz" integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ== dependencies: "@babel/code-frame" "^7.10.4" @@ -1558,36 +1558,36 @@ rollup-plugin-terser@^7.0.2: rollup@^2.79.0: version "2.79.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.0.tgz#9177992c9f09eb58c5e56cbfa641607a12b57ce2" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.79.0.tgz" integrity sha512-x4KsrCgwQ7ZJPcFA/SUu6QVcYlO7uRLfLAy0DSA4NS2eG8japdbpM50ToH7z4iObodRYOJ0soneF0iaQRJ6zhA== optionalDependencies: fsevents "~2.3.2" safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== serialize-javascript@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz" integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== dependencies: randombytes "^2.1.0" source-map-resolve@^0.6.0: version "0.6.0" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" + resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz" integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== dependencies: atob "^2.1.2" @@ -1595,7 +1595,7 @@ source-map-resolve@^0.6.0: source-map-support@~0.5.20: version "0.5.21" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" @@ -1603,36 +1603,36 @@ source-map-support@~0.5.20: source-map@^0.6.0: version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== sourcemap-codec@^1.4.8: version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + resolved "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.0.0: version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== terser@^5.0.0: version "5.15.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.0.tgz#e16967894eeba6e1091509ec83f0c60e179f2425" + resolved "https://registry.npmjs.org/terser/-/terser-5.15.0.tgz" integrity sha512-L1BJiXVmheAQQy+as0oF3Pwtlo4s3Wi1X2zNZ2NxOB4wx9bdS9Vk67XQENLFdLYGCK/Z2di53mTj/hBafR+dTA== dependencies: "@jridgewell/source-map" "^0.3.2" @@ -1642,17 +1642,17 @@ terser@^5.0.0: to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz" integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz" integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q== dependencies: unicode-canonical-property-names-ecmascript "^2.0.0" @@ -1660,17 +1660,17 @@ unicode-match-property-ecmascript@^2.0.0: unicode-match-property-value-ecmascript@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz" integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz" integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== update-browserslist-db@^1.0.9: version "1.0.9" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz" integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg== dependencies: escalade "^3.1.1" @@ -1678,5 +1678,5 @@ update-browserslist-db@^1.0.9: wrappy@1: version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== diff --git a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/parsers/SegmentProfileEventsConditionParser.java b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/parsers/SegmentProfileEventsConditionParser.java index 090f15280..20e7acac7 100644 --- a/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/parsers/SegmentProfileEventsConditionParser.java +++ b/graphql/cxs-impl/src/main/java/org/apache/unomi/graphql/condition/parsers/SegmentProfileEventsConditionParser.java @@ -185,9 +185,16 @@ private Map createProfileEventPropertyField(final Condition cond tuple.put("fieldName", "cdp_timestamp_gte"); } - final OffsetDateTime fieldValue = DateUtils.offsetDateTimeFromMap((Map) condition.getParameter("propertyValueDate")); - - tuple.put("fieldValue", fieldValue != null ? fieldValue.toString() : null); + Object propertyValueDate = condition.getParameter("propertyValueDate"); + if (propertyValueDate == null) { + tuple.put("fieldValue", null); + } else if (propertyValueDate instanceof Map){ + // This shouldn't be needed since Jackson was upgraded to > 2.13, but we keep it for backwards compatibility with older data sets + final OffsetDateTime fieldValue = DateUtils.offsetDateTimeFromMap((Map) propertyValueDate); + tuple.put("fieldValue", fieldValue != null ? fieldValue.toString() : null); + } else { + tuple.put("fieldValue", propertyValueDate.toString()); + } } else { if ("source.itemId".equals(propertyName)) { tuple.put("fieldName", "cdp_sourceID_equals"); diff --git a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json new file mode 100644 index 000000000..664c4641b --- /dev/null +++ b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/cdpSessionEvent.json @@ -0,0 +1,24 @@ +{ + "metadata" : { + "id": "cdp_sessionEvent", + "name": "Update session", + "description" : "Update session", + "readOnly":true + }, + + "condition" : { + "type": "cdpSessionEventCondition", + "parameterValues": { + } + }, + + "actions" : [ + { + "type": "cdpSessionEventAction", + "parameterValues": { + + } + } + ] + +} diff --git a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json new file mode 100644 index 000000000..01ea63303 --- /dev/null +++ b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateConsent.json @@ -0,0 +1,20 @@ +{ + "metadata": { + "id": "updateConsent", + "name": "Update profile/persona consents", + "description": "Update profile/persona consents", + "readOnly": true + }, + "condition": { + "type": "updateConsentEventCondition", + "parameterValues": { + } + }, + "actions": [ + { + "type": "updateConsentEventAction", + "parameterValues": { + } + } + ] +} diff --git a/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json new file mode 100644 index 000000000..b25d7d7c9 --- /dev/null +++ b/graphql/cxs-impl/src/main/resources/META-INF/cxs/rules/updateLists.json @@ -0,0 +1,24 @@ +{ + "metadata" : { + "id": "updateLists", + "name": "Update profile/persona lists", + "description" : "Update profile/persona lists", + "readOnly":true + }, + + "condition" : { + "type": "updateListsEventCondition", + "parameterValues": { + } + }, + + "actions" : [ + { + "type": "updateListsEventAction", + "parameterValues": { + + } + } + ] + +} diff --git a/graphql/graphql-ui/yarn.lock b/graphql/graphql-ui/yarn.lock index ef1f31db1..67be3181f 100644 --- a/graphql/graphql-ui/yarn.lock +++ b/graphql/graphql-ui/yarn.lock @@ -4,7 +4,7 @@ "@babel/code-frame@^7.0.0": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz" integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== dependencies: "@babel/highlight" "^7.24.7" @@ -12,19 +12,19 @@ "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" "@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz#9329b4782a7d6bbd7eef57e11addf91ee3ef1e41" + resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.12.7.tgz" integrity sha512-YaxPMGs/XIWtYqrdEOZOCPsVWfEoriXopnsz3/i7apYPXQ3698UFhS6dVT1KN5qOsWmVgw/FOrmQgpRaZayGsw== "@babel/core@^7.10.4": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz#b79a2e1b9f70ed3d84bbfb6d8c4ef825f606bccd" + resolved "https://registry.npmjs.org/@babel/core/-/core-7.12.10.tgz" integrity sha512-eTAlQKq65zHfkHZV0sIVODCPGVgoo1HdBlbSLi9CqOzuZanMv2ihzY+4paiKr1mH+XmYESMAmJ/dpZ68eN6d8w== dependencies: "@babel/code-frame" "^7.10.4" @@ -45,7 +45,7 @@ "@babel/generator@^7.12.10", "@babel/generator@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz" integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== dependencies: "@babel/types" "^7.12.11" @@ -54,14 +54,14 @@ "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz" integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== dependencies: "@babel/types" "^7.12.10" "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" + resolved "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz" integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== dependencies: "@babel/helper-explode-assignable-expression" "^7.10.4" @@ -69,7 +69,7 @@ "@babel/helper-compilation-targets@^7.12.5": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" + resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz" integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== dependencies: "@babel/compat-data" "^7.12.5" @@ -79,7 +79,7 @@ "@babel/helper-create-class-features-plugin@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" + resolved "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz" integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -90,7 +90,7 @@ "@babel/helper-create-regexp-features-plugin@^7.12.1": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" + resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz" integrity sha512-idnutvQPdpbduutvi3JVfEgcVIHooQnhvhx0Nk9isOINOIGYkZea1Pk2JlJRiUnMefrlvr0vkByATBY/mB4vjQ== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -98,7 +98,7 @@ "@babel/helper-define-map@^7.10.4": version "7.10.5" - resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" + resolved "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz" integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -107,14 +107,14 @@ "@babel/helper-explode-assignable-expression@^7.10.4": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz#8006a466695c4ad86a2a5f2fb15b5f2c31ad5633" + resolved "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.12.1.tgz" integrity sha512-dmUwH8XmlrUpVqgtZ737tK88v07l840z9j3OEhCLwKTkjlvKpfqXVIZ0wpK3aeOxspwGrf/5AP5qLx4rO3w5rA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4", "@babel/helper-function-name@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" + resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz" integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== dependencies: "@babel/helper-get-function-arity" "^7.12.10" @@ -123,35 +123,35 @@ "@babel/helper-get-function-arity@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" + resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz" integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== dependencies: "@babel/types" "^7.12.10" "@babel/helper-hoist-variables@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz" integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== dependencies: "@babel/types" "^7.10.4" "@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz#aa77bd0396ec8114e5e30787efa78599d874a855" + resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz" integrity sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw== dependencies: "@babel/types" "^7.12.7" "@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.5": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz#1bfc0229f794988f76ed0a4d4e90860850b54dfb" + resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz" integrity sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA== dependencies: "@babel/types" "^7.12.5" "@babel/helper-module-transforms@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" + resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz" integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -166,19 +166,19 @@ "@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz#94ca4e306ee11a7dd6e9f42823e2ac6b49881e2d" + resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.10.tgz" integrity sha512-4tpbU0SrSTjjt65UMWSrUOPZTsgvPgGG4S8QSTNHacKzpS51IVWGDj0yCwyeZND/i+LSN2g/O63jEXEWm49sYQ== dependencies: "@babel/types" "^7.12.10" "@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" + resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" + resolved "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz" integrity sha512-9d0KQCRM8clMPcDwo8SevNs+/9a8yWVVmaE80FGJcEP8N1qToREmWEGnBn8BUlJhYRFz6fqxeRL1sl5Ogsed7A== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -187,7 +187,7 @@ "@babel/helper-replace-supers@^7.12.1": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz#ea511658fc66c7908f923106dd88e08d1997d60d" + resolved "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.11.tgz" integrity sha512-q+w1cqmhL7R0FNzth/PLLp2N+scXEK/L2AHbXUyydxp828F4FEa5WcVoqui9vFRiHDQErj9Zof8azP32uGVTRA== dependencies: "@babel/helper-member-expression-to-functions" "^7.12.7" @@ -197,43 +197,43 @@ "@babel/helper-simple-access@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" + resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz" integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-skip-transparent-expression-wrappers@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz#462dc63a7e435ade8468385c63d2b84cce4b3cbf" + resolved "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.12.1.tgz" integrity sha512-Mf5AUuhG1/OCChOJ/HcADmvcHM42WJockombn8ATJG3OnyiSxBK/Mm5x78BQWvmtXZKHgbjdGL2kin/HOLlZGA== dependencies: "@babel/types" "^7.12.1" "@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" + resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz" integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: "@babel/types" "^7.12.11" "@babel/helper-validator-identifier@^7.10.4", "@babel/helper-validator-identifier@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz" integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== "@babel/helper-validator-identifier@^7.24.7": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== "@babel/helper-validator-option@^7.12.1", "@babel/helper-validator-option@^7.12.11": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" + resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz" integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== "@babel/helper-wrap-function@^7.10.4": version "7.12.3" - resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" + resolved "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz" integrity sha512-Cvb8IuJDln3rs6tzjW3Y8UeelAOdnpB8xtQ4sme2MSZ9wOxrbThporC0y/EtE16VAtoyEfLM404Xr1e0OOp+ow== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -243,7 +243,7 @@ "@babel/helpers@^7.12.5": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" + resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz" integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== dependencies: "@babel/template" "^7.10.4" @@ -252,7 +252,7 @@ "@babel/highlight@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz" integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: "@babel/helper-validator-identifier" "^7.10.4" @@ -261,7 +261,7 @@ "@babel/highlight@^7.24.7": version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz" integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== dependencies: "@babel/helper-validator-identifier" "^7.24.7" @@ -271,12 +271,12 @@ "@babel/parser@^7.12.10", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz" integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz#04b8f24fd4532008ab4e79f788468fd5a8476566" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.12.tgz" integrity sha512-nrz9y0a4xmUrRq51bYkWJIO5SBZyG2ys2qinHsN0zHDHVsUaModrkpyWWWXfGqYQmOL3x9sQIcTNN/pBGpo09A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -285,7 +285,7 @@ "@babel/plugin-proposal-class-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz" integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" @@ -293,7 +293,7 @@ "@babel/plugin-proposal-dynamic-import@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz#43eb5c2a3487ecd98c5c8ea8b5fdb69a2749b2dc" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.1.tgz" integrity sha512-a4rhUSZFuq5W8/OO8H7BL5zspjnc1FLd9hlOxIK/f7qG4a0qsqk8uvF/ywgBA8/OmjsapjpvaEOYItfGG1qIvQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -301,7 +301,7 @@ "@babel/plugin-proposal-export-namespace-from@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz#8b9b8f376b2d88f5dd774e4d24a5cc2e3679b6d4" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.12.1.tgz" integrity sha512-6CThGf0irEkzujYS5LQcjBx8j/4aQGiVv7J9+2f7pGfxqyKh3WnmVJYW3hdrQjyksErMGBPQrCnHfOtna+WLbw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -309,7 +309,7 @@ "@babel/plugin-proposal-json-strings@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz#d45423b517714eedd5621a9dfdc03fa9f4eb241c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.12.1.tgz" integrity sha512-GoLDUi6U9ZLzlSda2Df++VSqDJg3CG+dR0+iWsv6XRw1rEq+zwt4DirM9yrxW6XWaTpmai1cWJLMfM8qQJf+yw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -317,7 +317,7 @@ "@babel/plugin-proposal-logical-assignment-operators@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz#f2c490d36e1b3c9659241034a5d2cd50263a2751" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.12.1.tgz" integrity sha512-k8ZmVv0JU+4gcUGeCDZOGd0lCIamU/sMtIiX3UWnUc5yzgq6YUGyEolNYD+MLYKfSzgECPcqetVcJP9Afe/aCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -325,7 +325,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz" integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -333,7 +333,7 @@ "@babel/plugin-proposal-numeric-separator@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz" integrity sha512-8c+uy0qmnRTeukiGsjLGy6uVs/TFjJchGXUeBqlG4VWYOdJWkhhVPdQ3uHwbmalfJwv2JsV0qffXP4asRfL2SQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -341,7 +341,7 @@ "@babel/plugin-proposal-object-rest-spread@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz#def9bd03cea0f9b72283dac0ec22d289c7691069" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.12.1.tgz" integrity sha512-s6SowJIjzlhx8o7lsFx5zmY4At6CTtDvgNQDdPzkBQucle58A6b/TTeEBYtyDgmcXjUTM+vE8YOGHZzzbc/ioA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -350,7 +350,7 @@ "@babel/plugin-proposal-optional-catch-binding@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz#ccc2421af64d3aae50b558a71cede929a5ab2942" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.12.1.tgz" integrity sha512-hFvIjgprh9mMw5v42sJWLI1lzU5L2sznP805zeT6rySVRA0Y18StRhDqhSxlap0oVgItRsB6WSROp4YnJTJz0g== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -358,7 +358,7 @@ "@babel/plugin-proposal-optional-chaining@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz" integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -367,7 +367,7 @@ "@babel/plugin-proposal-private-methods@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz" integrity sha512-mwZ1phvH7/NHK6Kf8LP7MYDogGV+DKB1mryFOEwx5EBNQrosvIczzZFTUmWaeujd5xT6G1ELYWUz3CutMhjE1w== dependencies: "@babel/helper-create-class-features-plugin" "^7.12.1" @@ -375,7 +375,7 @@ "@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz" integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -383,105 +383,105 @@ "@babel/plugin-syntax-async-generators@^7.8.0": version "7.8.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-class-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz#bcb297c5366e79bebadef509549cd93b04f19978" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.1.tgz" integrity sha512-U40A76x5gTwmESz+qiqssqmeEsKvcSyvtgktrm0uzcARAmM9I1jR221f6Oq+GmHrcD+LvZDag1UTOTe2fL3TeA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-dynamic-import@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz" integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz" integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== dependencies: "@babel/helper-plugin-utils" "^7.8.3" "@babel/plugin-syntax-json-strings@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-jsx@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz#9d9d357cc818aa7ae7935917c1257f67677a0926" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.1.tgz" integrity sha512-1yRi7yAtB0ETgxdY9ti/p2TivUxJkTdhu/ZbF9MshVGqOx1TdB3b7xCXs49Fupgg50N45KcAsRP/ZqWjs9SRjg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-numeric-separator@^7.10.4": version "7.10.4" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-object-rest-spread@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-catch-binding@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-optional-chaining@^7.8.0": version "7.8.3" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" "@babel/plugin-syntax-top-level-await@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz#dd6c0b357ac1bb142d98537450a319625d13d2a0" + resolved "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.1.tgz" integrity sha512-i7ooMZFS+a/Om0crxZodrTzNEPJHZrlMVGMTEpFAj6rYY/bKCddB0Dk/YxfPuYXOopuhKk/e1jV6h+WUU9XN3A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-arrow-functions@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz#8083ffc86ac8e777fbe24b5967c4b2521f3cb2b3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.12.1.tgz" integrity sha512-5QB50qyN44fzzz4/qxDPQMBCTHgxg3n0xRBLJUmBlLoU/sFvxVWGZF/ZUfMVDQuJUKXaBhbupxIzIfZ6Fwk/0A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-async-to-generator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz#3849a49cc2a22e9743cbd6b52926d30337229af1" + resolved "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.12.1.tgz" integrity sha512-SDtqoEcarK1DFlRJ1hHRY5HvJUj5kX4qmtpMAm2QnhOlyuMC4TMdCRgW6WXpv93rZeYNeLP22y8Aq2dbcDRM1A== dependencies: "@babel/helper-module-imports" "^7.12.1" @@ -490,21 +490,21 @@ "@babel/plugin-transform-block-scoped-functions@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz#f2a1a365bde2b7112e0a6ded9067fdd7c07905d9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.12.1.tgz" integrity sha512-5OpxfuYnSgPalRpo8EWGPzIYf0lHBWORCkj5M0oLBwHdlux9Ri36QqGW3/LR13RSVOAoUUMzoPI/jpE4ABcHoA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-block-scoping@^7.12.11": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz#d93a567a152c22aea3b1929bb118d1d0a175cdca" + resolved "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.12.12.tgz" integrity sha512-VOEPQ/ExOVqbukuP7BYJtI5ZxxsmegTwzZ04j1aF0dkSypGo9XpDHuOrABsJu+ie+penpSJheDJ11x1BEZNiyQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-classes@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz#65e650fcaddd3d88ddce67c0f834a3d436a32db6" + resolved "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.12.1.tgz" integrity sha512-/74xkA7bVdzQTBeSUhLLJgYIcxw/dpEpCdRDiHgPJ3Mv6uC11UhjpOhl72CgqbBCmt1qtssCyB2xnJm1+PFjog== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -518,21 +518,21 @@ "@babel/plugin-transform-computed-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz#d68cf6c9b7f838a8a4144badbe97541ea0904852" + resolved "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.12.1.tgz" integrity sha512-vVUOYpPWB7BkgUWPo4C44mUQHpTZXakEqFjbv8rQMg7TC6S6ZhGZ3otQcRH6u7+adSlE5i0sp63eMC/XGffrzg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-destructuring@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz#b9a570fe0d0a8d460116413cb4f97e8e08b2f847" + resolved "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.12.1.tgz" integrity sha512-fRMYFKuzi/rSiYb2uRLiUENJOKq4Gnl+6qOv5f8z0TZXg3llUwUhsNNwrwaT/6dUhJTzNpBr+CUvEWBtfNY1cw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" + resolved "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz" integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -540,14 +540,14 @@ "@babel/plugin-transform-duplicate-keys@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" + resolved "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz" integrity sha512-iRght0T0HztAb/CazveUpUQrZY+aGKKaWXMJ4uf9YJtqxSUe09j3wteztCUDRHs+SRAL7yMuFqUsLoAKKzgXjw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-exponentiation-operator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz#b0f2ed356ba1be1428ecaf128ff8a24f02830ae0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.12.1.tgz" integrity sha512-7tqwy2bv48q+c1EHbXK0Zx3KXd2RVQp6OC7PbwFNt/dPTAV3Lu5sWtWuAj8owr5wqtWnqHfl2/mJlUmqkChKug== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" @@ -555,14 +555,14 @@ "@babel/plugin-transform-for-of@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" + resolved "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz" integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-function-name@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz#2ec76258c70fe08c6d7da154003a480620eba667" + resolved "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.12.1.tgz" integrity sha512-JF3UgJUILoFrFMEnOJLJkRHSk6LUSXLmEFsA23aR2O5CSLUxbeUX1IZ1YQ7Sn0aXb601Ncwjx73a+FVqgcljVw== dependencies: "@babel/helper-function-name" "^7.10.4" @@ -570,21 +570,21 @@ "@babel/plugin-transform-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz#d73b803a26b37017ddf9d3bb8f4dc58bfb806f57" + resolved "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.12.1.tgz" integrity sha512-+PxVGA+2Ag6uGgL0A5f+9rklOnnMccwEBzwYFL3EUaKuiyVnUipyXncFcfjSkbimLrODoqki1U9XxZzTvfN7IQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-member-expression-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz#496038602daf1514a64d43d8e17cbb2755e0c3ad" + resolved "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.12.1.tgz" integrity sha512-1sxePl6z9ad0gFMB9KqmYofk34flq62aqMt9NqliS/7hPEpURUCMbyHXrMPlo282iY7nAvUB1aQd5mg79UD9Jg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-modules-amd@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz#3154300b026185666eebb0c0ed7f8415fefcf6f9" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.12.1.tgz" integrity sha512-tDW8hMkzad5oDtzsB70HIQQRBiTKrhfgwC/KkJeGsaNFTdWhKNt/BiE8c5yj19XiGyrxpbkOfH87qkNg1YGlOQ== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -593,7 +593,7 @@ "@babel/plugin-transform-modules-commonjs@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz" integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -603,7 +603,7 @@ "@babel/plugin-transform-modules-systemjs@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz#663fea620d593c93f214a464cd399bf6dc683086" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.12.1.tgz" integrity sha512-Hn7cVvOavVh8yvW6fLwveFqSnd7rbQN3zJvoPNyNaQSvgfKmDBO9U1YL9+PCXGRlZD9tNdWTy5ACKqMuzyn32Q== dependencies: "@babel/helper-hoist-variables" "^7.10.4" @@ -614,7 +614,7 @@ "@babel/plugin-transform-modules-umd@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz#eb5a218d6b1c68f3d6217b8fa2cc82fec6547902" + resolved "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.12.1.tgz" integrity sha512-aEIubCS0KHKM0zUos5fIoQm+AZUMt1ZvMpqz0/H5qAQ7vWylr9+PLYurT+Ic7ID/bKLd4q8hDovaG3Zch2uz5Q== dependencies: "@babel/helper-module-transforms" "^7.12.1" @@ -622,21 +622,21 @@ "@babel/plugin-transform-named-capturing-groups-regex@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz#b407f5c96be0d9f5f88467497fa82b30ac3e8753" + resolved "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.12.1.tgz" integrity sha512-tB43uQ62RHcoDp9v2Nsf+dSM8sbNodbEicbQNA53zHz8pWUhsgHSJCGpt7daXxRydjb0KnfmB+ChXOv3oADp1Q== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/plugin-transform-new-target@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz#80073f02ee1bb2d365c3416490e085c95759dec0" + resolved "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.12.1.tgz" integrity sha512-+eW/VLcUL5L9IvJH7rT1sT0CzkdUTvPrXC2PXTn/7z7tXLBuKvezYbGdxD5WMRoyvyaujOq2fWoKl869heKjhw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-object-super@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz#4ea08696b8d2e65841d0c7706482b048bed1066e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.12.1.tgz" integrity sha512-AvypiGJH9hsquNUn+RXVcBdeE3KHPZexWRdimhuV59cSoOt5kFBmqlByorAeUlGG2CJWd0U+4ZtNKga/TB0cAw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -644,35 +644,35 @@ "@babel/plugin-transform-parameters@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz#d2e963b038771650c922eff593799c96d853255d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.12.1.tgz" integrity sha512-xq9C5EQhdPK23ZeCdMxl8bbRnAgHFrw5EOC3KJUsSylZqdkCaFEXxGSBuTSObOpiiHHNyb82es8M1QYgfQGfNg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-property-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz#41bc81200d730abb4456ab8b3fbd5537b59adecd" + resolved "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.12.1.tgz" integrity sha512-6MTCR/mZ1MQS+AwZLplX4cEySjCpnIF26ToWo942nqn8hXSm7McaHQNeGx/pt7suI1TWOWMfa/NgBhiqSnX0cQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-display-name@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz#1cbcd0c3b1d6648c55374a22fc9b6b7e5341c00d" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.12.1.tgz" integrity sha512-cAzB+UzBIrekfYxyLlFqf/OagTvHLcVBb5vpouzkYkBclRPraiygVnafvAoipErZLI8ANv8Ecn6E/m5qPXD26w== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-react-jsx-development@^7.12.7": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz#bccca33108fe99d95d7f9e82046bfe762e71f4e7" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.12.tgz" integrity sha512-i1AxnKxHeMxUaWVXQOSIco4tvVvvCxMSfeBMnMM06mpaJt3g+MpxYQQrDfojUQldP1xxraPSJYSMEljoWM/dCg== dependencies: "@babel/plugin-transform-react-jsx" "^7.12.12" "@babel/plugin-transform-react-jsx@^7.12.10", "@babel/plugin-transform-react-jsx@^7.12.12": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz#b0da51ffe5f34b9a900e9f1f5fb814f9e512d25e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.12.tgz" integrity sha512-JDWGuzGNWscYcq8oJVCtSE61a5+XAOos+V0HrxnDieUus4UMnBEosDnY1VJqU5iZ4pA04QY7l0+JvHL1hZEfsw== dependencies: "@babel/helper-annotate-as-pure" "^7.12.10" @@ -683,7 +683,7 @@ "@babel/plugin-transform-react-pure-annotations@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz#05d46f0ab4d1339ac59adf20a1462c91b37a1a42" + resolved "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.12.1.tgz" integrity sha512-RqeaHiwZtphSIUZ5I85PEH19LOSzxfuEazoY7/pWASCAIBuATQzpSVD+eT6MebeeZT2F4eSL0u4vw6n4Nm0Mjg== dependencies: "@babel/helper-annotate-as-pure" "^7.10.4" @@ -691,28 +691,28 @@ "@babel/plugin-transform-regenerator@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz#5f0a28d842f6462281f06a964e88ba8d7ab49753" + resolved "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.12.1.tgz" integrity sha512-gYrHqs5itw6i4PflFX3OdBPMQdPbF4bj2REIUxlMRUFk0/ZOAIpDFuViuxPjUL7YC8UPnf+XG7/utJvqXdPKng== dependencies: regenerator-transform "^0.14.2" "@babel/plugin-transform-reserved-words@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz#6fdfc8cc7edcc42b36a7c12188c6787c873adcd8" + resolved "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.12.1.tgz" integrity sha512-pOnUfhyPKvZpVyBHhSBoX8vfA09b7r00Pmm1sH+29ae2hMTKVmSp4Ztsr8KBKjLjx17H0eJqaRC3bR2iThM54A== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-shorthand-properties@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz#0bf9cac5550fce0cfdf043420f661d645fdc75e3" + resolved "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.12.1.tgz" integrity sha512-GFZS3c/MhX1OusqB1MZ1ct2xRzX5ppQh2JU1h2Pnfk88HtFTM+TWQqJNfwkmxtPQtb/s1tk87oENfXJlx7rSDw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-spread@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz#527f9f311be4ec7fdc2b79bb89f7bf884b3e1e1e" + resolved "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.12.1.tgz" integrity sha512-vuLp8CP0BE18zVYjsEBZ5xoCecMK6LBMMxYzJnh01rxQRvhNhH1csMMmBfNo5tGpGO+NhdSNW2mzIvBu3K1fng== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -720,35 +720,35 @@ "@babel/plugin-transform-sticky-regex@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz#560224613ab23987453948ed21d0b0b193fa7fad" + resolved "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.12.7.tgz" integrity sha512-VEiqZL5N/QvDbdjfYQBhruN0HYjSPjC4XkeqW4ny/jNtH9gcbgaqBIXYEZCNnESMAGs0/K/R7oFGMhOyu/eIxg== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-template-literals@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz#b43ece6ed9a79c0c71119f576d299ef09d942843" + resolved "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.12.1.tgz" integrity sha512-b4Zx3KHi+taXB1dVRBhVJtEPi9h1THCeKmae2qP0YdUHIFhVjtpqqNfxeVAa1xeHVhAy4SbHxEwx5cltAu5apw== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-typeof-symbol@^7.12.10": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz#de01c4c8f96580bd00f183072b0d0ecdcf0dec4b" + resolved "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.12.10.tgz" integrity sha512-JQ6H8Rnsogh//ijxspCjc21YPd3VLVoYtAwv3zQmqAt8YGYUtdo5usNhdl4b9/Vir2kPFZl6n1h0PfUz4hJhaA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-escapes@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz#5232b9f81ccb07070b7c3c36c67a1b78f1845709" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.12.1.tgz" integrity sha512-I8gNHJLIc7GdApm7wkVnStWssPNbSRMPtgHdmH3sRM1zopz09UWPS4x5V4n1yz/MIWTVnJ9sp6IkuXdWM4w+2Q== dependencies: "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-unicode-regex@^7.12.1": version "7.12.1" - resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz#cc9661f61390db5c65e3febaccefd5c6ac3faecb" + resolved "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.12.1.tgz" integrity sha512-SqH4ClNngh/zGwHZOOQMTD+e8FGWexILV+ePMyiDJttAWRh5dhDL8rcl5lSgU3Huiq6Zn6pWTMvdPAb21Dwdyg== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.12.1" @@ -756,7 +756,7 @@ "@babel/preset-env@^7.10.4": version "7.12.11" - resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz#55d5f7981487365c93dbbc84507b1c7215e857f9" + resolved "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.12.11.tgz" integrity sha512-j8Tb+KKIXKYlDBQyIOy4BLxzv1NUOwlHfZ74rvW+Z0Gp4/cI2IMDPBWAgWceGcE7aep9oL/0K9mlzlMGxA8yNw== dependencies: "@babel/compat-data" "^7.12.7" @@ -828,7 +828,7 @@ "@babel/preset-modules@^0.1.3": version "0.1.4" - resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" + resolved "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz" integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== dependencies: "@babel/helper-plugin-utils" "^7.0.0" @@ -839,7 +839,7 @@ "@babel/preset-react@^7.10.4": version "7.12.10" - resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz#4fed65f296cbb0f5fb09de6be8cddc85cc909be9" + resolved "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.10.tgz" integrity sha512-vtQNjaHRl4DUpp+t+g4wvTHsLQuye+n0H/wsXIZRn69oz/fvNC7gQ4IK73zGJBaxvHoxElDvnYCthMcT7uzFoQ== dependencies: "@babel/helper-plugin-utils" "^7.10.4" @@ -850,14 +850,14 @@ "@babel/runtime@^7.8.4": version "7.12.5" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz" integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== dependencies: regenerator-runtime "^0.13.4" "@babel/template@^7.10.4", "@babel/template@^7.12.7": version "7.12.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + resolved "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz" integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== dependencies: "@babel/code-frame" "^7.10.4" @@ -866,7 +866,7 @@ "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.10", "@babel/traverse@^7.12.5": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" + resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz" integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== dependencies: "@babel/code-frame" "^7.12.11" @@ -881,7 +881,7 @@ "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4": version "7.12.12" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + resolved "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz" integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== dependencies: "@babel/helper-validator-identifier" "^7.12.11" @@ -890,31 +890,31 @@ "@discoveryjs/json-ext@^0.5.0": version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" + resolved "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== "@emotion/is-prop-valid@^0.8.2": version "0.8.8" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" + resolved "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz" integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== dependencies: "@emotion/memoize" "0.7.4" "@emotion/memoize@0.7.4": version "0.7.4" - resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz" integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== "@floating-ui/core@^1.0.0": version "1.6.2" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a" + resolved "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.2.tgz" integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg== dependencies: "@floating-ui/utils" "^0.2.0" "@floating-ui/dom@^1.0.0": version "1.6.5" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" + resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.5.tgz" integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== dependencies: "@floating-ui/core" "^1.0.0" @@ -922,19 +922,19 @@ "@floating-ui/react-dom@^2.0.0": version "2.1.0" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.0.tgz#4f0e5e9920137874b2405f7d6c862873baf4beff" + resolved "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.0.tgz" integrity sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA== dependencies: "@floating-ui/dom" "^1.0.0" "@floating-ui/utils@^0.2.0": version "0.2.2" - resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" + resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz" integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== "@graphiql/react@0.22.3", "@graphiql/react@^0.22.3": version "0.22.3" - resolved "https://registry.yarnpkg.com/@graphiql/react/-/react-0.22.3.tgz#aa0cd4260ad8e98dc00e0fc9c54cb1b3e227d980" + resolved "https://registry.npmjs.org/@graphiql/react/-/react-0.22.3.tgz" integrity sha512-rZGs0BbJ4ImFy6l489aXUEB3HzGVoD7hI8CycydNRXR6+qYgp/fuNFCXMJe+q9gDyC/XhBXni8Pdugk8HxJ05g== dependencies: "@graphiql/toolkit" "^0.9.1" @@ -955,7 +955,7 @@ "@graphiql/toolkit@^0.9.1": version "0.9.1" - resolved "https://registry.yarnpkg.com/@graphiql/toolkit/-/toolkit-0.9.1.tgz#44bfa83aed79c8c18affac49efbb81f8e87bade3" + resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.9.1.tgz" integrity sha512-LVt9pdk0830so50ZnU2Znb2rclcoWznG8r8asqAENzV0U1FM1kuY0sdPpc/rBc9MmmNgnB6A+WZzDhq6dbhTHA== dependencies: "@n1ru4l/push-pull-async-iterable-iterator" "^3.1.0" @@ -963,7 +963,7 @@ "@headlessui/react@^1.7.15": version "1.7.19" - resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40" + resolved "https://registry.npmjs.org/@headlessui/react/-/react-1.7.19.tgz" integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw== dependencies: "@tanstack/react-virtual" "^3.0.0-beta.60" @@ -971,17 +971,17 @@ "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== "@jridgewell/trace-mapping@^0.3.20": version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" @@ -989,7 +989,7 @@ "@motionone/animation@^10.12.0": version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.18.0.tgz#868d00b447191816d5d5cf24b1cafa144017922b" + resolved "https://registry.npmjs.org/@motionone/animation/-/animation-10.18.0.tgz" integrity sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw== dependencies: "@motionone/easing" "^10.18.0" @@ -999,7 +999,7 @@ "@motionone/dom@10.12.0": version "10.12.0" - resolved "https://registry.yarnpkg.com/@motionone/dom/-/dom-10.12.0.tgz#ae30827fd53219efca4e1150a5ff2165c28351ed" + resolved "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz" integrity sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw== dependencies: "@motionone/animation" "^10.12.0" @@ -1011,7 +1011,7 @@ "@motionone/easing@^10.18.0": version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/easing/-/easing-10.18.0.tgz#7b82f6010dfee3a1bb0ee83abfbaff6edae0c708" + resolved "https://registry.npmjs.org/@motionone/easing/-/easing-10.18.0.tgz" integrity sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg== dependencies: "@motionone/utils" "^10.18.0" @@ -1019,7 +1019,7 @@ "@motionone/generators@^10.12.0": version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/generators/-/generators-10.18.0.tgz#fe09ab5cfa0fb9a8884097feb7eb60abeb600762" + resolved "https://registry.npmjs.org/@motionone/generators/-/generators-10.18.0.tgz" integrity sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg== dependencies: "@motionone/types" "^10.17.1" @@ -1028,12 +1028,12 @@ "@motionone/types@^10.12.0", "@motionone/types@^10.17.1": version "10.17.1" - resolved "https://registry.yarnpkg.com/@motionone/types/-/types-10.17.1.tgz#cf487badbbdc9da0c2cb86ffc1e5d11147c6e6fb" + resolved "https://registry.npmjs.org/@motionone/types/-/types-10.17.1.tgz" integrity sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A== "@motionone/utils@^10.12.0", "@motionone/utils@^10.18.0": version "10.18.0" - resolved "https://registry.yarnpkg.com/@motionone/utils/-/utils-10.18.0.tgz#a59ff8932ed9009624bca07c56b28ef2bb2f885e" + resolved "https://registry.npmjs.org/@motionone/utils/-/utils-10.18.0.tgz" integrity sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw== dependencies: "@motionone/types" "^10.17.1" @@ -1042,24 +1042,24 @@ "@n1ru4l/push-pull-async-iterable-iterator@^3.1.0": version "3.2.0" - resolved "https://registry.yarnpkg.com/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz#c15791112db68dd9315d329d652b7e797f737655" + resolved "https://registry.npmjs.org/@n1ru4l/push-pull-async-iterable-iterator/-/push-pull-async-iterable-iterator-3.2.0.tgz" integrity sha512-3fkKj25kEjsfObL6IlKPAlHYPq/oYwUkkQ03zsTTiDjD7vg/RxjdiLeCydqtxHZP0JgsXL3D/X5oAkMGzuUp/Q== "@radix-ui/primitive@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + resolved "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz" integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== "@radix-ui/react-arrow@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a" + resolved "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz" integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw== dependencies: "@radix-ui/react-primitive" "2.0.0" "@radix-ui/react-collection@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" + resolved "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz" integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== dependencies: "@radix-ui/react-compose-refs" "1.1.0" @@ -1069,17 +1069,17 @@ "@radix-ui/react-compose-refs@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + resolved "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz" integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== "@radix-ui/react-context@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + resolved "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz" integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== "@radix-ui/react-dialog@^1.0.4": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.0.tgz#9d354a8c7f534d49fffd2544fb7b371cb49da71c" + resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.0.tgz" integrity sha512-oiSJcsjbdC8JqbXrOuhOd7oaEaPp3x2L2zn6V7ie6SSpEjrAha/WabDX4po6laGwbhAu9DT0XxHL0DmcIXrR0A== dependencies: "@radix-ui/primitive" "1.1.0" @@ -1099,12 +1099,12 @@ "@radix-ui/react-direction@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + resolved "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz" integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== "@radix-ui/react-dismissable-layer@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz#2cd0a49a732372513733754e6032d3fb7988834e" + resolved "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz" integrity sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig== dependencies: "@radix-ui/primitive" "1.1.0" @@ -1115,7 +1115,7 @@ "@radix-ui/react-dropdown-menu@^2.0.5": version "2.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.0.tgz#9e4693f3b300cd54e553a486ddd7a5df355b78ba" + resolved "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.0.tgz" integrity sha512-8fAz27yxVaYTkXMm5dVOcKCHOiio9b4nl7rO1HmK8rpzcEl0kSSmwFQsYDyJxB/Em48PvXTez/iaBj3VEd2N4g== dependencies: "@radix-ui/primitive" "1.1.0" @@ -1128,12 +1128,12 @@ "@radix-ui/react-focus-guards@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13" + resolved "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz" integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw== "@radix-ui/react-focus-scope@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz#ebe2891a298e0a33ad34daab2aad8dea31caf0b2" + resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz" integrity sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA== dependencies: "@radix-ui/react-compose-refs" "1.1.0" @@ -1142,14 +1142,14 @@ "@radix-ui/react-id@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + resolved "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz" integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== dependencies: "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-menu@2.1.0": version "2.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.0.tgz#383d078f3e3708f4134e2d61a66c39b40c41c99c" + resolved "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.0.tgz" integrity sha512-0AxIUQJpimipHDgTVISZbdOY+wZzgICKAsqfI1rF2Hp0Jh3YSv9e9J1tYYyurPBONe5vKi3hZPtVt2E85Sac7A== dependencies: "@radix-ui/primitive" "1.1.0" @@ -1173,7 +1173,7 @@ "@radix-ui/react-popper@1.2.0": version "1.2.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a" + resolved "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz" integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg== dependencies: "@floating-ui/react-dom" "^2.0.0" @@ -1189,14 +1189,14 @@ "@radix-ui/react-portal@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.0.tgz#7d8591034d85478c172a91b1b879df8cf8b60bf0" + resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.0.tgz" integrity sha512-0tXZ5O6qAVvuN9SWP0X+zadHf9hzHiMf/vxOU+kXO+fbtS8lS57MXa6EmikDxk9s/Bmkk80+dcxgbvisIyeqxg== dependencies: "@radix-ui/react-primitive" "2.0.0" "@radix-ui/react-presence@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz" integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== dependencies: "@radix-ui/react-compose-refs" "1.1.0" @@ -1204,14 +1204,14 @@ "@radix-ui/react-primitive@2.0.0": version "2.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz" integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== dependencies: "@radix-ui/react-slot" "1.1.0" "@radix-ui/react-roving-focus@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" + resolved "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz" integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== dependencies: "@radix-ui/primitive" "1.1.0" @@ -1226,14 +1226,14 @@ "@radix-ui/react-slot@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + resolved "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz" integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== dependencies: "@radix-ui/react-compose-refs" "1.1.0" "@radix-ui/react-tooltip@^1.0.6": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.0.tgz#861c268b9c73472a32a312dbc0135ea581262ca6" + resolved "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.0.tgz" integrity sha512-DZZvEn5WUJyd9+JzVT/cTjt7m0rymjxpzJZMmb09lCWo8kRqOp4rsckFrGgocD5cR8e3gtaNINvWWqFMccvV/w== dependencies: "@radix-ui/primitive" "1.1.0" @@ -1251,83 +1251,83 @@ "@radix-ui/react-use-callback-ref@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + resolved "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz" integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== "@radix-ui/react-use-controllable-state@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + resolved "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz" integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== dependencies: "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-escape-keydown@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + resolved "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz" integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== dependencies: "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + resolved "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz" integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== "@radix-ui/react-use-rect@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + resolved "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz" integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== dependencies: "@radix-ui/rect" "1.1.0" "@radix-ui/react-use-size@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + resolved "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz" integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== dependencies: "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-visually-hidden@1.1.0", "@radix-ui/react-visually-hidden@^1.0.3": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2" + resolved "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz" integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ== dependencies: "@radix-ui/react-primitive" "2.0.0" "@radix-ui/rect@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + resolved "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz" integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== "@tanstack/react-virtual@^3.0.0-beta.60": version "3.5.1" - resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.5.1.tgz#1ce466f530a10f781871360ed2bf7ff83e664f85" + resolved "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.5.1.tgz" integrity sha512-jIsuhfgy8GqA67PdWqg73ZB2LFE+HD9hjWL1L6ifEIZVyZVAKpYmgUG4WsKQ005aEyImJmbuimPiEvc57IY0Aw== dependencies: "@tanstack/virtual-core" "3.5.1" "@tanstack/virtual-core@3.5.1": version "3.5.1" - resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.5.1.tgz#f519149bce9156d0e7954b9531df15f446f2fc12" + resolved "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.5.1.tgz" integrity sha512-046+AUSiDru/V9pajE1du8WayvBKeCvJ2NmKPy/mR8/SbKKrqmSbj7LJBfXE+nSq4f5TBXvnCzu0kcYebI9WdQ== "@types/codemirror@^0.0.90": version "0.0.90" - resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.90.tgz#9c5edafce2a780b4f8bc5e3b699fe1f4727c8f17" + resolved "https://registry.npmjs.org/@types/codemirror/-/codemirror-0.0.90.tgz" integrity sha512-8Z9+tSg27NPRGubbUPUCrt5DDG/OWzLph5BvcDykwR5D7RyZh5mhHG0uS1ePKV1YFCA+/cwc4Ey2AJAEFfV3IA== dependencies: "@types/tern" "*" "@types/codemirror@^5.60.8": version "5.60.15" - resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.15.tgz#0f82be6f4126d1e59cf4c4830e56dcd49d3c3e8a" + resolved "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.15.tgz" integrity sha512-dTOvwEQ+ouKJ/rE9LT1Ue2hmP6H1mZv5+CCnNWu2qtiOe2LQa9lCprEY20HxiDmV/Bxh+dXjywmy5aKvoGjULA== dependencies: "@types/tern" "*" "@types/eslint-scope@^3.7.3": version "3.7.7" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" + resolved "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz" integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== dependencies: "@types/eslint" "*" @@ -1335,7 +1335,7 @@ "@types/eslint@*": version "8.56.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" + resolved "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz" integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== dependencies: "@types/estree" "*" @@ -1343,36 +1343,36 @@ "@types/estree@*", "@types/estree@^1.0.5": version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6": version "7.0.7" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" + resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== "@types/node@*": version "20.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.6.tgz#f3c19ffc98c2220e18de259bb172dd4d892a6075" + resolved "https://registry.npmjs.org/@types/node/-/node-20.14.6.tgz" integrity sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw== dependencies: undici-types "~5.26.4" "@types/tern@*": version "0.23.9" - resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.9.tgz#6f6093a4a9af3e6bb8dde528e024924d196b367c" + resolved "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz" integrity sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw== dependencies: "@types/estree" "*" "@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz" integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: "@webassemblyjs/helper-numbers" "1.11.6" @@ -1380,22 +1380,22 @@ "@webassemblyjs/floating-point-hex-parser@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + resolved "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz" integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== "@webassemblyjs/helper-api-error@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz" integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== "@webassemblyjs/helper-buffer@1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz" integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== "@webassemblyjs/helper-numbers@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz" integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: "@webassemblyjs/floating-point-hex-parser" "1.11.6" @@ -1404,12 +1404,12 @@ "@webassemblyjs/helper-wasm-bytecode@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz" integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== "@webassemblyjs/helper-wasm-section@1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + resolved "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz" integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: "@webassemblyjs/ast" "1.12.1" @@ -1419,26 +1419,26 @@ "@webassemblyjs/ieee754@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + resolved "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz" integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" "@webassemblyjs/leb128@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + resolved "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz" integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" "@webassemblyjs/utf8@1.11.6": version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + resolved "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz" integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== "@webassemblyjs/wasm-edit@^1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz" integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== dependencies: "@webassemblyjs/ast" "1.12.1" @@ -1452,7 +1452,7 @@ "@webassemblyjs/wasm-gen@1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz" integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== dependencies: "@webassemblyjs/ast" "1.12.1" @@ -1463,7 +1463,7 @@ "@webassemblyjs/wasm-opt@1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz" integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== dependencies: "@webassemblyjs/ast" "1.12.1" @@ -1473,7 +1473,7 @@ "@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz" integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== dependencies: "@webassemblyjs/ast" "1.12.1" @@ -1485,7 +1485,7 @@ "@webassemblyjs/wast-printer@1.12.1": version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + resolved "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz" integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== dependencies: "@webassemblyjs/ast" "1.12.1" @@ -1493,61 +1493,61 @@ "@webpack-cli/configtest@^2.1.1": version "2.1.1" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-2.1.1.tgz#3b2f852e91dac6e3b85fb2a314fb8bef46d94646" + resolved "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz" integrity sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw== "@webpack-cli/info@^2.0.2": version "2.0.2" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-2.0.2.tgz#cc3fbf22efeb88ff62310cf885c5b09f44ae0fdd" + resolved "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz" integrity sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A== "@webpack-cli/serve@^2.0.5": version "2.0.5" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e" + resolved "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz" integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ== "@xtuc/ieee754@^1.2.0": version "1.2.0" - resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + resolved "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz" integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== "@xtuc/long@4.2.2": version "4.2.2" - resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + resolved "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== acorn-import-attributes@^1.9.5: version "1.9.5" - resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + resolved "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz" integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn@^8.7.1: version "8.12.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz" integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== ajv-formats@^2.1.1: version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + resolved "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz" integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== dependencies: ajv "^8.0.0" ajv-keywords@^3.5.2: version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ajv-keywords@^5.1.0: version "5.1.0" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz" integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== dependencies: fast-deep-equal "^3.1.3" ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -1557,7 +1557,7 @@ ajv@^6.12.4, ajv@^6.12.5: ajv@^8.0.0, ajv@^8.9.0: version "8.16.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.16.0.tgz#22e2a92b94f005f7e0f9c9d39652ef0b8f6f0cb4" + resolved "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz" integrity sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw== dependencies: fast-deep-equal "^3.1.3" @@ -1572,26 +1572,26 @@ ansi-regex@4.1.1: ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== aria-hidden@^1.1.1: version "1.2.4" - resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" + resolved "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz" integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== dependencies: tslib "^2.0.0" babel-loader@^8.1.0: version "8.2.2" - resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz#9363ce84c10c9a40e6c753748e1441b60c8a0b81" + resolved "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz" integrity sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g== dependencies: find-cache-dir "^3.3.1" @@ -1601,19 +1601,19 @@ babel-loader@^8.1.0: babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" - resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" + resolved "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz" integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== dependencies: object.assign "^4.1.0" big.js@^5.2.2: version "5.2.2" - resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + resolved "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== browserslist@^4.14.5, browserslist@^4.16.1: version "4.16.3" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.16.3.tgz" integrity sha512-vIyhWmIkULaq04Gt93txdh+j02yX/JzlyhLYbV3YQCn/zvES3JnY7TifHHvvr1w5hTDluNKMkV05cs4vy8Q7sw== dependencies: caniuse-lite "^1.0.30001181" @@ -1624,7 +1624,7 @@ browserslist@^4.14.5, browserslist@^4.16.1: browserslist@^4.21.10: version "4.23.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.1.tgz#ce4af0534b3d37db5c1a4ca98b9080f985041e96" + resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz" integrity sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw== dependencies: caniuse-lite "^1.0.30001629" @@ -1633,13 +1633,13 @@ browserslist@^4.21.10: update-browserslist-db "^1.0.16" buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + version "1.1.2" + resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== call-bind@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== dependencies: function-bind "^1.1.1" @@ -1647,27 +1647,27 @@ call-bind@^1.0.0: callsites@^3.0.0: version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.3.1: version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== caniuse-lite@^1.0.30001181: version "1.0.30001183" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz#7a57ba9d6584119bb5f2bc76d3cc47ba9356b3e2" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001183.tgz" integrity sha512-7JkwTEE1hlRKETbCFd8HDZeLiQIUcl8rC6JgNjvHCNaxOeNmQ9V4LvQXRUsKIV2CC73qKxljwVhToaA3kLRqTw== caniuse-lite@^1.0.30001629: version "1.0.30001636" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz#b15f52d2bdb95fad32c2f53c0b68032b85188a78" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz" integrity sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg== chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -1676,19 +1676,19 @@ chalk@^2.0.0, chalk@^2.4.2: chrome-trace-event@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + resolved "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz" integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== dependencies: tslib "^1.9.0" client-only@^0.0.1: version "0.0.1" - resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== clone-deep@^4.0.1: version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + resolved "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz" integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== dependencies: is-plain-object "^2.0.4" @@ -1697,12 +1697,12 @@ clone-deep@^4.0.1: clsx@^1.2.1: version "1.2.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== codemirror-graphql@^2.0.12: version "2.0.12" - resolved "https://registry.yarnpkg.com/codemirror-graphql/-/codemirror-graphql-2.0.12.tgz#75492b41f271a64eb207c923a4a536c3134d05c9" + resolved "https://registry.npmjs.org/codemirror-graphql/-/codemirror-graphql-2.0.12.tgz" integrity sha512-5UCqhWzck1jClCmRewFb8aSiabnAqiaRfsvIPfmbf6WJvOb8oiefJeHilclPPiZBzY8v/Et6EBMtOeKnWCoyng== dependencies: "@types/codemirror" "^0.0.90" @@ -1710,70 +1710,70 @@ codemirror-graphql@^2.0.12: codemirror@^5.65.3: version "5.65.16" - resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.16.tgz#efc0661be6bf4988a6a1c2fe6893294638cdb334" + resolved "https://registry.npmjs.org/codemirror/-/codemirror-5.65.16.tgz" integrity sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg== color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= colorette@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz" integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== colorette@^2.0.14: version "2.0.20" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + resolved "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== commander@^10.0.1: version "10.0.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" + resolved "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== commander@^2.20.0: version "2.20.3" - resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + resolved "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= convert-source-map@^1.7.0: version "1.7.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== dependencies: safe-buffer "~5.1.1" copy-anything@^2.0.1: version "2.0.6" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-2.0.6.tgz#092454ea9584a7b7ad5573062b2a87f5900fc480" + resolved "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz" integrity sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw== dependencies: is-what "^3.14.1" copy-to-clipboard@^3.2.0: version "3.3.1" - resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" + resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz" integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== dependencies: toggle-selection "^1.0.6" core-js-compat@^3.8.0: version "3.8.3" - resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz#9123fb6b9cad30f0651332dc77deba48ef9b0b3f" + resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz" integrity sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog== dependencies: browserslist "^4.16.1" @@ -1781,7 +1781,7 @@ core-js-compat@^3.8.0: cosmiconfig@^8.3.5: version "8.3.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.3.6.tgz#060a2b871d66dba6c8538ea1118ba1ac16f5fae3" + resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz" integrity sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA== dependencies: import-fresh "^3.3.0" @@ -1791,7 +1791,7 @@ cosmiconfig@^8.3.5: cross-spawn@^7.0.3: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" @@ -1800,7 +1800,7 @@ cross-spawn@^7.0.3: css-loader@^3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz#2e4b2c7e6e2d27f8c8f28f61bffcd2e6c91ef645" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz" integrity sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ== dependencies: camelcase "^5.3.1" @@ -1819,46 +1819,46 @@ css-loader@^3.6.0: cssesc@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + resolved "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== debug@^4.1.0: version "4.3.1" - resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: ms "2.1.2" define-properties@^1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" detect-node-es@^1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + resolved "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz" integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== electron-to-chromium@^1.3.649: version "1.3.650" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.650.tgz#24e821fff2ed61fd71fee092f2a0631b3c0c22a6" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.650.tgz" integrity sha512-j6pRuNylFBbroG6NB8Lw/Im9oDY74s2zWHBP5TmdYg73cBuL6cz//SMgolVa0gIJk/DSL+kO7baJ1DSXW1FUZg== electron-to-chromium@^1.4.796: version "1.4.807" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.807.tgz#4d6c5ea1516f0164ac5bfd487ccd4ee9507c8f01" + resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.807.tgz" integrity sha512-kSmJl2ZwhNf/bcIuCH/imtNOKlpkLDn2jqT5FJ+/0CXjhnFaOa9cOe9gHKKy71eM49izwuQjZhKk+lWQ1JxB7A== emojis-list@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" + resolved "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== enhanced-resolve@^5.17.0: version "5.17.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" + resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz" integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== dependencies: graceful-fs "^4.2.4" @@ -1866,51 +1866,51 @@ enhanced-resolve@^5.17.0: entities@^4.4.0: version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== envinfo@^7.7.3: version "7.13.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" + resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz" integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== errno@^0.1.1: version "0.1.8" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" + resolved "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz" integrity sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A== dependencies: prr "~1.0.1" error-ex@^1.3.1: version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== dependencies: is-arrayish "^0.2.1" es-module-lexer@^1.2.1: version "1.5.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz#25969419de9c0b1fbe54279789023e8a9a788412" + resolved "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.3.tgz" integrity sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg== escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escalade@^3.1.2: version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= eslint-scope@5.1.1: version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -1918,49 +1918,49 @@ eslint-scope@5.1.1: esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== events@^3.2.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + resolved "https://registry.npmjs.org/events/-/events-3.3.0.tgz" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fastest-levenshtein@^1.0.12: version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + resolved "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== file-loader@^6.0.0: version "6.2.0" - resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" + resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== dependencies: loader-utils "^2.0.0" @@ -1968,7 +1968,7 @@ file-loader@^6.0.0: find-cache-dir@^3.3.1: version "3.3.1" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== dependencies: commondir "^1.0.1" @@ -1977,7 +1977,7 @@ find-cache-dir@^3.3.1: find-up@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1985,12 +1985,12 @@ find-up@^4.0.0: flat@^5.0.2: version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== framer-motion@^6.5.1: version "6.5.1" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-6.5.1.tgz#802448a16a6eb764124bf36d8cbdfa6dd6b931a7" + resolved "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz" integrity sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw== dependencies: "@motionone/dom" "10.12.0" @@ -2004,29 +2004,29 @@ framer-motion@^6.5.1: framesync@6.0.1: version "6.0.1" - resolved "https://registry.yarnpkg.com/framesync/-/framesync-6.0.1.tgz#5e32fc01f1c42b39c654c35b16440e07a25d6f20" + resolved "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz" integrity sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA== dependencies: tslib "^2.1.0" function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== function-bind@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== gensync@^1.0.0-beta.1: version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-intrinsic@^1.0.2: version "1.1.0" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz#892e62931e6938c8a23ea5aaebcfb67bd97da97e" + resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz" integrity sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg== dependencies: function-bind "^1.1.1" @@ -2035,32 +2035,32 @@ get-intrinsic@^1.0.2: get-nonce@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + resolved "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== glob-to-regexp@^0.4.1: version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" + resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== globals@^11.1.0: version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== graceful-fs@^4.1.2: version "4.2.4" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== graphiql@^3.3.1: version "3.3.1" - resolved "https://registry.yarnpkg.com/graphiql/-/graphiql-3.3.1.tgz#60fc405c56492792c60d107c1f191aa6cf244034" + resolved "https://registry.npmjs.org/graphiql/-/graphiql-3.3.1.tgz" integrity sha512-UA29FQ418Pcxat54CvM//S5G+7DKG7XQ7s9UyAEdb7zMAKPANIDd222XEYNxG2I/FgAxsiq3ZTBpxwvPbB9Mcw== dependencies: "@graphiql/react" "^0.22.3" @@ -2070,7 +2070,7 @@ graphiql@^3.3.1: graphql-language-service@5.2.1, graphql-language-service@^5.2.1: version "5.2.1" - resolved "https://registry.yarnpkg.com/graphql-language-service/-/graphql-language-service-5.2.1.tgz#8929cf93deadecc0fbb78fe8a0c55d178ffa7833" + resolved "https://registry.npmjs.org/graphql-language-service/-/graphql-language-service-5.2.1.tgz" integrity sha512-8ewD6otGO43vg2TiEGjoLz3CweTwfaf4ZnqfNREqZXS2JSJGXtsRBOMMknCxMfFVh4x14ql3jyDrXcyAAtbmkQ== dependencies: nullthrows "^1.0.0" @@ -2078,70 +2078,70 @@ graphql-language-service@5.2.1, graphql-language-service@^5.2.1: graphql-ws@^5.16.0: version "5.16.0" - resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.16.0.tgz#849efe02f384b4332109329be01d74c345842729" + resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz" integrity sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A== graphql@^16.8.2: version "16.8.2" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.2.tgz#54771c7ff195da913f5e70af8044a026d32eca2a" + resolved "https://registry.npmjs.org/graphql/-/graphql-16.8.2.tgz" integrity sha512-cvVIBILwuoSyD54U4cF/UXDh5yAobhNV/tPygI4lZhgOIJQE/WLWC4waBRb4I6bDVYb3OVx3lfHbaQOEoUD5sg== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== has-symbols@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== has@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" hasown@^2.0.0: version "2.0.2" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + resolved "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" hey-listen@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" + resolved "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz" integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== iconv-lite@^0.6.3: version "0.6.3" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" icss-utils@^4.0.0, icss-utils@^4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz" integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== dependencies: postcss "^7.0.14" image-size@~0.5.0: version "0.5.5" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" + resolved "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz" integrity sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ== import-fresh@^3.3.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -2149,7 +2149,7 @@ import-fresh@^3.3.0: import-local@^3.0.2: version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + resolved "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz" integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== dependencies: pkg-dir "^4.2.0" @@ -2157,63 +2157,63 @@ import-local@^3.0.2: indexes-of@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + resolved "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz" integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= interpret@^3.1.1: version "3.1.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" + resolved "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz" integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== invariant@^2.2.4: version "2.2.4" - resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" is-arrayish@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-core-module@^2.13.0: version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== dependencies: hasown "^2.0.0" is-plain-object@^2.0.4: version "2.0.4" - resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz" integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" is-primitive@^3.0.1: version "3.0.1" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-3.0.1.tgz#98c4db1abff185485a657fc2905052b940524d05" + resolved "https://registry.npmjs.org/is-primitive/-/is-primitive-3.0.1.tgz" integrity sha512-GljRxhWvlCNRfZyORiH77FwdFwGcMO620o37EOYC0ORWdq+WYNVqW0w2Juzew4M+L81l6/QS3t5gkkihyRqv9w== is-what@^3.14.1: version "3.14.1" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" + resolved "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz" integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + resolved "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= jest-worker@^27.4.5: version "27.5.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + resolved "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz" integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" @@ -2222,73 +2222,73 @@ jest-worker@^27.4.5: jiti@^1.20.0: version "1.21.6" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.6.tgz#6c7f7398dd4b3142767f9a168af2f317a428d268" + resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz" integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" jsesc@^2.5.1: version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== jsesc@~0.5.0: version "0.5.0" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + resolved "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-schema-traverse@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== json5@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" json5@^2.1.2: version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" kind-of@^6.0.2: version "6.0.3" - resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== less-loader@^11.1.3: version "11.1.4" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-11.1.4.tgz#e8a070844efaefbe59b978acaf57b9d3e868cf08" + resolved "https://registry.npmjs.org/less-loader/-/less-loader-11.1.4.tgz" integrity sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A== less@^4.2.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/less/-/less-4.2.0.tgz#cbefbfaa14a4cd388e2099b2b51f956e1465c450" + resolved "https://registry.npmjs.org/less/-/less-4.2.0.tgz" integrity sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA== dependencies: copy-anything "^2.0.1" @@ -2305,24 +2305,24 @@ less@^4.2.0: lines-and-columns@^1.1.6: version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + resolved "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== linkify-it@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + resolved "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz" integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== dependencies: uc.micro "^2.0.0" loader-runner@^4.2.0: version "4.3.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + resolved "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== loader-utils@^1.2.3, loader-utils@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz" integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== dependencies: big.js "^5.2.2" @@ -2331,7 +2331,7 @@ loader-utils@^1.2.3, loader-utils@^1.4.0: loader-utils@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0" + resolved "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz" integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ== dependencies: big.js "^5.2.2" @@ -2340,26 +2340,26 @@ loader-utils@^2.0.0: locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" lodash@^4.17.19: version "4.17.20" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== loose-envify@^1.0.0, loose-envify@^1.1.0: version "1.4.0" - resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== dependencies: js-tokens "^3.0.0 || ^4.0.0" make-dir@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz" integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== dependencies: pify "^4.0.1" @@ -2367,14 +2367,14 @@ make-dir@^2.1.0: make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" markdown-it@^14.1.0: version "14.1.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" + resolved "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz" integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== dependencies: argparse "^2.0.1" @@ -2386,39 +2386,39 @@ markdown-it@^14.1.0: mdurl@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + resolved "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz" integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== merge-stream@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== meros@^1.1.4: version "1.3.0" - resolved "https://registry.yarnpkg.com/meros/-/meros-1.3.0.tgz#c617d2092739d55286bf618129280f362e6242f2" + resolved "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz" integrity sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w== mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.27: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" mime@^1.4.1: version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== mini-css-extract-plugin@^2.7.6: version "2.9.0" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz#c73a1327ccf466f69026ac22a8e8fd707b78a235" + resolved "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz" integrity sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA== dependencies: schema-utils "^4.0.0" @@ -2431,17 +2431,17 @@ minimist@1.2.6, minimist@^1.2.0, minimist@^1.2.5: ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== nanoid@^3.3.7: version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz" integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== needle@^3.1.0: version "3.3.1" - resolved "https://registry.yarnpkg.com/needle/-/needle-3.3.1.tgz#63f75aec580c2e77e209f3f324e2cdf3d29bd049" + resolved "https://registry.npmjs.org/needle/-/needle-3.3.1.tgz" integrity sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q== dependencies: iconv-lite "^0.6.3" @@ -2449,37 +2449,37 @@ needle@^3.1.0: neo-async@^2.6.2: version "2.6.2" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== node-releases@^1.1.70: version "1.1.70" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-1.1.70.tgz" integrity sha512-Slf2s69+2/uAD79pVVQo8uSiC34+g8GWY8UH2Qtqv34ZfhYrxpYpfzs9Js9d6O0mbDmALuxaTlplnBTnSELcrw== node-releases@^2.0.14: version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== normalize-path@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== nullthrows@^1.0.0: version "1.1.1" - resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz#7818258843856ae971eae4208ad7d7eb19a431b1" + resolved "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz" integrity sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw== object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@^4.1.0: version "4.1.2" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== dependencies: call-bind "^1.0.0" @@ -2489,33 +2489,33 @@ object.assign@^4.1.0: p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" parse-json@^5.2.0: version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + resolved "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz" integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== dependencies: "@babel/code-frame" "^7.0.0" @@ -2525,54 +2525,54 @@ parse-json@^5.2.0: parse-node-version@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" + resolved "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz" integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-key@^3.1.0: version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== picocolors@^0.2.1: version "0.2.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz" integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA== -picocolors@^1.0.0, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== +picocolors@^1.0.0, picocolors@^1.0.1, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== pify@^4.0.1: version "4.0.1" - resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + resolved "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pkg-dir@^4.1.0, pkg-dir@^4.2.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" popmotion@11.0.3: version "11.0.3" - resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-11.0.3.tgz#565c5f6590bbcddab7a33a074bb2ba97e24b0cc9" + resolved "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz" integrity sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA== dependencies: framesync "6.0.1" @@ -2582,7 +2582,7 @@ popmotion@11.0.3: postcss-loader@^7.3.3: version "7.3.4" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.3.4.tgz#aed9b79ce4ed7e9e89e56199d25ad1ec8f606209" + resolved "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz" integrity sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A== dependencies: cosmiconfig "^8.3.5" @@ -2591,14 +2591,14 @@ postcss-loader@^7.3.3: postcss-modules-extract-imports@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + resolved "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz" integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== dependencies: postcss "^7.0.5" postcss-modules-local-by-default@^3.0.2: version "3.0.3" - resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz#bb14e0cc78279d504dbdcbfd7e0ca28993ffbbb0" + resolved "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz" integrity sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw== dependencies: icss-utils "^4.1.1" @@ -2608,7 +2608,7 @@ postcss-modules-local-by-default@^3.0.2: postcss-modules-scope@^2.2.0: version "2.2.0" - resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz#385cae013cc7743f5a7d7602d1073a89eaae62ee" + resolved "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz" integrity sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ== dependencies: postcss "^7.0.6" @@ -2616,7 +2616,7 @@ postcss-modules-scope@^2.2.0: postcss-modules-values@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + resolved "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz" integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== dependencies: icss-utils "^4.0.0" @@ -2624,7 +2624,7 @@ postcss-modules-values@^3.0.0: postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: version "6.0.4" - resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3" + resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz" integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw== dependencies: cssesc "^3.0.0" @@ -2634,7 +2634,7 @@ postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: postcss-value-parser@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" + resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz" integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== postcss@7.0.39, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6: @@ -2646,39 +2646,39 @@ postcss@7.0.39, postcss@^7.0.14, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6 source-map "^0.6.1" postcss@^8.4.28: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== + version "8.4.49" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz" + integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA== dependencies: nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" + picocolors "^1.1.1" + source-map-js "^1.2.1" prr@~1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + resolved "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= punycode.js@^2.3.1: version "2.3.1" - resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + resolved "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz" integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== punycode@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" react-dom@^18.3.1: version "18.3.1" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz" integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" @@ -2686,7 +2686,7 @@ react-dom@^18.3.1: react-remove-scroll-bar@^2.3.4: version "2.3.6" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" + resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz" integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== dependencies: react-style-singleton "^2.2.1" @@ -2694,7 +2694,7 @@ react-remove-scroll-bar@^2.3.4: react-remove-scroll@2.5.7: version "2.5.7" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" + resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz" integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== dependencies: react-remove-scroll-bar "^2.3.4" @@ -2705,7 +2705,7 @@ react-remove-scroll@2.5.7: react-style-singleton@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" + resolved "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz" integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== dependencies: get-nonce "^1.0.0" @@ -2714,45 +2714,45 @@ react-style-singleton@^2.2.1: react@^18.3.1: version "18.3.1" - resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz" integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" rechoir@^0.8.0: version "0.8.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + resolved "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz" integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== dependencies: resolve "^1.20.0" regenerate-unicode-properties@^8.2.0: version "8.2.0" - resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" + resolved "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz" integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== dependencies: regenerate "^1.4.0" regenerate@^1.4.0: version "1.4.2" - resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" + resolved "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== regenerator-runtime@^0.13.4: version "0.13.7" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== regenerator-transform@^0.14.2: version "0.14.5" - resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" + resolved "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz" integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== dependencies: "@babel/runtime" "^7.8.4" regexpu-core@^4.7.1: version "4.7.1" - resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" + resolved "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz" integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== dependencies: regenerate "^1.4.0" @@ -2764,41 +2764,41 @@ regexpu-core@^4.7.1: regjsgen@^0.5.1: version "0.5.2" - resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" + resolved "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz" integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== regjsparser@^0.6.4: version "0.6.7" - resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz#c00164e1e6713c2e3ee641f1701c4b7aa0a7f86c" + resolved "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.7.tgz" integrity sha512-ib77G0uxsA2ovgiYbCVGx4Pv3PSttAx2vIwidqQzbL2U5S4Q+j00HdSAneSBuyVcMvEnTXMjiGgB+DlXozVhpQ== dependencies: jsesc "~0.5.0" require-from-string@^2.0.2: version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + resolved "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== resolve-cwd@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + resolved "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz" integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== dependencies: resolve-from "^5.0.0" resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== resolve-from@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve@^1.20.0: version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== dependencies: is-core-module "^2.13.0" @@ -2807,34 +2807,34 @@ resolve@^1.20.0: safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.1: version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: version "1.4.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" + resolved "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz" integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== scheduler@^0.23.2: version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz" integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" schema-utils@^2.6.5, schema-utils@^2.7.0: version "2.7.1" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz" integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== dependencies: "@types/json-schema" "^7.0.5" @@ -2843,7 +2843,7 @@ schema-utils@^2.6.5, schema-utils@^2.7.0: schema-utils@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.0.0.tgz" integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA== dependencies: "@types/json-schema" "^7.0.6" @@ -2852,7 +2852,7 @@ schema-utils@^3.0.0: schema-utils@^3.1.1, schema-utils@^3.2.0: version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== dependencies: "@types/json-schema" "^7.0.8" @@ -2861,7 +2861,7 @@ schema-utils@^3.1.1, schema-utils@^3.2.0: schema-utils@^4.0.0: version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz" integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== dependencies: "@types/json-schema" "^7.0.9" @@ -2871,34 +2871,34 @@ schema-utils@^4.0.0: semver@7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + resolved "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.1" - resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@^6.0.0, semver@^6.3.0: version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== semver@^7.5.4: version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + resolved "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== serialize-javascript@^6.0.1: version "6.0.2" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz" integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" set-value@^4.1.0: version "4.1.0" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.1.0.tgz#aa433662d87081b75ad88a4743bd450f044e7d09" + resolved "https://registry.npmjs.org/set-value/-/set-value-4.1.0.tgz" integrity sha512-zTEg4HL0RwVrqcWs3ztF+x1vkxfm0lP+MQQFPiMJTKVceBwEV0A569Ou8l9IYQG8jOZdMVI1hGsc0tmeD2o/Lw== dependencies: is-plain-object "^2.0.4" @@ -2906,57 +2906,57 @@ set-value@^4.1.0: shallow-clone@^3.0.0: version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz" integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== dependencies: kind-of "^6.0.2" shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -source-map-js@^1.0.2, source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== +source-map-js@^1.0.2, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== source-map-loader@^4.0.1: version "4.0.2" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-4.0.2.tgz#1b378721b65adb21e874928a9fb22e8a340d06a5" + resolved "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.2.tgz" integrity sha512-oYwAqCuL0OZhBoSgmdrLa7mv9MjommVMiQIWgcztf+eS4+8BfcUee6nenFnDhKOhzAVnk5gpZdfnz1iiBv+5sg== dependencies: iconv-lite "^0.6.3" source-map-js "^1.0.2" source-map-support@~0.5.12: - version "0.5.19" - resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" source-map@^0.5.0: version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== style-loader@^1.2.1: version "1.3.0" - resolved "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" + resolved "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz" integrity sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q== dependencies: loader-utils "^2.0.0" @@ -2964,7 +2964,7 @@ style-loader@^1.2.1: style-value-types@5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-5.0.0.tgz#76c35f0e579843d523187989da866729411fc8ad" + resolved "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz" integrity sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA== dependencies: hey-listen "^1.0.8" @@ -2972,31 +2972,31 @@ style-value-types@5.0.0: supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^8.0.0: version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1: version "2.2.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== terser-webpack-plugin@^5.3.10: version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + resolved "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz" integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: "@jridgewell/trace-mapping" "^0.3.20" @@ -3016,42 +3016,42 @@ terser@4.8.1, terser@^5.26.0: to-fast-properties@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= toggle-selection@^1.0.6: version "1.0.6" - resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= tslib@^1.9.0: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.3.1: version "2.6.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== uc.micro@^2.0.0, uc.micro@^2.1.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + resolved "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz" integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== undici-types@~5.26.4: version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + resolved "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== unicode-canonical-property-names-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + resolved "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz" integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== unicode-match-property-ecmascript@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + resolved "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz" integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== dependencies: unicode-canonical-property-names-ecmascript "^1.0.4" @@ -3059,22 +3059,22 @@ unicode-match-property-ecmascript@^1.0.4: unicode-match-property-value-ecmascript@^1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" + resolved "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz" integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== unicode-property-aliases-ecmascript@^1.0.4: version "1.1.0" - resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" + resolved "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz" integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== uniq@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + resolved "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= update-browserslist-db@^1.0.16: version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" + resolved "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz" integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== dependencies: escalade "^3.1.2" @@ -3082,21 +3082,21 @@ update-browserslist-db@^1.0.16: uri-js@^4.2.2, uri-js@^4.4.1: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" use-callback-ref@^1.3.0: version "1.3.2" - resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" + resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz" integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== dependencies: tslib "^2.0.0" use-sidecar@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" + resolved "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz" integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== dependencies: detect-node-es "^1.1.0" @@ -3104,17 +3104,17 @@ use-sidecar@^1.1.2: util-deprecate@^1.0.2: version "1.0.2" - resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= vscode-languageserver-types@^3.17.1: version "3.17.5" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz#3273676f0cf2eab40b3f44d085acbb7f08a39d8a" + resolved "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz" integrity sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg== watchpack@^2.4.1: version "2.4.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" + resolved "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz" integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== dependencies: glob-to-regexp "^0.4.1" @@ -3122,7 +3122,7 @@ watchpack@^2.4.1: webpack-cli@^5.1.4: version "5.1.4" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-5.1.4.tgz#c8e046ba7eaae4911d7e71e2b25b776fcc35759b" + resolved "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz" integrity sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg== dependencies: "@discoveryjs/json-ext" "^0.5.0" @@ -3141,7 +3141,7 @@ webpack-cli@^5.1.4: webpack-merge@^5.7.3: version "5.10.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" + resolved "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz" integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== dependencies: clone-deep "^4.0.1" @@ -3150,12 +3150,12 @@ webpack-merge@^5.7.3: webpack-sources@^3.2.3: version "3.2.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== webpack@^5.88.2: version "5.92.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.92.1.tgz#eca5c1725b9e189cffbd86e8b6c3c7400efc5788" + resolved "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz" integrity sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA== dependencies: "@types/eslint-scope" "^3.7.3" @@ -3185,12 +3185,12 @@ webpack@^5.88.2: which@^2.0.1: version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" wildcard@^2.0.0: version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + resolved "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz" integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== diff --git a/graphql/karaf-feature/src/main/feature/feature.xml b/graphql/karaf-feature/src/main/feature/feature.xml index 19203e810..7e2569951 100644 --- a/graphql/karaf-feature/src/main/feature/feature.xml +++ b/graphql/karaf-feature/src/main/feature/feature.xml @@ -18,38 +18,37 @@ - unomi-kar - wrap:mvn:com.google.code.findbugs/jsr305/1.3.9 - wrap:mvn:org.checkerframework/checker-compat-qual/2.0.0 - wrap:mvn:com.google.errorprone/error_prone_annotations/2.1.3 - wrap:mvn:com.google.j2objc/j2objc-annotations/1.1 - wrap:mvn:org.codehaus.mojo/animal-sniffer-annotations/1.14 - mvn:commons-fileupload/commons-fileupload/1.3.1 - mvn:org.antlr/antlr4-runtime/${antlr.runtime.version} - wrap:mvn:com.graphql-java/java-dataloader/${java.dataloader.version} - mvn:org.reactivestreams/reactive-streams/1.0.2 - mvn:com.graphql-java/graphql-java/${graphql.java.version} - mvn:io.github.graphql-java/graphql-java-annotations/${graphql.java.annotations.version} - mvn:javax.validation/validation-api/${bean.validation.version} - wrap:mvn:com.graphql-java/graphql-java-extended-scalars/${graphql.java.extended.scalars.version} - wrap:mvn:com.squareup.okhttp3/okhttp/3.2.0 - wrap:mvn:com.squareup.okio/okio/1.6.0 - mvn:io.reactivex.rxjava2/rxjava/2.2.19 - mvn:org.eclipse.jetty.websocket/websocket-server/${jetty.websocket.version} - mvn:org.eclipse.jetty.websocket/websocket-common/${jetty.websocket.version} - mvn:org.eclipse.jetty.websocket/websocket-api/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-util/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-io/${jetty.websocket.version} - mvn:org.eclipse.jetty.websocket/websocket-client/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-client/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-xml/${jetty.websocket.version} - mvn:org.eclipse.jetty.websocket/websocket-servlet/${jetty.websocket.version} - mvn:javax.servlet/javax.servlet-api/3.0.1 - mvn:org.eclipse.jetty/jetty-servlet/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-security/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-server/${jetty.websocket.version} - mvn:org.eclipse.jetty/jetty-http/${jetty.websocket.version} - mvn:org.apache.unomi/cdp-graphql-api-impl/${project.version} - mvn:org.apache.unomi/unomi-graphql-ui/${project.version} + wrap:mvn:com.google.code.findbugs/jsr305/1.3.9 + wrap:mvn:org.checkerframework/checker-compat-qual/2.0.0 + wrap:mvn:com.google.errorprone/error_prone_annotations/2.1.3 + wrap:mvn:com.google.j2objc/j2objc-annotations/1.1 + wrap:mvn:org.codehaus.mojo/animal-sniffer-annotations/1.14 + mvn:commons-fileupload/commons-fileupload/1.3.1 + mvn:org.antlr/antlr4-runtime/${antlr.runtime.version} + wrap:mvn:com.graphql-java/java-dataloader/${java.dataloader.version} + mvn:org.reactivestreams/reactive-streams/1.0.2 + mvn:com.graphql-java/graphql-java/${graphql.java.version} + mvn:io.github.graphql-java/graphql-java-annotations/${graphql.java.annotations.version} + mvn:javax.validation/validation-api/${bean.validation.version} + wrap:mvn:com.graphql-java/graphql-java-extended-scalars/${graphql.java.extended.scalars.version} + wrap:mvn:com.squareup.okhttp3/okhttp/3.2.0 + wrap:mvn:com.squareup.okio/okio/1.6.0 + mvn:io.reactivex.rxjava2/rxjava/2.2.19 + mvn:org.eclipse.jetty.websocket/websocket-server/${jetty.websocket.version} + mvn:org.eclipse.jetty.websocket/websocket-common/${jetty.websocket.version} + mvn:org.eclipse.jetty.websocket/websocket-api/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-util/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-io/${jetty.websocket.version} + mvn:org.eclipse.jetty.websocket/websocket-client/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-client/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-xml/${jetty.websocket.version} + mvn:org.eclipse.jetty.websocket/websocket-servlet/${jetty.websocket.version} + mvn:javax.servlet/javax.servlet-api/3.0.1 + mvn:org.eclipse.jetty/jetty-servlet/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-security/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-server/${jetty.websocket.version} + mvn:org.eclipse.jetty/jetty-http/${jetty.websocket.version} + mvn:org.apache.unomi/cdp-graphql-api-impl/${project.version} + mvn:org.apache.unomi/unomi-graphql-ui/${project.version} diff --git a/itests/pom.xml b/itests/pom.xml index 592da8297..4a10391a9 100644 --- a/itests/pom.xml +++ b/itests/pom.xml @@ -304,6 +304,7 @@ com.github.alexcojocaru elasticsearch-maven-plugin + 6.23 contextElasticSearchITests @@ -311,6 +312,7 @@ 9400 ${elasticsearch.test.version} true + 120 -Xms4g -Xmx4g @@ -326,6 +328,10 @@ + start-elasticsearch pre-integration-test diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java index 22193785c..8e2bece4a 100644 --- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java @@ -26,11 +26,7 @@ import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.*; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; @@ -100,6 +96,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import static org.ops4j.pax.exam.CoreOptions.maven; import static org.ops4j.pax.exam.CoreOptions.systemProperty; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*; @@ -173,11 +170,21 @@ public void waitForStartup() throws InterruptedException { // Start Unomi if not already done if (!unomiStarted) { if (SEARCH_ENGINE_ELASTICSEARCH.equals(searchEngine)) { + LOGGER.info("Starting Unomi with elasticsearch search engine..."); + System.out.println("==== Starting Unomi with elasticsearch search engine..."); executeCommand("unomi:start"); + } else if (SEARCH_ENGINE_OPENSEARCH.equals(searchEngine)){ + LOGGER.info("Starting Unomi with opensearch search engine..."); + System.out.println("==== Starting Unomi with opensearch search engine..."); + executeCommand("unomi:start " + SEARCH_ENGINE_OPENSEARCH); } else { - executeCommand("unomi:start opensearch"); + LOGGER.error("Unknown search engine: " + searchEngine); + throw new InterruptedException("Unknown search engine: " + searchEngine); } unomiStarted = true; + } else { + LOGGER.info("Unomi is already started."); + System.out.println("==== Unomi is already started."); } // Wait for startup complete @@ -216,6 +223,12 @@ public void shutdown() { } protected void removeItems(final Class... classes) throws InterruptedException { + if (definitionsService == null) { + throw new RuntimeException("definitionsService is null"); + } + if (persistenceService == null) { + throw new RuntimeException("persistenceService is null"); + } Condition condition = new Condition(definitionsService.getConditionType("matchAllCondition")); for (Class aClass : classes) { persistenceService.removeByQuery(condition, aClass); @@ -232,12 +245,34 @@ protected void refreshPersistence(final Class... classes) throws @Override public MavenArtifactUrlReference getKarafDistribution() { - return CoreOptions.maven().groupId("org.apache.unomi").artifactId("unomi").versionAsInProject().type("tar.gz"); + return maven().groupId("org.apache.unomi").artifactId("unomi").versionAsInProject().type("tar.gz"); } @Configuration public Option[] config() { System.out.println("==== Configuring container"); + + searchEngine = System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH); + System.out.println("Search Engine: " + searchEngine); + + // Define features option based on search engine + Option featuresOption; + if (SEARCH_ENGINE_ELASTICSEARCH.equals(searchEngine)) { + featuresOption = features(maven().groupId("org.apache.unomi") + .artifactId("unomi-kar").versionAsInProject().type("xml").classifier("features"), + "unomi-persistence-elasticsearch", "unomi-services", + "unomi-router-karaf-feature", "unomi-groovy-actions", + "unomi-web-applications", "unomi-rest-ui", "unomi-healthcheck", "cdp-graphql-feature"); + } else if (SEARCH_ENGINE_OPENSEARCH.equals(searchEngine)) { + featuresOption = features(maven().groupId("org.apache.unomi") + .artifactId("unomi-kar").versionAsInProject().type("xml").classifier("features"), + "unomi-persistence-opensearch", "unomi-services", + "unomi-router-karaf-feature", "unomi-groovy-actions", + "unomi-web-applications", "unomi-rest-ui", "unomi-healthcheck", "cdp-graphql-feature"); + } else { + throw new IllegalArgumentException("Unknown search engine: " + searchEngine); + } + Option[] options = new Option[]{ replaceConfigurationFile("etc/org.apache.unomi.router.cfg", new File("src/test/resources/org.apache.unomi.router.cfg")), @@ -271,6 +306,9 @@ public Option[] config() { systemProperty("org.apache.unomi.hazelcast.tcp-ip.interface").value("127.0.0.1"), systemProperty("org.apache.unomi.healthcheck.enabled").value("true"), + featuresOption, // Add the features option + + configureConsole().startRemoteShell(), logLevel(LogLevel.INFO), keepRuntimeFolder(), CoreOptions.bundleStartLevel(100), diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java index eddea843e..54774a481 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ProfileImportActorsIT.java @@ -30,12 +30,7 @@ import org.ops4j.pax.exam.spi.reactors.PerSuite; import java.io.File; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; /** * Created by amidani on 14/08/2017. @@ -95,7 +90,8 @@ public void testImportActors() throws InterruptedException { "file://" + importSurfersFile.getAbsolutePath() + "?fileName=6-actors-test.csv&consumer.delay=10m&move=.done"); importConfigActors.setActive(true); - importConfigurationService.save(importConfigActors, true); + ImportConfiguration savedImportConfigActors = importConfigurationService.save(importConfigActors, true); + keepTrying("Failed waiting for actors import configuration to be saved", () -> importConfigurationService.load(importConfigActors.getItemId()), Objects::nonNull, DEFAULT_TRYING_TIMEOUT, DEFAULT_TRYING_TRIES); //Wait for data to be processed keepTrying("Failed waiting for actors initial import to complete", diff --git a/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java b/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java index f892c338a..316b0bc28 100644 --- a/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java +++ b/itests/src/test/java/org/apache/unomi/itests/migration/Migrate16xTo220IT.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.unomi.api.*; +import org.apache.unomi.geonames.services.GeonameEntry; import org.apache.unomi.itests.BaseIT; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; import org.apache.unomi.shell.migration.utils.HttpUtils; @@ -27,12 +28,16 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.*; public class Migrate16xTo220IT extends BaseIT { + private final static Logger LOGGER = LoggerFactory.getLogger(Migrate16xTo220IT.class); + private int eventCount = 0; private int sessionCount = 0; private Set initialScopes = new HashSet<>(); @@ -47,6 +52,9 @@ public class Migrate16xTo220IT extends BaseIT { @Before public void waitForStartup() throws InterruptedException { + System.out.println("Restoring snapshot into search engine..."); + LOGGER.info("Restoring snapshot into search engine..."); + // Restore snapshot from 1.6.x try (CloseableHttpClient httpClient = HttpUtils.initHttpClient(true, null)) { // Create snapshot repo @@ -59,16 +67,31 @@ public void waitForStartup() throws InterruptedException { // Restore the snapshot HttpUtils.executePostRequest(httpClient, "http://localhost:9400/_snapshot/snapshots_repository/snapshot_1.6.x/_restore?wait_for_completion=true", "{}", null); + String snapshotStatus = HttpUtils.executeGetRequest(httpClient, "http://localhost:9400/_snapshot/_status", null); + System.out.println(snapshotStatus); + LOGGER.info(snapshotStatus); + // Get initial counts of items to compare after migration initCounts(httpClient); - } catch (IOException e) { - throw new RuntimeException(e); + } catch (Throwable t) { + throw new RuntimeException("Error during snapshot restore", t); } + System.out.println("Launching migration from 1.6.0..."); + LOGGER.info("Launching migration from 1.6.0..."); + // Do migrate the data set - String commandResults = executeCommand("unomi:migrate 1.6.0 true"); + String commandResults = null; + try { + commandResults = executeCommand("unomi:migrate 1.6.0 true", 900000L, true); + } catch (Throwable t) { + LOGGER.error("Error during migration", t); + System.err.println("Error during migration"); + t.printStackTrace(); + throw new RuntimeException("Error during migration", t); + } - // Prin the resulted output in the karaf shell directly + // Print the resulted output in the karaf shell directly System.out.println("Migration command output results:"); System.out.println(commandResults); @@ -78,11 +101,18 @@ public void waitForStartup() throws InterruptedException { @After public void cleanup() throws InterruptedException { - removeItems(Profile.class); - removeItems(ProfileAlias.class); - removeItems(Session.class); - removeItems(Event.class); - removeItems(Scope.class); + try { + removeItems(Profile.class); + removeItems(ProfileAlias.class); + removeItems(Session.class); + removeItems(Event.class); + removeItems(Scope.class); + removeItems(GeonameEntry.class); + } catch (Throwable t) { + LOGGER.error("Error during cleanup", t); + System.err.println("Error during cleanup"); + t.printStackTrace(); + } } @Test @@ -262,7 +292,7 @@ private void checkScopeHaveBeenCreated() { // check that the scope mySite have been created based on the previous existings events Map existingScopesFromEvents = persistenceService.aggregateWithOptimizedQuery(null, new TermsAggregate("scope"), Event.ITEM_TYPE); for (String scopeFromEvents : existingScopesFromEvents.keySet()) { - if (!Objects.equals(scopeFromEvents, "_filtered")) { + if (!Objects.equals(scopeFromEvents, "_filtered") && !Objects.equals(scopeFromEvents, "_missing")) { Scope scope = scopeService.getScope(scopeFromEvents); Assert.assertNotNull(String.format("Unable to find registered scope %s", scopeFromEvents), scope); } diff --git a/itests/src/test/resources/migration/snapshots_repository.zip b/itests/src/test/resources/migration/snapshots_repository.zip index 566a5657c24ecb603d23d70229131e3139659606..010569bc0b2dd64437ca86b9a9109bc097eb4670 100644 GIT binary patch delta 666190 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

    NC@ihX)L0St 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

    mV_3{QfYlC=fg&?X{08bGs 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

  • ;J0b@LQ&0 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 z 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 z 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 z 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 U_&I6j@c@HlGsoo>}3McjjmsFMP zfi*7H7x%!+i=Cc*f(+NDokZI)MiI91EZ;Y>;YFW8zICU++iWZhjWuODjKu<(zC%WP z(fg}LEV=y1TZue>c>M$4UY{@`UE;&cD?GJ$^)vY27FN)~N?6LjU4R__Rp#feeE|L2 z1t{;R&l#56$&(8;ii9QBdZgklhNiXifh{zw>e$l&+Ie2{2_@1nw;M-qS-zez;b3g% z;8kE$-_j@3?8mV{!AP}H7qxx)h~?2|E};DpAi%$%hR!07)`9@K)<{%fv6lX5)dSCe z7Aji9$sj8<=9sVpO}>2h>t8(@TKFhlHfhRr({1PW!*l&196&#- z-iCvLi9vuaic+%t?Fim<5A*uB?qRA{<}&}OdswiVkOM9UA*-xxSipmDG65J+t`Ap@ zm~4$?Uifr;va@6b;rco4mDZ`|40Ht`1rf!C&G(6ngQeuy!^L8HdXDHPzVyt|nV_(7 zEV6Xn_uNk~#&?s%UB-wG!;vH%RgFEPROS{;kDEkslmIR;&_+bXC=F`6>#LyjKos%PK#FL{EN9ivWMrJ6K>a^KQs- zsRy%-7p0Clt@(PM>;GJoGIw8;824P1 zFrz9m)g?c6+DE>Q!1Py`R#$wa4}w9NeprZVDc!Vy5qx@fp_y{RPu@$QJlJRKP z9<8su`2bBeF9<_S2@yy$GYdsdMuH+~h0vr2OGy(UK(VOshzJZ!Uu(+d8F_;ZwXN;r zq#6Rs)Lv*7QbFU+U^x(hDU+n

    This service handles the following responsibilities:

    + *
      + *
    • Loading configuration from the OSGi Configuration Admin service, including persistence implementation and feature lists.
    • + *
    • Starting Apache Unomi by installing and starting the configured features for a selected persistence implementation.
    • + *
    • Stopping Apache Unomi by uninstalling features in reverse order to ensure proper teardown.
    • + *
    • Interfacing with the {@link org.apache.unomi.shell.migration.MigrationService} for migration tasks during startup.
    • + *
    + * + *

    The class is designed to be used within an OSGi environment and integrates with the Configuration Admin service + * to dynamically adjust its behavior based on external configurations. It leverages the {@link FeaturesService} to + * manage Karaf features dynamically.

    + * + *

    Configuration

    + *

    The service reads its configuration from the OSGi Configuration Admin under the PID org.apache.unomi.start. + * The configuration includes:

    + *
      + *
    • startFeatures: A semicolon-separated list of features mapped to persistence implementations + * in the format persistenceImplementation:feature1,feature2.
    • + *
    + * + *

    Usage

    + *

    This service can be controlled programmatically through its methods:

    + *
      + *
    • {@link #startUnomi(String, boolean)}: Installs and starts features for the specified persistence implementation.
    • + *
    • {@link #stopUnomi()}: Stops and uninstalls the previously started features.
    • + *
    + * + *

    Dependencies

    + *

    The following dependencies are required for this service:

    + *
      + *
    • {@link MigrationService}: Handles migration tasks during startup.
    • + *
    • {@link FeaturesService}: Provides access to Karaf's feature management API for installing, starting, and stopping features.
    • + *
    + * + *

    This service is registered as an OSGi component and automatically activated when the bundle is started. + * It is configured to listen for configuration updates and adapt its behavior accordingly.

    + * * @author dgaillard - */ -@Component(service = UnomiManagementService.class, immediate = true) + * @see org.apache.unomi.shell.services.UnomiManagementService + * @see org.apache.unomi.shell.migration.MigrationService + * @see org.apache.karaf.features.FeaturesService + * @see org.apache.karaf.features.Feature + */@Component(service = UnomiManagementService.class, immediate = true, configurationPid = "org.apache.unomi.start") +@Designate(ocd = UnomiManagementServiceConfiguration.class) public class UnomiManagementServiceImpl implements UnomiManagementService { private static final Logger LOGGER = LoggerFactory.getLogger(UnomiManagementServiceImpl.class.getName()); + private static final String CDP_GRAPHQL_FEATURE = "cdp-graphql-feature"; + private BundleContext bundleContext; @Reference(cardinality = ReferenceCardinality.MANDATORY) private MigrationService migrationService; - private final List bundleSymbolicNames = new ArrayList<>(); - private List reversedBundleSymbolicNames; - private Map persistenceImplementations = new HashMap<>(); - private Map persistenceConditions = new HashMap<>(); + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private FeaturesService featuresService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private BundleWatcher bundleWatcher; + + private Map> startFeatures = new HashMap>(); + private final List installedFeatures = new ArrayList<>(); + private final List startedFeatures = new ArrayList<>(); + private String selectedPersistenceImplementation = "elasticsearch"; @Activate - public void init(ComponentContext componentContext) throws Exception { + public void init(ComponentContext componentContext, UnomiManagementServiceConfiguration config) throws Exception { try { this.bundleContext = componentContext.getBundleContext(); - initReversedBundleSymbolicNames(); + this.startFeatures = parseStartFeatures(config.startFeatures()); if (StringUtils.isNotBlank(bundleContext.getProperty("unomi.autoMigrate"))) { migrationService.migrateUnomi(bundleContext.getProperty("unomi.autoMigrate"), true, null); @@ -65,33 +120,91 @@ public void init(ComponentContext componentContext) throws Exception { if (StringUtils.isNotBlank(bundleContext.getProperty("unomi.autoStart")) && bundleContext.getProperty("unomi.autoStart").equals("true")) { - startUnomi(selectedPersistenceImplementation); + startUnomi(selectedPersistenceImplementation, true); } + } catch (Exception e) { LOGGER.error("Error during Unomi startup when processing 'unomi.autoMigrate' or 'unomi.autoStart' properties:", e); } } + private List getAdditionalFeaturesToInstall() { + List featuresToInstall = new ArrayList<>(); + if (Boolean.parseBoolean(bundleContext.getProperty("org.apache.unomi.graphql.feature.activated"))) { + featuresToInstall.add(CDP_GRAPHQL_FEATURE); + bundleWatcher.addRequiredBundle("org.apache.unomi.cdp-graphql-api-impl"); + bundleWatcher.addRequiredBundle("org.apache.unomi.graphql-ui"); + } + return featuresToInstall; + } + + private Map> parseStartFeatures(String startFeaturesConfig) { + Map> startFeatures = new HashMap<>(); + if (startFeaturesConfig == null || startFeaturesConfig.isEmpty()) { + return startFeatures; + } + + String[] entries = startFeaturesConfig.split(";"); + for (String entry : entries) { + String[] parts = entry.split(":"); + if (parts.length == 2) { + String key = parts[0].trim(); + List features = new ArrayList<>(Arrays.asList(parts[1].split(","))); + startFeatures.put(key, features); + } else { + LOGGER.warn("Invalid start feature entry: {}", entry); + } + } + return startFeatures; + } + @Override - public void startUnomi(String selectedPersistenceImplementation) throws BundleException { + public void startUnomi(String selectedPersistenceImplementation, boolean mustStartFeatures) throws BundleException { if (selectedPersistenceImplementation != null) { this.selectedPersistenceImplementation = selectedPersistenceImplementation; } - for (String bundleSymbolicName : bundleSymbolicNames) { - if (bundleSymbolicName.equals("${persistenceImplementationName}")) { - bundleSymbolicName = persistenceImplementations.get(selectedPersistenceImplementation); - } else if (bundleSymbolicName.equals("${persistenceConditionsName}")) { - bundleSymbolicName = persistenceConditions.get(selectedPersistenceImplementation); - if (bundleSymbolicName == null) { + List features = startFeatures.get(selectedPersistenceImplementation); + if (features == null || features.isEmpty()) { + LOGGER.warn("No features configured for persistence implementation: {}", selectedPersistenceImplementation); + return; + } + features.addAll(getAdditionalFeaturesToInstall()); + + LOGGER.info("Installing features for persistence implementation: {}", selectedPersistenceImplementation); + for (String featureName : features) { + try { + Feature feature = featuresService.getFeature(featureName); + if (feature == null) { + LOGGER.error("Feature not found: {}", featureName); continue; } + + if (!installedFeatures.contains(featureName)) { + LOGGER.info("Installing feature: {}", featureName); + featuresService.installFeature(featureName, EnumSet.of(FeaturesService.Option.NoAutoStartBundles)); + installedFeatures.add(featureName); + } + } catch (Exception e) { + LOGGER.error("Error installing feature: {}", featureName, e); } - for (Bundle bundle : bundleContext.getBundles()) { - if (bundle.getSymbolicName().equals(bundleSymbolicName)) { - if (bundle.getState() == Bundle.RESOLVED) { - bundle.start(); + } + + if (mustStartFeatures) { + LOGGER.info("Starting features for persistence implementation: {}", selectedPersistenceImplementation); + for (String featureName : features) { + try { + Feature feature = featuresService.getFeature(featureName); + if (feature == null) { + LOGGER.error("Feature not found: {}", featureName); + continue; } - break; + if (mustStartFeatures) { + LOGGER.info("Starting feature: {}", featureName); + startFeature(featureName); + startedFeatures.add(featureName); // Keep track of started features + } + } catch (Exception e) { + LOGGER.error("Error starting feature: {}", featureName, e); } } } @@ -99,70 +212,57 @@ public void startUnomi(String selectedPersistenceImplementation) throws BundleEx @Override public void stopUnomi() throws BundleException { - for (String bundleSymbolicName : reversedBundleSymbolicNames) { - if (bundleSymbolicName.equals("${persistenceImplementationName}")) { - bundleSymbolicName = persistenceImplementations.get(selectedPersistenceImplementation); - } else if (bundleSymbolicName.equals("${persistenceConditionsName}")) { - bundleSymbolicName = persistenceConditions.get(selectedPersistenceImplementation); - if (bundleSymbolicName == null) { - continue; + if (startedFeatures.isEmpty()) { + LOGGER.info("No features to stop."); + } else { + LOGGER.info("Stopping features in reverse order..."); + ListIterator iterator = startedFeatures.listIterator(startedFeatures.size()); + while (iterator.hasPrevious()) { + String featureName = iterator.previous(); + try { + LOGGER.info("Stopping feature: {}", featureName); + stopFeature(featureName); + } catch (Exception e) { + LOGGER.error("Error stopping feature: {}", featureName, e); } } - for (Bundle bundle : bundleContext.getBundles()) { - if (bundle.getSymbolicName().equals(bundleSymbolicName)) { - if (bundle.getState() == Bundle.ACTIVE) { - bundle.stop(); - } - break; + + startedFeatures.clear(); // Clear the list after stopping all features + } + if (installedFeatures.isEmpty()) { + LOGGER.info("No features to uninstall."); + } else { + LOGGER.info("Stopping features in reverse order..."); + ListIterator iterator = installedFeatures.listIterator(installedFeatures.size()); + while (iterator.hasPrevious()) { + String featureName = iterator.previous(); + try { + LOGGER.info("Uninstalling feature: {}", featureName); + featuresService.uninstallFeature(featureName); + } catch (Exception e) { + LOGGER.error("Error uninstalling feature: {}", featureName, e); } } + installedFeatures.clear(); // Clear the list after stopping all features } } - public void initReversedBundleSymbolicNames() { - persistenceImplementations.clear(); - persistenceImplementations.put("elasticsearch", "org.apache.unomi.persistence-elasticsearch-core"); - persistenceImplementations.put("opensearch", "org.apache.unomi.persistence-opensearch-core"); - persistenceConditions.clear(); - persistenceConditions.put("opensearch", "org.apache.unomi.persistence-opensearch-conditions"); - bundleSymbolicNames.clear(); - bundleSymbolicNames.add("org.apache.unomi.lifecycle-watcher"); - bundleSymbolicNames.add("org.apache.unomi.api"); - bundleSymbolicNames.add("org.apache.unomi.common"); - bundleSymbolicNames.add("org.apache.unomi.scripting"); - bundleSymbolicNames.add("org.apache.unomi.metrics"); - bundleSymbolicNames.add("org.apache.unomi.persistence-spi"); - bundleSymbolicNames.add("${persistenceImplementationName}"); - bundleSymbolicNames.add("${persistenceConditionsName}"); - bundleSymbolicNames.add("org.apache.unomi.services"); - bundleSymbolicNames.add("org.apache.unomi.cxs-lists-extension-services"); - bundleSymbolicNames.add("org.apache.unomi.cxs-lists-extension-rest"); - bundleSymbolicNames.add("org.apache.unomi.cxs-geonames-services"); - bundleSymbolicNames.add("org.apache.unomi.cxs-geonames-rest"); - bundleSymbolicNames.add("org.apache.unomi.cxs-privacy-extension-services"); - bundleSymbolicNames.add("org.apache.unomi.cxs-privacy-extension-rest"); - bundleSymbolicNames.add("org.apache.unomi.json-schema-services"); - bundleSymbolicNames.add("org.apache.unomi.json-schema-rest"); - bundleSymbolicNames.add("org.apache.unomi.rest"); - bundleSymbolicNames.add("org.apache.unomi.wab"); - bundleSymbolicNames.add("org.apache.unomi.plugins-base"); - bundleSymbolicNames.add("org.apache.unomi.plugins-request"); - bundleSymbolicNames.add("org.apache.unomi.plugins-mail"); - bundleSymbolicNames.add("org.apache.unomi.plugins-optimization-test"); - bundleSymbolicNames.add("org.apache.unomi.cxs-lists-extension-actions"); - bundleSymbolicNames.add("org.apache.unomi.router-api"); - bundleSymbolicNames.add("org.apache.unomi.router-core"); - bundleSymbolicNames.add("org.apache.unomi.router-service"); - bundleSymbolicNames.add("org.apache.unomi.router-rest"); - bundleSymbolicNames.add("org.apache.unomi.shell-dev-commands"); - bundleSymbolicNames.add("org.apache.unomi.web-tracker-wab"); - bundleSymbolicNames.add("org.apache.unomi.groovy-actions-services"); - bundleSymbolicNames.add("org.apache.unomi.groovy-actions-rest"); - - if (reversedBundleSymbolicNames == null || reversedBundleSymbolicNames.isEmpty()) { - this.reversedBundleSymbolicNames = new ArrayList<>(); - reversedBundleSymbolicNames.addAll(bundleSymbolicNames); - Collections.reverse(reversedBundleSymbolicNames); - } + private void startFeature(String featureName) throws Exception { + Feature feature = featuresService.getFeature(featureName); + Map> stateChanges = new HashMap<>(); + Map regionChanges = new HashMap<>(); + regionChanges.put(feature.getId(), FeatureState.Started); + stateChanges.put(FeaturesService.ROOT_REGION, regionChanges); + featuresService.updateFeaturesState(stateChanges, EnumSet.of(FeaturesService.Option.Verbose)); + } + + private void stopFeature(String featureName) throws Exception { + Feature feature = featuresService.getFeature(featureName); + Map> stateChanges = new HashMap<>(); + Map regionChanges = new HashMap<>(); + regionChanges.put(feature.getId(), FeatureState.Resolved); + stateChanges.put(FeaturesService.ROOT_REGION, regionChanges); + featuresService.updateFeaturesState(stateChanges, EnumSet.of(FeaturesService.Option.Verbose)); } + } diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-05-globalReindex.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-05-globalReindex.groovy index 3d013b1e4..cc29a9dc5 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-05-globalReindex.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-05-globalReindex.groovy @@ -27,5 +27,5 @@ String[] indicesToReindex = ["segment", "scoring", "campaign", "conditionType", indicesToReindex.each { indexToReindex -> String mapping = MigrationUtils.resourceAsString(bundleContext, "requestBody/2.0.0/mappings/${indexToReindex}.json") String newIndexSettings = MigrationUtils.buildIndexCreationRequest(baseSettings, mapping, context, false) - MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, "${indexPrefix}-${indexToReindex.toLowerCase()}", newIndexSettings, null, context) + MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, "${indexPrefix}-${indexToReindex.toLowerCase()}", newIndexSettings, null, context, "migrate-2.0.0-05-globalReindex") } diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-10-profileReindex.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-10-profileReindex.groovy index bcb4e6ae7..b4e86761c 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-10-profileReindex.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-10-profileReindex.groovy @@ -26,4 +26,4 @@ String baseSettings = MigrationUtils.resourceAsString(bundleContext, "requestBod String mapping = MigrationUtils.extractMappingFromBundles(bundleContext, "profile.json") String newIndexSettings = MigrationUtils.buildIndexCreationRequest(baseSettings, mapping, context, false) MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, indexPrefix + "-profile", - newIndexSettings, MigrationUtils.getFileWithoutComments(bundleContext, "requestBody/2.0.0/profile_migrate.painless"), context) + newIndexSettings, MigrationUtils.getFileWithoutComments(bundleContext, "requestBody/2.0.0/profile_migrate.painless"), context, "migrate-2.0.0-10-profileReindex") diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy index 85a25df87..88ce723de 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.0.0-15-eventsReindex.groovy @@ -1,5 +1,4 @@ import org.apache.unomi.shell.migration.service.MigrationContext -import org.apache.unomi.shell.migration.utils.HttpUtils import org.apache.unomi.shell.migration.utils.MigrationUtils /* @@ -35,5 +34,5 @@ String mapping = MigrationUtils.extractMappingFromBundles(bundleContext, "event. String newIndexSettings = MigrationUtils.buildIndexCreationRequest(baseSettings, mapping, context, true) Set eventIndices = MigrationUtils.getIndexesPrefixedBy(context.getHttpClient(), esAddress, "${indexPrefix}-event-date-") eventIndices.each { eventIndex -> - MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, eventIndex, newIndexSettings, reIndexScript, context) + MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, eventIndex, newIndexSettings, reIndexScript, context, "migrate-2.0.0-15-eventsReindex") } diff --git a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy index 7b519ce47..904a24202 100644 --- a/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy +++ b/tools/shell-commands/src/main/resources/META-INF/cxs/migration/migrate-2.5.0-00-cleanPastEventProfileSession.groovy @@ -1,8 +1,5 @@ import org.apache.unomi.shell.migration.service.MigrationContext -import org.apache.unomi.shell.migration.utils.HttpUtils import org.apache.unomi.shell.migration.utils.MigrationUtils -import org.osgi.framework.BundleContext -import org.osgi.framework.Bundle /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -32,7 +29,7 @@ context.performMigrationStep("2.5.0-clean-profile-mapping", () -> { String updatePastEventScript = MigrationUtils.getFileWithoutComments(bundleContext, "requestBody/2.5.0/update_pastEvents_profile.painless") String mapping = MigrationUtils.extractMappingFromBundles(bundleContext, "profile.json") String newIndexSettings = MigrationUtils.buildIndexCreationRequest(baseSettings, mapping, context, false) - MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, indexPrefix + "-profile", newIndexSettings, updatePastEventScript, context) + MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, indexPrefix + "-profile", newIndexSettings, updatePastEventScript, context, "2.5.0-clean-profile-mapping") }) context.performMigrationStep("2.5.0-clean-session-mapping", () -> { @@ -43,6 +40,6 @@ context.performMigrationStep("2.5.0-clean-session-mapping", () -> { Set sessionIndices = MigrationUtils.getIndexesPrefixedBy(context.getHttpClient(), esAddress, "${indexPrefix}-session-") sessionIndices.each { sessionIndex -> - MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, sessionIndex, newIndexSettings, cleanPastEventScript, context) + MigrationUtils.reIndex(context.getHttpClient(), bundleContext, esAddress, sessionIndex, newIndexSettings, cleanPastEventScript, context, "2.5.0-clean-session-mapping") } }) diff --git a/tools/shell-commands/src/main/resources/org.apache.unomi.start.cfg b/tools/shell-commands/src/main/resources/org.apache.unomi.start.cfg new file mode 100644 index 000000000..a9d91958d --- /dev/null +++ b/tools/shell-commands/src/main/resources/org.apache.unomi.start.cfg @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +startFeatures=elasticsearch:unomi-persistence-elasticsearch,unomi-services,unomi-router-karaf-feature,unomi-groovy-actions,unomi-web-applications,unomi-rest-ui,unomi-healthcheck;opensearch:unomi-persistence-opensearch,unomi-services,unomi-router-karaf-feature,unomi-groovy-actions,unomi-web-applications,unomi-rest-ui,unomi-healthcheck diff --git a/tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless b/tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless new file mode 100644 index 000000000..837103fe1 --- /dev/null +++ b/tools/shell-commands/src/main/resources/requestBody/2.5.0/login_event_scope_migrate.painless @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Handle login events */ + +ctx._source.put('scope', 'systemsite'); +if (ctx._source.source != null) { + ctx._source.source.put('scope', 'systemsite'); +} +if (ctx._source.target != null) { + ctx._source.target.put('scope', 'systemsite'); +} diff --git a/tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless b/tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless new file mode 100644 index 000000000..6e3b6d248 --- /dev/null +++ b/tools/shell-commands/src/main/resources/requestBody/2.5.0/remove_pastEvents_session.painless @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (ctx._source.profile != null) { + if (ctx._source.profile.systemProperties != null && ctx._source.profile.systemProperties.pastEvents != null) { + ctx._source.profile.systemProperties.remove('pastEvents'); + } +} diff --git a/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 5437e3b49..0fdf3d857 100644 --- a/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/wab/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -54,10 +54,9 @@ javax.servlet.Servlet - javax.servlet.ServletConfig - java.io.Serializable + /context.json @@ -72,10 +71,9 @@ javax.servlet.Servlet - javax.servlet.ServletConfig - java.io.Serializable + @@ -88,10 +86,9 @@ javax.servlet.Servlet - javax.servlet.ServletConfig - java.io.Serializable + From 0213604f7b32f338e5a5c1a7492cabe63c855f96 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Tue, 17 Dec 2024 15:02:55 +0100 Subject: [PATCH 11/58] - Remove old build scripts - Add option to new build script to be able to use opensearch with integration tests --- build.sh | 15 +++++++++++++- buildAndRun.sh | 38 ----------------------------------- buildAndRunNoTests.sh | 46 ------------------------------------------- compileDeploy.sh | 37 ---------------------------------- generate-package.sh | 22 --------------------- 5 files changed, 14 insertions(+), 144 deletions(-) delete mode 100755 buildAndRun.sh delete mode 100755 buildAndRunNoTests.sh delete mode 100755 compileDeploy.sh delete mode 100755 generate-package.sh diff --git a/build.sh b/build.sh index 01d3d3938..d53030d20 100755 --- a/build.sh +++ b/build.sh @@ -64,6 +64,7 @@ MAVEN_OFFLINE=false SEARCH_ENGINE="elasticsearch" KARAF_DEBUG_PORT=5005 KARAF_DEBUG_SUSPEND=n +USE_OPENSEARCH=false # Function to display usage usage() { @@ -91,6 +92,7 @@ EOF echo " --purge-maven-cache Purge local Maven cache before building" echo " --search-engine ENGINE Set search engine (elasticsearch|opensearch)" echo " --karaf-home PATH Set Karaf home directory for deployment" + echo " --use-opensearch Use OpenSearch instead of ElasticSearch for tests" echo "" echo "Examples:" echo " $0 --integration-tests --search-engine opensearch" @@ -99,6 +101,7 @@ EOF echo " $0 --purge-maven-cache --no-maven-cache" echo " $0 -X --integration-tests Run tests with Maven debug output" echo " $0 -o -X Run offline with Maven debug output" + echo " $0 --integration-tests --use-opensearch" exit 1 } @@ -147,6 +150,9 @@ while [ "$1" != "" ]; do shift CONTEXT_SERVER_KARAF_HOME=$1 ;; + --use-opensearch) + USE_OPENSEARCH=true + ;; *) echo "Unknown option: $1" usage @@ -244,7 +250,14 @@ fi # Add profile options PROFILES="" if [ "$RUN_INTEGRATION_TESTS" = true ]; then - PROFILES="$PROFILES,integration-tests,$SEARCH_ENGINE" + if [ "$USE_OPENSEARCH" = true ]; then + MVN_OPTS="$MVN_OPTS -Duse.opensearch=true -P opensearch" + echo "Running integration tests with OpenSearch" + else + MVN_OPTS="$MVN_OPTS -Duse.opensearch=false" + echo "Running integration tests with ElasticSearch" + fi + MVN_OPTS="$MVN_OPTS -P integration-tests" else if [ "$SKIP_TESTS" = true ]; then PROFILES="$PROFILES,!integration-tests,!run-tests" diff --git a/buildAndRun.sh b/buildAndRun.sh deleted file mode 100755 index df085ae5c..000000000 --- a/buildAndRun.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/sh -################################################################################ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ -echo Building... -DIRNAME=`dirname "$0"` -PROGNAME=`basename "$0"` -if [ -f "$DIRNAME/setenv.sh" ]; then - . "$DIRNAME/setenv.sh" -fi -mvn clean install -P integration-tests,rat -if [ $? -ne 0 ] -then - exit 1; -fi -pushd package/target -echo Uncompressing Unomi package... -tar zxvf unomi-$UNOMI_VERSION.tar.gz -cd unomi-$UNOMI_VERSION/bin -echo Apache Unomi features installed, use [unomi:start] to start it. -./karaf debug -popd - diff --git a/buildAndRunNoTests.sh b/buildAndRunNoTests.sh deleted file mode 100755 index e3b2ecea8..000000000 --- a/buildAndRunNoTests.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh -################################################################################ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ -echo Building... -DIRNAME=`dirname "$0"` -PROGNAME=`basename "$0"` -if [ -f "$DIRNAME/setenv.sh" ]; then - . "$DIRNAME/setenv.sh" -fi -mvn clean install -P \!integration-tests,rat,\!run-tests -DskipTests -if [ $? -ne 0 ] -then - exit 1; -fi -pushd package/target -echo Uncompressing Unomi package... -tar zxvf unomi-$UNOMI_VERSION.tar.gz -if [ -f "../../GeoLite2-City.mmdb" ]; then - echo Installing GeoLite2 City database... - cp ../../GeoLite2-City.mmdb unomi-$UNOMI_VERSION/etc -fi -if [ -f "../../allCountries.zip" ]; then - echo Installing Geonames countries database... - cp ../../allCountries.zip unomi-$UNOMI_VERSION/etc -fi -cd unomi-$UNOMI_VERSION/bin -echo echo Apache Unomi features installed, use [unomi:start] to start it. -./karaf debug -popd - diff --git a/compileDeploy.sh b/compileDeploy.sh deleted file mode 100755 index f1a511093..000000000 --- a/compileDeploy.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -################################################################################ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ -echo Setting up environment... -DIRNAME=`dirname "$0"` -PROGNAME=`basename "$0"` -if [ -f "$DIRNAME/setenv.sh" ]; then - . "$DIRNAME/setenv.sh" -fi -if [ "x$CONTEXT_SERVER_KARAF_HOME" = "x" ]; then - CONTEXT_SERVER_KARAF_HOME=~/java/deployments/context-server/apache-karaf-$KARAF_VERSION - export CONTEXT_SERVER_KARAF_HOME -fi -echo Compiling... -mvn clean install -echo Deploying KAR package to $CONTEXT_SERVER_KARAF_HOME/deploy... -cp kar/target/unomi-kar-$UNOMI_VERSION.kar $CONTEXT_SERVER_KARAF_HOME/deploy/ -echo Purging Karaf local Maven repository, exploded KAR directory and temporary directory... -rm -rf $CONTEXT_SERVER_KARAF_HOME/data/maven/repository/* -rm -rf $CONTEXT_SERVER_KARAF_HOME/data/tmp/* -echo Compilation and deployment completed successfully. diff --git a/generate-package.sh b/generate-package.sh deleted file mode 100755 index 73084b931..000000000 --- a/generate-package.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh -################################################################################ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -################################################################################ -echo Building... -mvn clean install -P !integration-tests,rat -echo Package building completed. From 88bfdc188350ca39690c22dae4791b567fdcfb33 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Fri, 20 Dec 2024 16:36:09 +0100 Subject: [PATCH 12/58] - Add new conditions bundle for ElasticSearch-specific conditions - Replace hardcoded past event ES query builder in pasteventconditionbuilder to use a generic interface - Replace GeoDistance and DistanceUnit used directly from ElasticSearch with clean-room implementation that are validated through unit tests. Also added unit tests on the ElasticSearch implementation to be able to test any differences - Also added clean-room implementation of the DateMathParser so that it can be used with ElasticSearch or OpenSearch - Modified Unomi startup mechanism to use features instead of bundles. Unfortunately due to complex interdependencies between bundles the features could not be split as wanted, so there is some duplication in the list of bundles. - Removed last of inter-dependencies in the base plugin and the persistence-spi to try to resolve bundle inter-dependencies but that wasn't enough. - ElasticSearch integration tests are now execute without any errors ! --- .../java/org/apache/unomi/api/GeoPoint.java | 1 - build.sh | 13 - kar/src/main/feature/feature.xml | 24 +- .../asciidoc/builtin-condition-types.adoc | 4 +- manual/src/main/asciidoc/writing-plugins.adoc | 6 +- persistence-elasticsearch/conditions/pom.xml | 177 +++++++++ .../BooleanConditionESQueryBuilder.java | 6 +- ...ByPointSessionConditionESQueryBuilder.java | 6 +- .../IdsConditionESQueryBuilder.java | 6 +- .../MatchAllConditionESQueryBuilder.java | 6 +- .../NestedConditionESQueryBuilder.java | 6 +- .../NotConditionESQueryBuilder.java | 6 +- .../PastEventConditionESQueryBuilder.java | 13 +- .../PropertyConditionESQueryBuilder.java | 8 +- ...eEventPropertyConditionESQueryBuilder.java | 8 +- .../OSGI-INF/blueprint/blueprint.xml | 136 +++++++ persistence-elasticsearch/core/pom.xml | 2 +- .../ConditionESQueryBuilder.java | 2 +- .../ConditionESQueryBuilderDispatcher.java | 2 +- .../ElasticSearchPersistenceServiceImpl.java | 11 +- .../OSGI-INF/blueprint/blueprint.xml | 4 +- .../elasticsearch/geo/DistanceUnitTest.java | 121 +++++++ .../elasticsearch/geo/GeoDistanceTest.java | 59 +++ persistence-elasticsearch/pom.xml | 1 + persistence-opensearch/conditions/pom.xml | 7 - .../BooleanConditionOSQueryBuilder.java | 6 +- ...ByPointSessionConditionOSQueryBuilder.java | 6 +- .../IdsConditionOSQueryBuilder.java | 6 +- .../MatchAllConditionOSQueryBuilder.java | 6 +- .../NestedConditionOSQueryBuilder.java | 6 +- .../NotConditionOSQueryBuilder.java | 6 +- .../PastEventConditionOSQueryBuilder.java | 13 +- .../PropertyConditionOSQueryBuilder.java | 10 +- ...eEventPropertyConditionOSQueryBuilder.java | 6 +- .../OSGI-INF/blueprint/blueprint.xml | 41 ++- persistence-opensearch/core/pom.xml | 2 +- .../ConditionOSQueryBuilder.java | 2 +- .../ConditionOSQueryBuilderDispatcher.java | 2 +- .../OpenSearchPersistenceServiceImpl.java | 3 +- .../OSGI-INF/blueprint/blueprint.xml | 4 +- .../persistence/spi/conditions/DateUtils.java | 54 +++ ...EventConditionPersistenceQueryBuilder.java | 31 ++ .../datemath/DateMathParseException.java | 38 ++ .../conditions/datemath/DateMathParser.java | 257 +++++++++++++ .../datemath/JavaDateFormatter.java | 339 ++++++++++++++++++ .../spi/conditions/geo/DistanceUnit.java | 163 +++++++++ .../spi/conditions/geo/GeoDistance.java | 102 ++++++ .../{ => spi}/PropertyHelperTest.java | 3 +- .../datemath/DateMathParserTest.java | 192 ++++++++++ .../datemath/JavaDateFormatterTest.java | 164 +++++++++ .../spi/conditions/geo/DistanceUnitTest.java | 136 +++++++ .../spi/conditions/geo/GeoDistanceTest.java | 56 +++ plugins/baseplugin/pom.xml | 6 - ...ationByPointSessionConditionEvaluator.java | 4 +- .../PastEventConditionEvaluator.java | 10 +- .../PropertyConditionEvaluator.java | 44 +-- .../OSGI-INF/blueprint/blueprint.xml | 85 +---- .../HoverEventConditionESQueryBuilder.java | 4 +- 58 files changed, 2186 insertions(+), 256 deletions(-) create mode 100644 persistence-elasticsearch/conditions/pom.xml rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/BooleanConditionESQueryBuilder.java (93%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java (92%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/IdsConditionESQueryBuilder.java (90%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/MatchAllConditionESQueryBuilder.java (84%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/NestedConditionESQueryBuilder.java (89%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/NotConditionESQueryBuilder.java (85%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/PastEventConditionESQueryBuilder.java (96%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/PropertyConditionESQueryBuilder.java (97%) rename {plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin => persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch}/conditions/SourceEventPropertyConditionESQueryBuilder.java (91%) create mode 100644 persistence-elasticsearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml rename persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/{conditions => }/ConditionESQueryBuilder.java (95%) rename persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/{conditions => }/ConditionESQueryBuilderDispatcher.java (98%) create mode 100644 persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/DistanceUnitTest.java create mode 100644 persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/GeoDistanceTest.java rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/BooleanConditionOSQueryBuilder.java (93%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java (93%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/IdsConditionOSQueryBuilder.java (89%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/MatchAllConditionOSQueryBuilder.java (84%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/NestedConditionOSQueryBuilder.java (89%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/NotConditionOSQueryBuilder.java (85%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/PastEventConditionOSQueryBuilder.java (96%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/PropertyConditionOSQueryBuilder.java (97%) rename persistence-opensearch/conditions/src/main/java/org/apache/unomi/{ => persistence}/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java (91%) rename persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/{conditions => }/ConditionOSQueryBuilder.java (95%) rename persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/{conditions => }/ConditionOSQueryBuilderDispatcher.java (98%) create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/DateUtils.java create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/PastEventConditionPersistenceQueryBuilder.java create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParseException.java create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParser.java create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatter.java create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnit.java create mode 100644 persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistance.java rename persistence-spi/src/test/java/org/apache/unomi/persistence/{ => spi}/PropertyHelperTest.java (98%) create mode 100644 persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParserTest.java create mode 100644 persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatterTest.java create mode 100644 persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnitTest.java create mode 100644 persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistanceTest.java diff --git a/api/src/main/java/org/apache/unomi/api/GeoPoint.java b/api/src/main/java/org/apache/unomi/api/GeoPoint.java index b3d0d02a6..4472bbe45 100644 --- a/api/src/main/java/org/apache/unomi/api/GeoPoint.java +++ b/api/src/main/java/org/apache/unomi/api/GeoPoint.java @@ -16,7 +16,6 @@ */ package org.apache.unomi.api; - import java.util.Map; /** diff --git a/build.sh b/build.sh index d53030d20..6eccd7069 100755 --- a/build.sh +++ b/build.sh @@ -61,7 +61,6 @@ USE_MAVEN_CACHE=true PURGE_MAVEN_CACHE=false MAVEN_DEBUG=false MAVEN_OFFLINE=false -SEARCH_ENGINE="elasticsearch" KARAF_DEBUG_PORT=5005 KARAF_DEBUG_SUSPEND=n USE_OPENSEARCH=false @@ -90,7 +89,6 @@ EOF echo " --debug-suspend Suspend JVM until debugger connects" echo " --no-maven-cache Disable Maven build cache" echo " --purge-maven-cache Purge local Maven cache before building" - echo " --search-engine ENGINE Set search engine (elasticsearch|opensearch)" echo " --karaf-home PATH Set Karaf home directory for deployment" echo " --use-opensearch Use OpenSearch instead of ElasticSearch for tests" echo "" @@ -142,10 +140,6 @@ while [ "$1" != "" ]; do --purge-maven-cache) PURGE_MAVEN_CACHE=true ;; - --search-engine) - shift - SEARCH_ENGINE=$1 - ;; --karaf-home) shift CONTEXT_SERVER_KARAF_HOME=$1 @@ -175,12 +169,6 @@ if [ "$PURGE_MAVEN_CACHE" = true ]; then echo "Maven cache purged." fi -# Validate search engine value -if [ "$SEARCH_ENGINE" != "elasticsearch" ] && [ "$SEARCH_ENGINE" != "opensearch" ]; then - echo "Invalid search engine: $SEARCH_ENGINE. Must be 'elasticsearch' or 'opensearch'" - exit 1 -fi - # Function to check if command exists command_exists() { command -v "$1" >/dev/null 2>&1 @@ -254,7 +242,6 @@ if [ "$RUN_INTEGRATION_TESTS" = true ]; then MVN_OPTS="$MVN_OPTS -Duse.opensearch=true -P opensearch" echo "Running integration tests with OpenSearch" else - MVN_OPTS="$MVN_OPTS -Duse.opensearch=false" echo "Running integration tests with ElasticSearch" fi MVN_OPTS="$MVN_OPTS -P integration-tests" diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml index f7570ab51..6835ba1a8 100644 --- a/kar/src/main/feature/feature.xml +++ b/kar/src/main/feature/feature.xml @@ -84,15 +84,27 @@ mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/cfg/elasticsearchcfg mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version} + mvn:org.apache.unomi/unomi-services/${project.version} + mvn:org.apache.unomi/unomi-json-schema-services/${project.version} + mvn:org.apache.unomi/unomi-json-schema-rest/${project.version} + mvn:org.apache.unomi/cxs-lists-extension-services/${project.version} + mvn:org.apache.unomi/cxs-lists-extension-rest/${project.version} + mvn:org.apache.unomi/cxs-geonames-services/${project.version} + mvn:org.apache.unomi/cxs-geonames-rest/${project.version} + mvn:org.apache.unomi/cxs-privacy-extension-services/${project.version} + mvn:org.apache.unomi/cxs-privacy-extension-rest/${project.version} + mvn:org.apache.unomi/unomi-persistence-elasticsearch-conditions/${project.version} + mvn:org.apache.unomi/unomi-rest/${project.version} + mvn:org.apache.unomi/unomi-plugins-base/${project.version} + mvn:org.apache.unomi/unomi-plugins-request/${project.version} + mvn:org.apache.unomi/unomi-plugins-mail/${project.version} + mvn:org.apache.unomi/unomi-plugins-optimization-test/${project.version} + mvn:org.apache.unomi/cxs-lists-extension-actions/${project.version} mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version}/cfg/opensearchcfg mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version} - mvn:org.apache.unomi/unomi-persistence-opensearch-conditions/${project.version} - - - mvn:org.apache.unomi/unomi-services/${project.version} mvn:org.apache.unomi/unomi-json-schema-services/${project.version} mvn:org.apache.unomi/unomi-json-schema-rest/${project.version} @@ -102,12 +114,16 @@ mvn:org.apache.unomi/cxs-geonames-rest/${project.version} mvn:org.apache.unomi/cxs-privacy-extension-services/${project.version} mvn:org.apache.unomi/cxs-privacy-extension-rest/${project.version} + mvn:org.apache.unomi/unomi-persistence-opensearch-conditions/${project.version} mvn:org.apache.unomi/unomi-rest/${project.version} mvn:org.apache.unomi/unomi-plugins-base/${project.version} mvn:org.apache.unomi/unomi-plugins-request/${project.version} mvn:org.apache.unomi/unomi-plugins-mail/${project.version} mvn:org.apache.unomi/unomi-plugins-optimization-test/${project.version} mvn:org.apache.unomi/cxs-lists-extension-actions/${project.version} + + + mvn:org.apache.unomi/shell-dev-commands/${project.version} diff --git a/manual/src/main/asciidoc/builtin-condition-types.adoc b/manual/src/main/asciidoc/builtin-condition-types.adoc index 68a484ba7..39e18f873 100644 --- a/manual/src/main/asciidoc/builtin-condition-types.adoc +++ b/manual/src/main/asciidoc/builtin-condition-types.adoc @@ -68,11 +68,11 @@ From https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/res ---- ... + interface="org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder"> - + ... diff --git a/manual/src/main/asciidoc/writing-plugins.adoc b/manual/src/main/asciidoc/writing-plugins.adoc index 7b230499d..f74cb305b 100644 --- a/manual/src/main/asciidoc/writing-plugins.adoc +++ b/manual/src/main/asciidoc/writing-plugins.adoc @@ -519,11 +519,11 @@ src/main/resources/OSGI-INF/blueprint/blueprint.xml xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd"> + interface="org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder"> - + @@ -538,6 +538,6 @@ src/main/resources/OSGI-INF/blueprint/blueprint.xml You can find the implementation of the two classes here : -* https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java[org.apache.unomi.plugins.baseplugin.conditions.MatchAllConditionESQueryBuilder] +* https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java[conditions.org.apache.unomi.persistence.elasticsearch.MatchAllConditionESQueryBuilder] * https://github.com/apache/unomi/blob/master/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionEvaluator.java[org.apache.unomi.plugins.baseplugin.conditions.MatchAllConditionEvaluator] diff --git a/persistence-elasticsearch/conditions/pom.xml b/persistence-elasticsearch/conditions/pom.xml new file mode 100644 index 000000000..26d4462c5 --- /dev/null +++ b/persistence-elasticsearch/conditions/pom.xml @@ -0,0 +1,177 @@ + + + + + 4.0.0 + + + org.apache.unomi + unomi-persistence-elasticsearch + 2.7.0-SNAPSHOT + + + unomi-persistence-elasticsearch-conditions + Apache Unomi :: Persistence :: ElasticSearch :: Conditions + Conditions ElasticSearch persistence implementation for the Apache Unomi Context Server + bundle + + + + org.osgi + osgi.core + provided + + + org.osgi + osgi.cmpn + provided + + + + org.apache.unomi + unomi-api + ${project.version} + provided + + + org.apache.unomi + unomi-common + ${project.version} + provided + + + org.apache.unomi + unomi-persistence-spi + ${project.version} + provided + + + com.google.guava + guava + ${guava.version} + + + + com.fasterxml.jackson.core + jackson-databind + + + + org.apache.commons + commons-lang3 + + + commons-collections + commons-collections + + + commons-io + commons-io + + + + org.apache.unomi + unomi-metrics + ${project.version} + provided + + + + junit + junit + test + + + com.hazelcast + hazelcast-all + 3.12.8 + provided + + + + org.apache.unomi + unomi-scripting + ${project.version} + provided + + + + org.apache.unomi + unomi-persistence-elasticsearch-core + ${project.version} + provided + + + + joda-time + joda-time + 2.12.7 + + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + + android.os;resolution:=optional, + com.conversantmedia.util.concurrent;resolution:=optional, + com.google.appengine.api;resolution:=optional, + com.google.appengine.api.utils;resolution:=optional, + com.google.apphosting.api;resolution:=optional, + jakarta.enterprise.context.spi;resolution:=optional, + jakarta.enterprise.inject.spi;resolution:=optional, + jdk.net;resolution:=optional, + org.apache.avalon.framework.logger;resolution:=optional, + org.apache.log;resolution:=optional, + org.apache.log4j, + org.brotli.dec;resolution:=optional, + org.conscrypt;resolution:=optional, + org.glassfish.hk2.osgiresourcelocator;resolution:=optional, + org.ietf.jgss;resolution:=optional, + org.joda.convert;resolution:=optional, + org.reactivestreams;resolution:=optional, + software.amazon.awssdk.auth.credentials;resolution:=optional, + software.amazon.awssdk.core.async;resolution:=optional, + software.amazon.awssdk.http;resolution:=optional, + software.amazon.awssdk.http.async;resolution:=optional, + software.amazon.awssdk.http.auth.aws.signer;resolution:=optional, + software.amazon.awssdk.http.auth.spi.signer;resolution:=optional, + software.amazon.awssdk.identity.spi;resolution:=optional, + software.amazon.awssdk.regions;resolution:=optional, + software.amazon.awssdk.utils;resolution:=optional, + software.amazon.awssdk.utils.builder;resolution:=optional, + sun.misc;resolution:=optional, + sun.nio.ch;resolution:=optional, + * + + *;scope=compile|runtime + true + + + + + + + + diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/BooleanConditionESQueryBuilder.java similarity index 93% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/BooleanConditionESQueryBuilder.java index fa33b29b6..0da3fcac1 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/BooleanConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/BooleanConditionESQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java similarity index 92% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java index 21d27b127..d77ae0d74 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/GeoLocationByPointSessionConditionESQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/IdsConditionESQueryBuilder.java similarity index 90% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/IdsConditionESQueryBuilder.java index d535c1b65..4999f186a 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/IdsConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/IdsConditionESQueryBuilder.java @@ -14,11 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.IdsQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/MatchAllConditionESQueryBuilder.java similarity index 84% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/MatchAllConditionESQueryBuilder.java index 700286ac4..f1555d689 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/MatchAllConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/MatchAllConditionESQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/NestedConditionESQueryBuilder.java similarity index 89% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/NestedConditionESQueryBuilder.java index e8c3701eb..a6c01c5ea 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NestedConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/NestedConditionESQueryBuilder.java @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.lucene.search.join.ScoreMode; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/NotConditionESQueryBuilder.java similarity index 85% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/NotConditionESQueryBuilder.java index 9574fe82f..1be236f2c 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/NotConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/NotConditionESQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/PastEventConditionESQueryBuilder.java similarity index 96% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/PastEventConditionESQueryBuilder.java index b2481e794..c440793fc 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/PastEventConditionESQueryBuilder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.Event; import org.apache.unomi.api.Profile; @@ -23,18 +23,19 @@ import org.apache.unomi.api.services.DefinitionsService; import org.apache.unomi.api.services.SegmentService; import org.apache.unomi.api.utils.ConditionBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.PastEventConditionPersistenceQueryBuilder; import org.apache.unomi.scripting.ScriptExecutor; import org.elasticsearch.index.query.QueryBuilder; import java.util.*; import java.util.stream.Collectors; -public class PastEventConditionESQueryBuilder implements ConditionESQueryBuilder { +public class PastEventConditionESQueryBuilder implements ConditionESQueryBuilder, PastEventConditionPersistenceQueryBuilder { private DefinitionsService definitionsService; private PersistenceService persistenceService; @@ -117,7 +118,7 @@ public long count(Condition condition, Map context, ConditionESQ } } - protected static boolean getStrategyFromOperator(String operator) { + public boolean getStrategyFromOperator(String operator) { if (operator != null && !operator.equals("eventsOccurred") && !operator.equals("eventsNotOccurred")) { throw new UnsupportedOperationException("Unsupported operator: " + operator + ", please use either 'eventsOccurred' or 'eventsNotOccurred'"); } @@ -198,7 +199,7 @@ private Set getProfileIdsMatchingEventCount(Condition eventCondition, in } } - protected static Condition getEventCondition(Condition condition, Map context, String profileId, + public Condition getEventCondition(Condition condition, Map context, String profileId, DefinitionsService definitionsService, ScriptExecutor scriptExecutor) { Condition eventCondition; try { diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/PropertyConditionESQueryBuilder.java similarity index 97% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/PropertyConditionESQueryBuilder.java index d923d76ad..e4e259661 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/PropertyConditionESQueryBuilder.java @@ -15,13 +15,13 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.commons.lang3.ObjectUtils; import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.index.query.BoolQueryBuilder; @@ -33,7 +33,7 @@ import java.util.*; -import static org.apache.unomi.plugins.baseplugin.conditions.PropertyConditionEvaluator.getDate; +import static org.apache.unomi.persistence.spi.conditions.DateUtils.getDate; public class PropertyConditionESQueryBuilder implements ConditionESQueryBuilder { diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/SourceEventPropertyConditionESQueryBuilder.java similarity index 91% rename from plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java rename to persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/SourceEventPropertyConditionESQueryBuilder.java index 7ba6c6f65..d763e6b03 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/SourceEventPropertyConditionESQueryBuilder.java +++ b/persistence-elasticsearch/conditions/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/SourceEventPropertyConditionESQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.plugins.baseplugin.conditions; +package org.apache.unomi.persistence.elasticsearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; @@ -60,4 +60,4 @@ public QueryBuilder buildQuery(Condition condition, Map context, return null; } } -} \ No newline at end of file +} diff --git a/persistence-elasticsearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-elasticsearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 000000000..8c38cfa96 --- /dev/null +++ b/persistence-elasticsearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder + org.apache.unomi.persistence.spi.conditions.PastEventConditionPersistenceQueryBuilder + + + + + + + + + + + + + + + + + + + + + + + diff --git a/persistence-elasticsearch/core/pom.xml b/persistence-elasticsearch/core/pom.xml index ee5afc77f..21d472288 100644 --- a/persistence-elasticsearch/core/pom.xml +++ b/persistence-elasticsearch/core/pom.xml @@ -297,7 +297,7 @@ org.elasticsearch.*;version="${elasticsearch.version}", org.elasticsearch.index.query.*;version="${elasticsearch.version}", org.apache.lucene.search.join.*;version="${lucene.version}", - org.apache.unomi.persistence.elasticsearch.conditions;version="${project.version}" + org.apache.unomi.persistence.elasticsearch;version="${project.version}" *;scope=compile|runtime true diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilder.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ConditionESQueryBuilder.java similarity index 95% rename from persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilder.java rename to persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ConditionESQueryBuilder.java index 7a100d05a..b1348c3d2 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilder.java +++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ConditionESQueryBuilder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.persistence.elasticsearch.conditions; +package org.apache.unomi.persistence.elasticsearch; import org.apache.unomi.api.conditions.Condition; import org.elasticsearch.index.query.QueryBuilder; diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ConditionESQueryBuilderDispatcher.java similarity index 98% rename from persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java rename to persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ConditionESQueryBuilderDispatcher.java index bed2cb5bc..937d642e9 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/conditions/ConditionESQueryBuilderDispatcher.java +++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ConditionESQueryBuilderDispatcher.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.persistence.elasticsearch.conditions; +package org.apache.unomi.persistence.elasticsearch; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java index a691cf0ae..6ee564a8b 100644 --- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java +++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java @@ -37,7 +37,6 @@ import org.apache.unomi.api.query.NumericRange; import org.apache.unomi.metrics.MetricAdapter; import org.apache.unomi.metrics.MetricsService; -import org.apache.unomi.persistence.elasticsearch.conditions.*; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.*; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; @@ -67,8 +66,8 @@ import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.update.UpdateRequest; -import org.elasticsearch.client.*; import org.elasticsearch.action.update.UpdateResponse; +import org.elasticsearch.client.*; import org.elasticsearch.client.core.CountRequest; import org.elasticsearch.client.core.CountResponse; import org.elasticsearch.client.core.MainResponse; @@ -84,10 +83,14 @@ import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.unit.DistanceUnit; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.*; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.query.*; -import org.elasticsearch.index.reindex.*; +import org.elasticsearch.index.reindex.AbstractBulkByScrollRequest; +import org.elasticsearch.index.reindex.DeleteByQueryRequest; +import org.elasticsearch.index.reindex.UpdateByQueryRequest; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptException; diff --git a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 5dab36ff6..830a6e12d 100644 --- a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -89,7 +89,7 @@ + class="org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher"> @@ -169,7 +169,7 @@ diff --git a/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/DistanceUnitTest.java b/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/DistanceUnitTest.java new file mode 100644 index 000000000..9af49c3e9 --- /dev/null +++ b/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/DistanceUnitTest.java @@ -0,0 +1,121 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.elasticsearch.geo; + +import org.elasticsearch.common.unit.DistanceUnit; +import org.junit.Test; + +import static org.elasticsearch.common.geo.GeoUtils.EARTH_EQUATOR; +import static org.elasticsearch.common.geo.GeoUtils.EARTH_SEMI_MAJOR_AXIS; +import static org.junit.Assert.assertEquals; + +public class DistanceUnitTest { + + + @Test + public void testEarthCircumference() { + assertEquals(EARTH_EQUATOR / DistanceUnit.KILOMETERS.toMeters(1.0), DistanceUnit.KILOMETERS.getEarthCircumference(), 0.0001); + assertEquals(EARTH_EQUATOR, DistanceUnit.METERS.getEarthCircumference(), 0.0001); + } + + @Test + public void testEarthRadius() { + assertEquals(EARTH_SEMI_MAJOR_AXIS / DistanceUnit.MILES.toMeters(1.0), DistanceUnit.MILES.getEarthRadius(), 0.0001); + assertEquals(EARTH_SEMI_MAJOR_AXIS, DistanceUnit.METERS.getEarthRadius(), 0.0001); + } + + @Test + public void testDistancePerDegree() { + assertEquals(EARTH_EQUATOR / 360.0, DistanceUnit.METERS.getDistancePerDegree(), 0.0001); + assertEquals(EARTH_EQUATOR / (360.0 * DistanceUnit.KILOMETERS.toMeters(1.0)), DistanceUnit.KILOMETERS.getDistancePerDegree(), 0.0001); + } + + @Test + public void testToMeters() { + assertEquals(1000.0, DistanceUnit.KILOMETERS.toMeters(1.0), 0.0001); + assertEquals(1609.344, DistanceUnit.MILES.toMeters(1.0), 0.0001); + assertEquals(1.0, DistanceUnit.METERS.toMeters(1.0), 0.0001); + } + + @Test + public void testFromMeters() { + assertEquals(1.0, DistanceUnit.KILOMETERS.fromMeters(1000.0), 0.0001); + assertEquals(1.0, DistanceUnit.MILES.fromMeters(1609.344), 0.0001); + assertEquals(1.0, DistanceUnit.METERS.fromMeters(1.0), 0.0001); + } + + @Test + public void testConvert() { + assertEquals(1.0, DistanceUnit.convert(1.0, DistanceUnit.KILOMETERS, DistanceUnit.KILOMETERS), 0.0001); + assertEquals(1000.0, DistanceUnit.convert(1.0, DistanceUnit.KILOMETERS, DistanceUnit.METERS), 0.0001); + assertEquals(1.0, DistanceUnit.convert(1609.344, DistanceUnit.METERS, DistanceUnit.MILES), 0.0001); + } + + @Test + public void testToString() { + assertEquals("km", DistanceUnit.KILOMETERS.toString()); + assertEquals("mi", DistanceUnit.MILES.toString()); + } + + @Test + public void testParse() { + assertEquals(1.0, DistanceUnit.MILES.parse("1mi", DistanceUnit.METERS), 0.0001); + assertEquals(1609.344, DistanceUnit.METERS.parse("1mi", DistanceUnit.METERS), 0.0001); + assertEquals(1000.0, DistanceUnit.METERS.parse("1km", DistanceUnit.METERS), 0.0001); + assertEquals(1.0, DistanceUnit.KILOMETERS.parse("1km", DistanceUnit.KILOMETERS), 0.0001); + } + + @Test + public void testParseUnit() { + assertEquals(DistanceUnit.KILOMETERS, DistanceUnit.parseUnit("1km", DistanceUnit.METERS)); + assertEquals(DistanceUnit.MILES, DistanceUnit.parseUnit("1mi", DistanceUnit.METERS)); + assertEquals(DistanceUnit.METERS, DistanceUnit.parseUnit("1", DistanceUnit.METERS)); + } + + @Test + public void testDistanceParsing() { + DistanceUnit.Distance distance = DistanceUnit.Distance.parseDistance("1km"); + assertEquals(1.0, distance.value, 0.0001); + assertEquals(DistanceUnit.KILOMETERS, distance.unit); + + DistanceUnit.Distance defaultDistance = DistanceUnit.Distance.parseDistance("100"); + assertEquals(100.0, defaultDistance.value, 0.0001); + assertEquals(DistanceUnit.DEFAULT, defaultDistance.unit); + } + + @Test + public void testDistanceConversion() { + DistanceUnit.Distance distance = new DistanceUnit.Distance(1.0, DistanceUnit.KILOMETERS); + DistanceUnit.Distance converted = distance.convert(DistanceUnit.METERS); + assertEquals(1000.0, converted.value, 0.0001); + assertEquals(DistanceUnit.METERS, converted.unit); + } + + @Test + public void testDistanceEqualsAndHashCode() { + DistanceUnit.Distance d1 = new DistanceUnit.Distance(1.0, DistanceUnit.KILOMETERS); + DistanceUnit.Distance d2 = new DistanceUnit.Distance(1000.0, DistanceUnit.METERS); + assertEquals(d1, d2); + assertEquals(d1.hashCode(), d2.hashCode()); + } + + @Test(expected = IllegalArgumentException.class) + public void testFromStringInvalidUnit() { + DistanceUnit.fromString("invalid"); + } + +} diff --git a/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/GeoDistanceTest.java b/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/GeoDistanceTest.java new file mode 100644 index 000000000..f91666c02 --- /dev/null +++ b/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/geo/GeoDistanceTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.elasticsearch.geo; + +import org.elasticsearch.common.geo.GeoDistance; +import org.elasticsearch.common.unit.DistanceUnit; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class GeoDistanceTest { + + private static final double SRC_LAT = 40.7128; // Example source latitude + private static final double SRC_LON = -74.0060; // Example source longitude + private static final double DST_LAT = 34.0522; // Example destination latitude + private static final double DST_LON = -118.2437; // Example destination longitude + + @Test + public void testFromString() { + assertEquals(GeoDistance.PLANE, GeoDistance.fromString("plane")); + assertEquals(GeoDistance.ARC, GeoDistance.fromString("arc")); + } + + @Test(expected = IllegalArgumentException.class) + public void testFromStringInvalid() { + GeoDistance.fromString("invalid"); + } + + @Test + public void testCalculatePlane() { + // Assuming GeoUtils.planeDistance returns 3940.0 km for the given coordinates + double expectedDistanceInMeters = 3978199.0100920075; + double actualDistance = GeoDistance.PLANE.calculate(SRC_LAT, SRC_LON, DST_LAT, DST_LON, DistanceUnit.METERS); + assertEquals(expectedDistanceInMeters, actualDistance, 0.01); + } + + @Test + public void testCalculateArc() { + // Assuming GeoUtils.arcDistance returns 3971.0 km for the given coordinates + double expectedDistanceInMeters = 3935751.673226063; + double actualDistance = GeoDistance.ARC.calculate(SRC_LAT, SRC_LON, DST_LAT, DST_LON, DistanceUnit.METERS); + assertEquals(expectedDistanceInMeters, actualDistance, 0.01); + } + +} diff --git a/persistence-elasticsearch/pom.xml b/persistence-elasticsearch/pom.xml index 01aa88967..b8980ec0d 100644 --- a/persistence-elasticsearch/pom.xml +++ b/persistence-elasticsearch/pom.xml @@ -32,6 +32,7 @@ core + conditions diff --git a/persistence-opensearch/conditions/pom.xml b/persistence-opensearch/conditions/pom.xml index ae970a3cf..a0364c429 100644 --- a/persistence-opensearch/conditions/pom.xml +++ b/persistence-opensearch/conditions/pom.xml @@ -130,13 +130,6 @@ 2.12.7 - - org.apache.unomi - unomi-plugins-base - ${project.version} - provided - - diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/BooleanConditionOSQueryBuilder.java similarity index 93% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/BooleanConditionOSQueryBuilder.java index 287391f87..034e189d4 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/BooleanConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/BooleanConditionOSQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.BoolQuery; import org.opensearch.client.opensearch._types.query_dsl.Query; import org.slf4j.Logger; diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java similarity index 93% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java index ddc61643a..aeb0a78ff 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/GeoLocationByPointSessionConditionOSQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.Query; import java.util.Map; diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/IdsConditionOSQueryBuilder.java similarity index 89% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/IdsConditionOSQueryBuilder.java index 5697e9a4f..936d6af50 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/IdsConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/IdsConditionOSQueryBuilder.java @@ -14,11 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.Query; import java.util.ArrayList; diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/MatchAllConditionOSQueryBuilder.java similarity index 84% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/MatchAllConditionOSQueryBuilder.java index 7dfdaf35a..16886cfef 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/MatchAllConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/MatchAllConditionOSQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.Query; import java.util.Map; diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/NestedConditionOSQueryBuilder.java similarity index 89% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/NestedConditionOSQueryBuilder.java index 85b839d17..5552a323d 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NestedConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/NestedConditionOSQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.ChildScoreMode; import org.opensearch.client.opensearch._types.query_dsl.Query; diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/NotConditionOSQueryBuilder.java similarity index 85% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/NotConditionOSQueryBuilder.java index cb1f52187..3134a4d20 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/NotConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/NotConditionOSQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.Query; import java.util.Map; diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/PastEventConditionOSQueryBuilder.java similarity index 96% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/PastEventConditionOSQueryBuilder.java index 2eaaffbd5..fb6e0d9e6 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PastEventConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/PastEventConditionOSQueryBuilder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.Event; import org.apache.unomi.api.Profile; @@ -23,18 +23,19 @@ import org.apache.unomi.api.conditions.ConditionType; import org.apache.unomi.api.services.DefinitionsService; import org.apache.unomi.api.services.SegmentService; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.persistence.spi.conditions.PastEventConditionPersistenceQueryBuilder; import org.apache.unomi.scripting.ScriptExecutor; import org.opensearch.client.opensearch._types.query_dsl.Query; import java.util.*; import java.util.stream.Collectors; -public class PastEventConditionOSQueryBuilder implements ConditionOSQueryBuilder { +public class PastEventConditionOSQueryBuilder implements ConditionOSQueryBuilder, PastEventConditionPersistenceQueryBuilder { private DefinitionsService definitionsService; private PersistenceService persistenceService; @@ -115,7 +116,7 @@ public long count(Condition condition, Map context, ConditionOSQ } } - protected static boolean getStrategyFromOperator(String operator) { + public boolean getStrategyFromOperator(String operator) { if (operator != null && !operator.equals("eventsOccurred") && !operator.equals("eventsNotOccurred")) { throw new UnsupportedOperationException("Unsupported operator: " + operator + ", please use either 'eventsOccurred' or 'eventsNotOccurred'"); } @@ -202,7 +203,7 @@ private Set getProfileIdsMatchingEventCount(Condition eventCondition, in } } - protected static Condition getEventCondition(Condition condition, Map context, String profileId, + public Condition getEventCondition(Condition condition, Map context, String profileId, DefinitionsService definitionsService, ScriptExecutor scriptExecutor) { Condition eventCondition; try { diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/PropertyConditionOSQueryBuilder.java similarity index 97% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/PropertyConditionOSQueryBuilder.java index 55b27bf8b..c67719f38 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/PropertyConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/PropertyConditionOSQueryBuilder.java @@ -15,26 +15,26 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.commons.lang3.ObjectUtils; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.opensearch.client.json.JsonData; +import org.opensearch.client.opensearch._types.FieldValue; import org.opensearch.client.opensearch._types.GeoDistanceType; import org.opensearch.client.opensearch._types.query_dsl.BoolQuery; import org.opensearch.client.opensearch._types.query_dsl.Query; -import org.opensearch.client.opensearch._types.FieldValue; import org.opensearch.client.util.ObjectBuilder; import java.util.*; -import static org.apache.unomi.plugins.baseplugin.conditions.PropertyConditionEvaluator.getDate; +import static org.apache.unomi.persistence.spi.conditions.DateUtils.getDate; public class PropertyConditionOSQueryBuilder implements ConditionOSQueryBuilder { diff --git a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java similarity index 91% rename from persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java rename to persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java index d2745f29f..a113421a6 100644 --- a/persistence-opensearch/conditions/src/main/java/org/apache/unomi/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java +++ b/persistence-opensearch/conditions/src/main/java/org/apache/unomi/persistence/opensearch/conditions/SourceEventPropertyConditionOSQueryBuilder.java @@ -15,11 +15,11 @@ * limitations under the License. */ -package org.apache.unomi.opensearch.conditions; +package org.apache.unomi.persistence.opensearch.conditions; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilder; -import org.apache.unomi.persistence.opensearch.conditions.ConditionOSQueryBuilderDispatcher; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder; +import org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher; import org.opensearch.client.opensearch._types.query_dsl.BoolQuery; import org.opensearch.client.opensearch._types.query_dsl.Query; diff --git a/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 48e4c400b..0cb936ac5 100644 --- a/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/persistence-opensearch/conditions/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -51,69 +51,72 @@ + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + - + + + org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder + org.apache.unomi.persistence.spi.conditions.PastEventConditionPersistenceQueryBuilder + - + @@ -125,11 +128,11 @@ + interface="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilder"> - + diff --git a/persistence-opensearch/core/pom.xml b/persistence-opensearch/core/pom.xml index d950d82fc..2e0431f1c 100644 --- a/persistence-opensearch/core/pom.xml +++ b/persistence-opensearch/core/pom.xml @@ -156,7 +156,7 @@ org.opensearch.*;version="${opensearch.version}", org.opensearch.index.query.*;version="${opensearch.version}", org.apache.lucene.search.join.*;version="${lucene.version}", - org.apache.unomi.persistence.opensearch.conditions;version="${project.version}" + org.apache.unomi.persistence.opensearch;version="${project.version}" *;scope=compile|runtime true diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/ConditionOSQueryBuilder.java similarity index 95% rename from persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java rename to persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/ConditionOSQueryBuilder.java index c9012b207..e89ce3d79 100644 --- a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilder.java +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/ConditionOSQueryBuilder.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.persistence.opensearch.conditions; +package org.apache.unomi.persistence.opensearch; import org.apache.unomi.api.conditions.Condition; import org.opensearch.client.opensearch._types.query_dsl.Query; diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/ConditionOSQueryBuilderDispatcher.java similarity index 98% rename from persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java rename to persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/ConditionOSQueryBuilderDispatcher.java index 4f645c047..b5ad16498 100644 --- a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/conditions/ConditionOSQueryBuilderDispatcher.java +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/ConditionOSQueryBuilderDispatcher.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.unomi.persistence.opensearch.conditions; +package org.apache.unomi.persistence.opensearch; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; diff --git a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java index 71269433c..c0b9c4736 100644 --- a/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java +++ b/persistence-opensearch/core/src/main/java/org/apache/unomi/persistence/opensearch/OpenSearchPersistenceServiceImpl.java @@ -37,12 +37,11 @@ import org.apache.unomi.api.query.NumericRange; import org.apache.unomi.metrics.MetricAdapter; import org.apache.unomi.metrics.MetricsService; -import org.apache.unomi.persistence.opensearch.conditions.*; import org.apache.unomi.persistence.spi.CustomObjectMapper; import org.apache.unomi.persistence.spi.PersistenceService; -import org.apache.unomi.persistence.spi.aggregate.*; import org.apache.unomi.persistence.spi.aggregate.DateRangeAggregate; import org.apache.unomi.persistence.spi.aggregate.IpRangeAggregate; +import org.apache.unomi.persistence.spi.aggregate.*; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; diff --git a/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 2536f9e10..72b0a4b9c 100644 --- a/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/persistence-opensearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -94,7 +94,7 @@ + class="org.apache.unomi.persistence.opensearch.ConditionOSQueryBuilderDispatcher"> @@ -162,7 +162,7 @@ diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/DateUtils.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/DateUtils.java new file mode 100644 index 000000000..eac3e358b --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/DateUtils.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions; + +import org.apache.unomi.persistence.spi.conditions.datemath.DateMathParseException; +import org.apache.unomi.persistence.spi.conditions.datemath.DateMathParser; +import org.apache.unomi.persistence.spi.conditions.datemath.JavaDateFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Date; + +public class DateUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(DateUtils.class.getName()); + + public static Date getDate(Object value) { + if (value == null) { + return null; + } + if (value instanceof Date) { + return (Date) value; + } else { + JavaDateFormatter formatter = new JavaDateFormatter("strict_date_optional_time||epoch_millis"); + DateMathParser dateMathParser = new DateMathParser(formatter, DateTimeFormatter.ISO_DATE_TIME); + try { + Instant instant = dateMathParser.parse(value.toString(), System::currentTimeMillis, false, ZoneOffset.UTC); + return Date.from(instant); + } catch (DateMathParseException e) { + LOGGER.warn("unable to parse date. See debug log level for full stacktrace"); + LOGGER.debug("unable to parse date {}", value, e); + } + return null; + } + } + +} diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/PastEventConditionPersistenceQueryBuilder.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/PastEventConditionPersistenceQueryBuilder.java new file mode 100644 index 000000000..909c1dafe --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/PastEventConditionPersistenceQueryBuilder.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions; + +import org.apache.unomi.api.conditions.Condition; +import org.apache.unomi.api.services.DefinitionsService; +import org.apache.unomi.scripting.ScriptExecutor; + +import java.util.Map; + +public interface PastEventConditionPersistenceQueryBuilder { + + boolean getStrategyFromOperator(String operator); + + Condition getEventCondition(Condition condition, Map context, String profileId, + DefinitionsService definitionsService, ScriptExecutor scriptExecutor); +} diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParseException.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParseException.java new file mode 100644 index 000000000..60f5af9be --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParseException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.datemath; + +/** + * Exception thrown by the {@link DateMathParser} when a malformed date math expression is encountered. + */ +public class DateMathParseException extends RuntimeException { + public DateMathParseException(String message) { + super(message); + } + + public DateMathParseException(String message, Throwable cause) { + super(message, cause); + } + + public DateMathParseException(String message, Object... args) { + super(String.format(message, args)); + } + + public DateMathParseException(String message, Throwable cause, Object... args) { + super(String.format(message, args), cause); + } +} diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParser.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParser.java new file mode 100644 index 000000000..95feb6994 --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParser.java @@ -0,0 +1,257 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.datemath; + +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalAdjusters; +import java.time.temporal.TemporalQueries; +import java.util.function.Function; +import java.util.function.LongSupplier; + +public class DateMathParser { + + public static boolean isNullOrEmpty(CharSequence cs) { + return cs == null || cs.length() == 0; + } + + public static class DateFormatters { + public static ZonedDateTime from(TemporalAccessor accessor) { + // Default to UTC if no zone or offset is present + ZoneId zone = accessor.query(TemporalQueries.zone()); + if (zone == null) { + ZoneOffset offset = accessor.query(TemporalQueries.offset()); + zone = (offset != null) ? offset : ZoneOffset.UTC; + } + + // If the accessor supports INSTANT_SECONDS, construct from Instant + if (accessor.isSupported(ChronoField.INSTANT_SECONDS)) { + return ZonedDateTime.ofInstant(Instant.from(accessor), zone); + } + + // Handle LocalDate and LocalTime explicitly + LocalDate date = accessor.query(TemporalQueries.localDate()); + LocalTime time = accessor.query(TemporalQueries.localTime()); + + // Ensure missing components are handled gracefully + if (date == null && time == null) { + throw new DateTimeException("Cannot extract LocalDate or LocalTime from TemporalAccessor"); + } + + if (date == null) { + date = LocalDate.ofEpochDay(0); // Default to 1970-01-01 + } + + if (time == null) { + time = LocalTime.MIDNIGHT; // Default to 00:00 + } + + // Combine LocalDate and LocalTime with ZoneId + return ZonedDateTime.of(date, time, zone); + } + } + + private final JavaDateFormatter formatter; + private final DateTimeFormatter roundUpFormatter; + + public DateMathParser(JavaDateFormatter formatter, DateTimeFormatter roundUpFormatter) { + this.formatter = formatter; + this.roundUpFormatter = roundUpFormatter; + } + + public Instant parse(String text, LongSupplier now, boolean roundUpProperty, ZoneId timeZone) { + Instant time; + String mathString; + if (text.startsWith("now")) { + try { + time = Instant.ofEpochMilli(now.getAsLong()); + } catch (Exception e) { + throw new DateMathParseException("could not read the current timestamp", e); + } + mathString = text.substring("now".length()); + } else { + int index = text.indexOf("||"); + if (index == -1) { + // no math, just parse date + return parseDateTime(text, timeZone, roundUpProperty); + } + time = parseDateTime(text.substring(0, index), timeZone, false); + mathString = text.substring(index + 2); + } + + return parseMath(mathString, time, roundUpProperty, timeZone); + } + + private Instant parseMath(final String mathString, final Instant time, final boolean roundUpProperty, + ZoneId timeZone) throws DateMathParseException { + if (timeZone == null) { + timeZone = ZoneOffset.UTC; + } + ZonedDateTime dateTime = ZonedDateTime.ofInstant(time, timeZone); + int i = 0; + while (i < mathString.length()) { + char c = mathString.charAt(i++); + final boolean round; + final int sign; + if (c == '/') { + round = true; + sign = 1; + } else { + round = false; + if (c == '+') { + sign = 1; + } else if (c == '-') { + sign = -1; + } else { + throw new DateMathParseException("operator not supported for date math [%s]", mathString); + } + } + + if (i >= mathString.length()) { + throw new DateMathParseException("truncated date math [%s]", mathString); + } + + final int num; + int numStart = i; + if (!Character.isDigit(mathString.charAt(i))) { + num = 1; + } else { + while (i < mathString.length() && Character.isDigit(mathString.charAt(i))) { + i++; + } + if (i >= mathString.length()) { + throw new DateMathParseException("truncated date math [%s]", mathString); + } + num = Integer.parseInt(mathString.substring(numStart, i)); + } + if (round && num != 1) { + throw new DateMathParseException("rounding `/` can only be used on single unit types [%s]", mathString); + } + char unit = mathString.charAt(i++); + switch (unit) { + case 'y': + if (round) { + dateTime = dateTime.withDayOfYear(1).with(LocalTime.MIN); + if (roundUpProperty) { + dateTime = dateTime.plusYears(1); + } + } else { + dateTime = dateTime.plusYears(sign * num); + } + break; + case 'M': + if (round) { + dateTime = dateTime.withDayOfMonth(1).with(LocalTime.MIN); + if (roundUpProperty) { + dateTime = dateTime.plusMonths(1); + } + } else { + dateTime = dateTime.plusMonths(sign * num); + } + break; + case 'w': + if (round) { + dateTime = dateTime.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).with(LocalTime.MIN); + if (roundUpProperty) { + dateTime = dateTime.plusWeeks(1); + } + } else { + dateTime = dateTime.plusWeeks(sign * num); + } + break; + case 'd': + if (round) { + dateTime = dateTime.with(LocalTime.MIN); + if (roundUpProperty) { + dateTime = dateTime.plusDays(1); + } + } else { + dateTime = dateTime.plusDays(sign * num); + } + break; + case 'h': + case 'H': + if (round) { + dateTime = dateTime.withMinute(0).withSecond(0).withNano(0); + if (roundUpProperty) { + dateTime = dateTime.plusHours(1); + } + } else { + dateTime = dateTime.plusHours(sign * num); + } + break; + case 'm': + if (round) { + dateTime = dateTime.withSecond(0).withNano(0); + if (roundUpProperty) { + dateTime = dateTime.plusMinutes(1); + } + } else { + dateTime = dateTime.plusMinutes(sign * num); + } + break; + case 's': + if (round) { + dateTime = dateTime.withNano(0); + if (roundUpProperty) { + dateTime = dateTime.plusSeconds(1); + } + } else { + dateTime = dateTime.plusSeconds(sign * num); + } + break; + default: + // Adjust error message to remove the operator sign from the substring + // We know substring from numStart to current i is the "1X" part + // Operator was c, num was parsed, unit is unit + String unitString = mathString.substring(numStart, numStart + Integer.toString(num).length()) + unit; + throw new DateMathParseException("unit [%s] not supported for date math [%s]", unit, unitString); + } + if (round && roundUpProperty) { + // subtract 1 millisecond + dateTime = dateTime.minus(1, ChronoField.MILLI_OF_SECOND.getBaseUnit()); + } + } + return dateTime.toInstant(); + } + + private Instant parseDateTime(String value, ZoneId timeZone, boolean roundUpIfNoTime) { + if (isNullOrEmpty(value)) { + throw new DateMathParseException("cannot parse empty date"); + } + + Function parser = roundUpIfNoTime ? roundUpFormatter::parse : formatter::parse; + try { + TemporalAccessor accessor = parser.apply(value); + + // Convert to ZonedDateTime from accessor + ZonedDateTime zdt = DateFormatters.from(accessor); + if (timeZone != null) { + // Convert to the same instant in the given timeZone + zdt = zdt.withZoneSameInstant(timeZone); + } + return zdt.toInstant(); + } catch (Throwable t) { + throw new DateMathParseException( + "failed to parse date field [%s] with format [%s]: [%s]", + value, formatter, t.getMessage()); + } + } + +} diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatter.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatter.java new file mode 100644 index 000000000..ab2616bf1 --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatter.java @@ -0,0 +1,339 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.datemath; + +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeFormatterBuilder; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalQueries; +import java.util.ArrayList; +import java.util.List; + +public class JavaDateFormatter { + private final List formats; + private final boolean allowEpochMillis; + private final boolean allowEpochSecond; + + public JavaDateFormatter(String formatString) { + this.formats = new ArrayList<>(); + boolean epochMillis = false; + boolean epochSecond = false; + + String[] formatParts = formatString.split("\\|\\|"); + for (String f : formatParts) { + f = f.trim(); + if (f.equals("epoch_millis")) { + formats.add(new FormatDefinition("epoch_millis", f, null)); + epochMillis = true; + } else if (f.equals("epoch_second")) { + formats.add(new FormatDefinition("epoch_second", f, null)); + epochSecond = true; + } else { + formats.add(createFormatDefinition(f)); + } + } + + this.allowEpochMillis = epochMillis; + this.allowEpochSecond = epochSecond; + } + + public TemporalAccessor parse(String input) { + // Numeric check + if (isNumeric(input)) { + long value = Long.parseLong(input); + if (allowEpochMillis && containsFormatName("epoch_millis")) { + return Instant.ofEpochMilli(value); + } + if (allowEpochSecond && containsFormatName("epoch_second")) { + return Instant.ofEpochSecond(value); + } + } + + for (FormatDefinition def : formats) { + try { + String adjusted = adjustForPattern(input, def.pattern); + TemporalAccessor ta = def.formatter.parse(adjusted); + return toInstant(ta, def.formatter.getZone() != null ? def.formatter.getZone() : ZoneOffset.UTC); + } catch (Throwable t) { + // try next + } + } + + throw new DateMathParseException("failed to parse date field [" + input + "] with provided formats"); + } + + private Instant toInstant(TemporalAccessor ta, ZoneId zone) { + boolean hasYear = ta.isSupported(ChronoField.YEAR); + boolean hasMonth = ta.isSupported(ChronoField.MONTH_OF_YEAR); + boolean hasDay = ta.isSupported(ChronoField.DAY_OF_MONTH); + boolean hasDoY = ta.isSupported(ChronoField.DAY_OF_YEAR); + boolean hasHour = ta.isSupported(ChronoField.HOUR_OF_DAY); + boolean hasMinute = ta.isSupported(ChronoField.MINUTE_OF_HOUR); + boolean hasSecond = ta.isSupported(ChronoField.SECOND_OF_MINUTE); + + LocalDate date; + if (hasYear && hasMonth && hasDay) { + // Normal date + date = LocalDate.from(ta); + } else if (hasYear && hasDoY) { + // Ordinal date: year + dayOfYear + int year = ta.get(ChronoField.YEAR); + int dayOfYear = ta.get(ChronoField.DAY_OF_YEAR); + date = LocalDate.ofYearDay(year, dayOfYear); + } else if (!hasYear && (hasHour || hasMinute || hasSecond)) { + // Time only → 1970-01-01 + date = LocalDate.ofEpochDay(0); + } else if (hasYear && !hasMonth && !hasDay && !hasDoY) { + // Year only → yyyy means yyyy-01-01 + int year = ta.get(ChronoField.YEAR); + date = LocalDate.of(year, 1, 1); + } else { + // Maybe week-based fields or partial fields: + // Attempt ZonedDateTime directly if possible + try { + return ZonedDateTime.from(ta).toInstant(); + } catch (DateTimeException e) { + // If fails, handle week-based or incomplete dates + if (ta.isSupported(ChronoField.YEAR_OF_ERA)) { + throw new DateMathParseException("Week-based date formats need additional logic."); + } + // Default to epoch day + date = LocalDate.ofEpochDay(0); + } + } + + int hour = hasHour ? ta.get(ChronoField.HOUR_OF_DAY) : 0; + int minute = hasMinute ? ta.get(ChronoField.MINUTE_OF_HOUR) : 0; + int second = hasSecond ? ta.get(ChronoField.SECOND_OF_MINUTE) : 0; + int nano = ta.isSupported(ChronoField.NANO_OF_SECOND) ? ta.get(ChronoField.NANO_OF_SECOND) : 0; + + LocalTime time = LocalTime.of(hour, minute, second, nano); + + // Handle zone and offset explicitly + ZoneOffset offset = ta.query(TemporalQueries.offset()); + if (offset != null) { + return ZonedDateTime.of(date, time, offset).toInstant(); + } + + // Fall back to provided zone + return ZonedDateTime.of(date, time, zone).toInstant(); + } + + private String adjustForPattern(String input, String pattern) { + // If pattern is strict_date_* and only date is given, append midnight + if (pattern.contains("strict_date") && input.matches("^\\d{4}-\\d{2}-\\d{2}$")) { + return input + "T00:00:00Z"; + } + return input; + } + + private boolean isNumeric(String s) { + if (s.isEmpty()) return false; + for (char c : s.toCharArray()) { + if (!Character.isDigit(c)) return false; + } + return true; + } + + private boolean containsFormatName(String name) { + return formats.stream().anyMatch(def -> def.name.equals(name)); + } + + private FormatDefinition createFormatDefinition(String f) { + // Known patterns from documentation: + // We'll define exact patterns for each built-in format: + switch (f) { + // Already handled: epoch_millis, epoch_second + case "strict_date_optional_time": + case "date_optional_time": + // yyyy-MM-dd or yyyy-MM-dd'T'HH:mm:ss.SSSX + return fmt(f, "yyyy-MM-dd['T'HH:mm:ss[.SSS][XXX]]"); + + case "strict_date_optional_time_nanos": + // Nanosecond resolution: allow up to 9 fractional digits: .SSSSSSSSS + return fmt(f, "yyyy-MM-dd['T'HH:mm:ss[.SSSSSSSSS]][X]"); + + case "basic_date": + return fmt(f, "yyyyMMdd"); + case "basic_date_time": + return fmt(f, "yyyyMMdd'T'HHmmss.SSSX"); + case "basic_date_time_no_millis": + return fmt(f, "yyyyMMdd'T'HHmmssX"); + case "basic_ordinal_date": + return fmt(f, "yyyyDDD"); + case "basic_ordinal_date_time": + return fmt(f, "yyyyDDD'T'HHmmss.SSSX"); + case "basic_ordinal_date_time_no_millis": + return fmt(f, "yyyyDDD'T'HHmmssX"); + case "basic_time": + return fmt(f, "HHmmss.SSSX"); + case "basic_time_no_millis": + return fmt(f, "HHmmssX"); + case "basic_t_time": + return fmt(f, "'T'HHmmss.SSSX"); + case "basic_t_time_no_millis": + return fmt(f, "'T'HHmmssX"); + + // Week-based formats: + // Week dates require 'YYYY' for weekyear, 'ww' for week of year, and 'e' for day of week. + // Example: basic_week_date: xxxx'W'wwe + // We'll assume ISO week date parsing works with pattern: + case "basic_week_date": + case "strict_basic_week_date": + return fmt(f, "xxxx'W'wwe"); + case "basic_week_date_time": + case "strict_basic_week_date_time": + return fmt(f, "xxxx'W'wwe'T'HHmmss.SSSX"); + case "basic_week_date_time_no_millis": + case "strict_basic_week_date_time_no_millis": + return fmt(f, "xxxx'W'wwe'T'HHmmssX"); + + case "date": + case "strict_date": + return fmt(f, "yyyy-MM-dd"); + case "date_hour": + case "strict_date_hour": + return fmt(f, "yyyy-MM-dd'T'HH"); + case "date_hour_minute": + case "strict_date_hour_minute": + return fmt(f, "yyyy-MM-dd'T'HH:mm"); + case "date_hour_minute_second": + case "strict_date_hour_minute_second": + return fmt(f, "yyyy-MM-dd'T'HH:mm:ss"); + case "date_hour_minute_second_fraction": + case "strict_date_hour_minute_second_fraction": + return fmt(f, "yyyy-MM-dd'T'HH:mm:ss.SSS"); + case "date_hour_minute_second_millis": + case "strict_date_hour_minute_second_millis": + // same as fraction? + return fmt(f, "yyyy-MM-dd'T'HH:mm:ss.SSS"); + case "date_time": + case "strict_date_time": + return fmt(f, "yyyy-MM-dd'T'HH:mm:ss.SSSX"); + case "date_time_no_millis": + case "strict_date_time_no_millis": + return fmt(f, "yyyy-MM-dd'T'HH:mm:ssXXX"); + + case "hour": + case "strict_hour": + return fmt(f, "HH"); + case "hour_minute": + case "strict_hour_minute": + return fmt(f, "HH:mm"); + case "hour_minute_second": + case "strict_hour_minute_second": + return fmt(f, "HH:mm:ss"); + case "hour_minute_second_fraction": + case "strict_hour_minute_second_fraction": + return fmt(f, "HH:mm:ss.SSS"); + case "hour_minute_second_millis": + case "strict_hour_minute_second_millis": + return fmt(f, "HH:mm:ss.SSS"); + case "ordinal_date": + case "strict_ordinal_date": + return fmt(f, "yyyy-DDD"); + case "ordinal_date_time": + case "strict_ordinal_date_time": + return fmt(f, "yyyy-DDD'T'HH:mm:ss.SSSX"); + case "ordinal_date_time_no_millis": + case "strict_ordinal_date_time_no_millis": + return fmt(f, "yyyy-DDD'T'HH:mm:ssX"); + case "time": + case "strict_time": + return fmt(f, "HH:mm:ss.SSSX"); + case "time_no_millis": + case "strict_time_no_millis": + return fmt(f, "HH:mm:ssX"); + case "t_time": + case "strict_t_time": + return fmt(f, "'T'HH:mm:ss.SSSX"); + case "t_time_no_millis": + case "strict_t_time_no_millis": + return fmt(f, "'T'HH:mm:ssX"); + case "week_date": + case "strict_week_date": + return fmt(f, "YYYY-'W'ww-e"); + case "week_date_time": + case "strict_week_date_time": + return fmt(f, "YYYY-'W'ww-e'T'HH:mm:ss.SSSX"); + case "week_date_time_no_millis": + case "strict_week_date_time_no_millis": + return fmt(f, "YYYY-'W'ww-e'T'HH:mm:ssX"); + case "weekyear": + case "strict_weekyear": + return fmt(f, "YYYY"); + case "weekyear_week": + case "strict_weekyear_week": + return fmt(f, "YYYY-'W'ww"); + case "weekyear_week_day": + case "strict_weekyear_week_day": + return fmt(f, "YYYY-'W'ww-e"); + case "year": + case "strict_year": + return fmt(f, "yyyy"); + case "year_month": + case "strict_year_month": + return fmt(f, "yyyy-MM"); + case "year_month_day": + case "strict_year_month_day": + return fmt(f, "yyyy-MM-dd"); + + default: + // Custom pattern + return fmt(f, f); + } + } + + private FormatDefinition fmt(String name, String pattern) { + // Apply UTC zone to all and consider using strict resolver if needed + DateTimeFormatter dtf = new DateTimeFormatterBuilder() + .appendPattern(pattern) + .toFormatter() + .withZone(ZoneOffset.UTC); + return new FormatDefinition(name, pattern, dtf); + } + + public static class FormatDefinition { + final String name; + final String pattern; + final DateTimeFormatter formatter; + + public FormatDefinition(String name, String pattern, DateTimeFormatter formatter) { + this.name = name; + this.pattern = pattern; + this.formatter = formatter; + } + + @Override + public String toString() { + return "FormatDefinition{" + + "name='" + name + '\'' + + ", pattern='" + pattern + '\'' + + '}'; + } + } + + + @Override + public String toString() { + return "JavaDateFormatter{" + + "formats=" + formats + + '}'; + } +} diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnit.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnit.java new file mode 100644 index 000000000..292cbd383 --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnit.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.geo; + +import java.util.HashMap; +import java.util.Map; + +public enum DistanceUnit { + KILOMETERS(1000.0, "km", "kilometers"), + MILES(1609.344, "mi", "miles"), + YARDS(0.9144, "yd", "yards"), + FEET(0.3048, "ft", "feet"), + INCHES(0.0254, "in", "inches"), + NAUTICAL_MILES(1852.0, "NM", "nauticalmiles"), + METERS(1.0, "m", "meters"); + + // Constants for Earth's properties + private static final double EARTH_SEMI_MAJOR_AXIS = 6378137.0; // in meters + private static final double EARTH_EQUATOR = 2*Math.PI * EARTH_SEMI_MAJOR_AXIS; // in meters + + private static final Map UNIT_MAP = new HashMap<>(); + + public static final DistanceUnit DEFAULT = METERS; + + static { + for (DistanceUnit unit : values()) { + for (String alias : unit.aliases) { + UNIT_MAP.put(alias.toLowerCase(), unit); + } + } + } + + private final double metersPerUnit; + private final String[] aliases; + + DistanceUnit(double metersPerUnit, String... aliases) { + this.metersPerUnit = metersPerUnit; + this.aliases = aliases; + } + + public double getEarthCircumference() { + return EARTH_EQUATOR / metersPerUnit; + } + + public double getEarthRadius() { + return EARTH_SEMI_MAJOR_AXIS / metersPerUnit; + } + + public double getDistancePerDegree() { + return EARTH_EQUATOR / (360.0 * metersPerUnit); + } + + public double toMeters(double value) { + return value * metersPerUnit; + } + + public double fromMeters(double value) { + return value / metersPerUnit; + } + + public double convert(double value, DistanceUnit toUnit) { + return (value * metersPerUnit) / toUnit.metersPerUnit; + } + + public static double convert(double value, DistanceUnit from, DistanceUnit to) { + return (value * from.metersPerUnit) / to.metersPerUnit; + } + + public static DistanceUnit fromString(String unit) { + if (unit == null || unit.isEmpty()) { + throw new IllegalArgumentException("Unit string must not be null or empty"); + } + DistanceUnit distanceUnit = UNIT_MAP.get(unit.toLowerCase()); + if (distanceUnit == null) { + throw new IllegalArgumentException("Unknown distance unit: " + unit); + } + return distanceUnit; + } + + public static DistanceUnit parseUnit(String distance, DistanceUnit defaultUnit) { + for (DistanceUnit unit : values()) { + for (String alias : unit.aliases) { + if (distance.endsWith(alias)) { + return unit; + } + } + } + return defaultUnit; + } + + public double parse(String distance, DistanceUnit defaultUnit) { + Distance parsed = Distance.parseDistance(distance, defaultUnit); + return convert(parsed.value, parsed.unit, this); + } + + @Override + public String toString() { + return aliases[0]; + } + + public static class Distance { + public final double value; + public final DistanceUnit unit; + + public Distance(double value, DistanceUnit unit) { + this.value = value; + this.unit = unit; + } + + public Distance convert(DistanceUnit toUnit) { + double convertedValue = DistanceUnit.convert(value, unit, toUnit); + return new Distance(convertedValue, toUnit); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Distance other = (Distance) obj; + return Double.compare(DistanceUnit.convert(value, unit, other.unit), other.value) == 0; + } + + @Override + public int hashCode() { + return Double.hashCode(value * unit.metersPerUnit); + } + + @Override + public String toString() { + return value + " " + unit.toString(); + } + + public static Distance parseDistance(String distance) { + return parseDistance(distance, DistanceUnit.METERS); + } + + public static Distance parseDistance(String distance, DistanceUnit defaultUnit) { + for (DistanceUnit unit : values()) { + for (String alias : unit.aliases) { + if (distance.endsWith(alias)) { + String valuePart = distance.substring(0, distance.length() - alias.length()).trim(); + return new Distance(Double.parseDouble(valuePart), unit); + } + } + } + return new Distance(Double.parseDouble(distance), defaultUnit); + } + } +} diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistance.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistance.java new file mode 100644 index 000000000..117671c02 --- /dev/null +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistance.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.geo; + +public enum GeoDistance { + HAVERSINE { + @Override + public double calculate(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit) { + double latRad1 = toRadians(lat1); + double latRad2 = toRadians(lat2); + double deltaLat = toRadians(lat2 - lat1); + double deltaLon = toRadians(lon2 - lon1); + + double a = Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) + + Math.cos(latRad1) * Math.cos(latRad2) + * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + return unit.convert(EARTH_MEAN_RADIUS * c, DistanceUnit.METERS); + } + }, + ARC { + @Override + public double calculate(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit) { + double latRad1 = toRadians(lat1); + double lonRad1 = toRadians(lon1); + double latRad2 = toRadians(lat2); + double lonRad2 = toRadians(lon2); + + double deltaLon = lonRad2 - lonRad1; + + double cosTheta = Math.sin(latRad1) * Math.sin(latRad2) + + Math.cos(latRad1) * Math.cos(latRad2) * Math.cos(deltaLon); + + double theta = Math.acos(Math.min(1.0, Math.max(-1.0, cosTheta))); // Clamp to avoid NaN + return unit.convert(EARTH_MEAN_RADIUS * theta, DistanceUnit.METERS); + } + }, + PLANE { + @Override + public double calculate(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit) { + double x = toRadians(lon2 - lon1) * Math.cos(toRadians((lat1 + lat2) / 2)); + double y = toRadians(lat2 - lat1); + double distance = Math.sqrt(x * x + y * y) * EARTH_MEAN_RADIUS; + return unit.convert(distance, DistanceUnit.METERS); + } + }; + + public static final double EARTH_MEAN_RADIUS = 6371008.7714D; // meters (WGS 84) + + public static final double TO_RADIANS = Math.PI / 180D; + public static final double TO_DEGREES = 180D / Math.PI; + + public static double toRadians(double degrees) { + return degrees * TO_RADIANS; + } + + /** + * Calculate the distance between two geographic points and return it in the specified unit. + * + * @param lat1 Latitude of the first point. + * @param lon1 Longitude of the first point. + * @param lat2 Latitude of the second point. + * @param lon2 Longitude of the second point. + * @param unit The distance unit for the result. + * @return The calculated distance in the specified unit. + */ + public abstract double calculate(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit); + + /** + * Converts a string representation of a GeoDistance method to its corresponding enum. + * + * @param name The string representation of the GeoDistance method (e.g., "plane" or "arc"). + * @return The corresponding GeoDistance enum. + * @throws IllegalArgumentException If the name does not match any known GeoDistance methods. + */ + public static GeoDistance fromString(String name) { + if ("plane".equalsIgnoreCase(name)) { + return PLANE; + } else if ("arc".equalsIgnoreCase(name)) { + return ARC; + } else if ("haversine".equalsIgnoreCase(name)) { + return HAVERSINE; + } else { + throw new IllegalArgumentException("Unknown GeoDistance method: " + name); + } + } +} diff --git a/persistence-spi/src/test/java/org/apache/unomi/persistence/PropertyHelperTest.java b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/PropertyHelperTest.java similarity index 98% rename from persistence-spi/src/test/java/org/apache/unomi/persistence/PropertyHelperTest.java rename to persistence-spi/src/test/java/org/apache/unomi/persistence/spi/PropertyHelperTest.java index 3ee01b395..8be1a6285 100644 --- a/persistence-spi/src/test/java/org/apache/unomi/persistence/PropertyHelperTest.java +++ b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/PropertyHelperTest.java @@ -14,10 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.unomi.persistence; +package org.apache.unomi.persistence.spi; import org.apache.unomi.api.Profile; -import org.apache.unomi.persistence.spi.PropertyHelper; import org.junit.Test; import java.util.Arrays; diff --git a/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParserTest.java b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParserTest.java new file mode 100644 index 000000000..7882a3bff --- /dev/null +++ b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/DateMathParserTest.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.datemath; + +import org.junit.Test; + +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.function.LongSupplier; + +import static org.junit.Assert.*; + +public class DateMathParserTest { + + // Create the JavaDateFormatter with epoch millis support + JavaDateFormatter formatter = new JavaDateFormatter("strict_date_optional_time||epoch_millis"); + + // Round up formatter can be the same or similar: + DateTimeFormatter roundUpFormatter = DateTimeFormatter.ISO_DATE_TIME; + + DateMathParser parser = new DateMathParser(formatter, roundUpFormatter); + + // A fixed "now" supplier returning a fixed timestamp: 2001-01-01T12:00:00Z in epoch millis + private final LongSupplier fixedNow = () -> ZonedDateTime.of(2001, 1, 1, 12, 0, 0, 0, ZoneOffset.UTC).toInstant().toEpochMilli(); + + @Test + public void testNowWithFixedSupplier() { + Instant parsed = parser.parse("now", fixedNow, false, ZoneOffset.UTC); + assertEquals("2001-01-01T12:00:00Z", parsed.toString()); + } + + @Test + public void testNowPlus1HourWithFixedSupplier() { + Instant parsed = parser.parse("now+1h", fixedNow, false, ZoneOffset.UTC); + assertEquals("2001-01-01T13:00:00Z", parsed.toString()); + } + + @Test + public void testNowMinus1HourWithFixedSupplier() { + Instant parsed = parser.parse("now-1h", fixedNow, false, ZoneOffset.UTC); + assertEquals("2001-01-01T11:00:00Z", parsed.toString()); + } + + @Test + public void testRoundingWithRoundUpProperty() { + // now = 2001-01-01T12:00:00Z + // now/d with roundUp = true should round to the beginning of the day + 1 day -1 millisecond + // Actually: rounding sets time to 2001-01-01T00:00:00Z, roundUp would move to 2001-01-02T00:00:00Z, + // and subtract one millisecond → 2001-01-01T23:59:59.999Z + Instant parsed = parser.parse("now/d", fixedNow, true, ZoneOffset.UTC); + // Just before midnight of the next day + assertEquals("2001-01-01T23:59:59.999Z", parsed.toString()); + } + + @Test + public void testRoundingWithoutRoundUpProperty() { + Instant parsed = parser.parse("now/d", fixedNow, false, ZoneOffset.UTC); + // Rounding down to the start of the day: 2001-01-01T00:00:00Z + assertEquals("2001-01-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testFixedDatePlusMonthAndRoundToDay() { + // "2001-02-01||+1M/d" + // start: 2001-02-01T00:00:00Z + // +1M → 2001-03-01T00:00:00Z + // /d rounds to start of day (same day) + Instant parsed = parser.parse("2001-02-01||+1M/d", fixedNow, false, ZoneOffset.UTC); + assertEquals("2001-03-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testInvalidUnit() { + try { + parser.parse("now+1X", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + // "Invalid unit: X" + // Actually from code: "unit [X] not supported for date math [1X]" + // The exact message: + // "unit [X] not supported for date math [1X]" is expected + // The code tries to parse "now+1X" → operator '+' recognized, num=1, unit='X'. + // The mathString is "1X". We'll accept the default message. + assertEquals("unit [X] not supported for date math [1X]", e.getMessage()); + } + } + + @Test + public void testInvalidOperator() { + try { + parser.parse("now*1d", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + // operator not supported + assertEquals("operator not supported for date math [*1d]", e.getMessage()); + } + } + + @Test + public void testTruncatedMath() { + try { + parser.parse("now+", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + // truncated date math + assertEquals("truncated date math [+]", e.getMessage()); + } + } + + @Test + public void testRoundSingleUnitOnly() { + try { + parser.parse("now/2d", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + // rounding `/` can only be used on single unit types + assertEquals("rounding `/` can only be used on single unit types [/2d]", e.getMessage()); + } + } + + @Test + public void testTimeZoneAwareParsing() { + // Parse a date with a different timezone + // We'll pick a date in a different zone and ensure it adjusts if timeZone is provided + Instant parsed = parser.parse("2001-01-01T12:00:00-02:00", fixedNow, false, ZoneOffset.UTC); + // 12:00 at -02:00 is actually 14:00 UTC + assertEquals("2001-01-01T14:00:00Z", parsed.toString()); + } + + @Test + public void testNowWithMultipleOperationsAndRoundUp() { + // now = 2001-01-01T12:00:00Z + // now+1M-1d/d with roundUp = true + // Steps: + // +1M → 2001-02-01T12:00:00Z + // -1d → 2001-01-31T12:00:00Z + // /d with roundUp → round down: 2001-01-31T00:00:00Z plus 1 day = 2001-02-01T00:00:00Z minus 1 ms = 2001-01-31T23:59:59.999Z + Instant parsed = parser.parse("now+1M-1d/d", fixedNow, true, ZoneOffset.UTC); + assertEquals("2001-01-31T23:59:59.999Z", parsed.toString()); + } + + @Test + public void testEmptyDate() { + try { + parser.parse("", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + assertEquals("cannot parse empty date", e.getMessage()); + } + } + + @Test + public void testInvalidExpression() { + // Something like 2022-05-18||invalid + try { + parser.parse("2022-05-18||invalid", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + // operator not supported or truncated math. Actually, 'i' is not recognized as '+', '-', or '/' + // This should fail as "operator not supported for date math [invalid]" + assertEquals("operator not supported for date math [invalid]", e.getMessage()); + } + } + + @Test + public void testFailedToParseDate() { + try { + parser.parse("not-a-date", fixedNow, false, ZoneOffset.UTC); + fail("Expected an exception"); + } catch (DateMathParseException e) { + // "failed to parse date field [not-a-date] with format [strict_date_optional_time]: [Text 'not-a-date' could not be parsed...]" + // Checking just the start of the message: + assertTrue(e.getMessage().startsWith("failed to parse date field [not-a-date] with format")); + } + } +} diff --git a/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatterTest.java b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatterTest.java new file mode 100644 index 000000000..76a52c79e --- /dev/null +++ b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/datemath/JavaDateFormatterTest.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.datemath; + +import org.junit.Test; + +import java.time.Instant; + +import static org.junit.Assert.*; + +/** + * Comprehensive tests for JavaDateFormatter covering various formats: + * - Epoch formats (epoch_millis, epoch_second) + * - ISO-based formats (strict_date_optional_time, strict_date_time_no_millis, etc.) + * - Basic formats (basic_date, basic_date_time, etc.) + * - Ordinal formats (ordinal_date, etc.) + * - Strict vs non-strict variants + * - Custom patterns + * - Fallback between multiple formats + */ +public class JavaDateFormatterTest { + + @Test + public void testEpochMillis() { + // epoch_millis: 978307200000L = 2001-01-01T12:00:00Z + // The expected original code had midnight, let's confirm correct epoch: + // 978307200000 ms = 2001-01-01T12:00:00Z indeed. + JavaDateFormatter formatter = new JavaDateFormatter("epoch_millis"); + Instant parsed = Instant.from(formatter.parse("978307200000")); + assertEquals("2001-01-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testEpochSecond() { + // epoch_second: 978307200 = 2001-01-01T12:00:00Z + JavaDateFormatter formatter = new JavaDateFormatter("epoch_second"); + Instant parsed = Instant.from(formatter.parse("978307200")); + assertEquals("2001-01-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testStrictDateOptionalTime() { + // strict_date_optional_time: "2022-05-18T15:23:17Z" + JavaDateFormatter formatter = new JavaDateFormatter("strict_date_optional_time"); + Instant parsed = Instant.from(formatter.parse("2022-05-18T15:23:17Z")); + assertEquals("2022-05-18T15:23:17Z", parsed.toString()); + } + + @Test + public void testDateOnlyWithStrictDateOptionalTime() { + // strict_date_optional_time: "2022-05-18" should default to midnight + JavaDateFormatter formatter = new JavaDateFormatter("strict_date_optional_time"); + Instant parsed = Instant.from(formatter.parse("2022-05-18")); + assertEquals("2022-05-18T00:00:00Z", parsed.toString()); + } + + @Test + public void testDateTimeNoMillis() { + // date_time_no_millis: "yyyy-MM-dd'T'HH:mm:ssZ" + JavaDateFormatter formatter = new JavaDateFormatter("date_time_no_millis"); + Instant parsed = Instant.from(formatter.parse("2022-05-18T15:23:17+00:00")); + assertEquals("2022-05-18T15:23:17Z", parsed.toString()); + } + + @Test + public void testStrictDateTimeNoMillis() { + // strict_date_time_no_millis: same pattern but strict + JavaDateFormatter formatter = new JavaDateFormatter("strict_date_time_no_millis"); + Instant parsed = Instant.from(formatter.parse("2022-05-18T15:23:17Z")); + assertEquals("2022-05-18T15:23:17Z", parsed.toString()); + } + + @Test + public void testBasicDate() { + // basic_date: yyyyMMdd + // "20010101" = 2001-01-01T00:00:00Z + JavaDateFormatter formatter = new JavaDateFormatter("basic_date"); + Instant parsed = Instant.from(formatter.parse("20010101")); + assertEquals("2001-01-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testBasicDateTime() { + // basic_date_time: yyyyMMdd'T'HHmmss.SSSZ + // "20010101T123000.000Z" = 2001-01-01T12:30:00Z + JavaDateFormatter formatter = new JavaDateFormatter("basic_date_time"); + Instant parsed = Instant.from(formatter.parse("20010101T123000.000Z")); + assertEquals("2001-01-01T12:30:00Z", parsed.toString()); + } + + @Test + public void testOrdinalDate() { + // ordinal_date: yyyy-DDD, e.g. "2001-001" = 2001-01-01 + JavaDateFormatter formatter = new JavaDateFormatter("ordinal_date"); + Instant parsed = Instant.from(formatter.parse("2001-001")); + assertEquals("2001-01-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testOrdinalDateTimeNoMillis() { + // ordinal_date_time_no_millis: yyyy-DDD'T'HH:mm:ssZ + // "2001-001T12:00:00Z" = 2001-01-01T12:00:00Z + JavaDateFormatter formatter = new JavaDateFormatter("ordinal_date_time_no_millis"); + Instant parsed = Instant.from(formatter.parse("2001-001T12:00:00Z")); + assertEquals("2001-01-01T12:00:00Z", parsed.toString()); + } + + @Test + public void testHourMinuteSecond() { + // hour_minute_second: HH:mm:ss + // "12:34:56" with no date = defaults to today's date at that time? + // Our code sets date-only defaults. For time-only, must default to 1970-01-01? + // If not implemented, either skip or fix code to handle pure times. + // Let's assume we default to 1970-01-01 if time only: + JavaDateFormatter formatter = new JavaDateFormatter("hour_minute_second"); + Instant parsed = Instant.from(formatter.parse("12:34:56")); + assertEquals("1970-01-01T12:34:56Z", parsed.toString()); + } + + @Test + public void testCustomPattern() { + // "MM/dd/yyyy": "03/21/2019" = 2019-03-21T00:00:00Z + JavaDateFormatter formatter = new JavaDateFormatter("MM/dd/yyyy"); + Instant parsed = Instant.from(formatter.parse("03/21/2019")); + assertEquals("2019-03-21T00:00:00Z", parsed.toString()); + } + + @Test + public void testFallbackBetweenFormats() { + // If first format doesn't match, second one should + JavaDateFormatter formatter = new JavaDateFormatter("yyyy-MM-dd||epoch_millis"); + // Not a yyyy-MM-dd date, but epoch_millis: + Instant parsed = Instant.from(formatter.parse("978307200000")); + assertEquals("2001-01-01T00:00:00Z", parsed.toString()); + } + + @Test + public void testNoMatch() { + JavaDateFormatter formatter = new JavaDateFormatter("yyyy/MM/dd||basic_date"); + try { + formatter.parse("not-a-date"); + fail("Expected exception"); + } catch (DateMathParseException e) { + assertTrue(e.getMessage().contains("failed to parse date field [not-a-date]")); + } + } + + // Add more tests as needed for strict variants, time_no_millis, t_time, week_date, etc. + // The provided tests give a broad coverage of different formats. +} diff --git a/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnitTest.java b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnitTest.java new file mode 100644 index 000000000..14e727555 --- /dev/null +++ b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/DistanceUnitTest.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.geo; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class DistanceUnitTest { + + // Local constants + /** Earth ellipsoid major axis defined by WGS 84 in meters */ + public static final double EARTH_SEMI_MAJOR_AXIS = 6378137.0; // meters (WGS 84) + + /** Earth ellipsoid minor axis defined by WGS 84 in meters */ + public static final double EARTH_SEMI_MINOR_AXIS = 6356752.314245; // meters (WGS 84) + + /** Earth mean radius defined by WGS 84 in meters */ + public static final double EARTH_MEAN_RADIUS = 6371008.7714D; // meters (WGS 84) + + /** Earth axis ratio defined by WGS 84 (0.996647189335) */ + public static final double EARTH_AXIS_RATIO = EARTH_SEMI_MINOR_AXIS / EARTH_SEMI_MAJOR_AXIS; + + /** Earth ellipsoid equator length in meters */ + public static final double EARTH_EQUATOR = 2*Math.PI * EARTH_SEMI_MAJOR_AXIS; + + /** Earth ellipsoid polar distance in meters */ + public static final double EARTH_POLAR_DISTANCE = Math.PI * EARTH_SEMI_MINOR_AXIS; + + @Test + public void testEarthCircumference() { + assertEquals(EARTH_EQUATOR / DistanceUnit.KILOMETERS.toMeters(1.0), DistanceUnit.KILOMETERS.getEarthCircumference(), 0.0001); + assertEquals(EARTH_EQUATOR, DistanceUnit.METERS.getEarthCircumference(), 0.0001); + } + + @Test + public void testEarthRadius() { + assertEquals(EARTH_SEMI_MAJOR_AXIS / DistanceUnit.MILES.toMeters(1.0), DistanceUnit.MILES.getEarthRadius(), 0.0001); + assertEquals(EARTH_SEMI_MAJOR_AXIS, DistanceUnit.METERS.getEarthRadius(), 0.0001); + } + + @Test + public void testDistancePerDegree() { + assertEquals(EARTH_EQUATOR / 360.0, DistanceUnit.METERS.getDistancePerDegree(), 0.0001); + assertEquals(EARTH_EQUATOR / (360.0 * DistanceUnit.KILOMETERS.toMeters(1.0)), DistanceUnit.KILOMETERS.getDistancePerDegree(), 0.0001); + } + + @Test + public void testToMeters() { + assertEquals(1000.0, DistanceUnit.KILOMETERS.toMeters(1.0), 0.0001); + assertEquals(1609.344, DistanceUnit.MILES.toMeters(1.0), 0.0001); + assertEquals(1.0, DistanceUnit.METERS.toMeters(1.0), 0.0001); + } + + @Test + public void testFromMeters() { + assertEquals(1.0, DistanceUnit.KILOMETERS.fromMeters(1000.0), 0.0001); + assertEquals(1.0, DistanceUnit.MILES.fromMeters(1609.344), 0.0001); + assertEquals(1.0, DistanceUnit.METERS.fromMeters(1.0), 0.0001); + } + + @Test + public void testConvert() { + assertEquals(1.0, DistanceUnit.convert(1.0, DistanceUnit.KILOMETERS, DistanceUnit.KILOMETERS), 0.0001); + assertEquals(1000.0, DistanceUnit.convert(1.0, DistanceUnit.KILOMETERS, DistanceUnit.METERS), 0.0001); + assertEquals(1.0, DistanceUnit.convert(1609.344, DistanceUnit.METERS, DistanceUnit.MILES), 0.0001); + } + + @Test + public void testToString() { + assertEquals("km", DistanceUnit.KILOMETERS.toString()); + assertEquals("mi", DistanceUnit.MILES.toString()); + } + + @Test + public void testParse() { + assertEquals(1.0, DistanceUnit.MILES.parse("1mi", DistanceUnit.METERS), 0.0001); + assertEquals(1609.344, DistanceUnit.METERS.parse("1mi", DistanceUnit.METERS), 0.0001); + assertEquals(1000.0, DistanceUnit.METERS.parse("1km", DistanceUnit.METERS), 0.0001); + assertEquals(1.0, DistanceUnit.KILOMETERS.parse("1km", DistanceUnit.KILOMETERS), 0.0001); + } + + @Test + public void testParseUnit() { + assertEquals(DistanceUnit.KILOMETERS, DistanceUnit.parseUnit("1km", DistanceUnit.METERS)); + assertEquals(DistanceUnit.MILES, DistanceUnit.parseUnit("1mi", DistanceUnit.METERS)); + assertEquals(DistanceUnit.METERS, DistanceUnit.parseUnit("1", DistanceUnit.METERS)); + } + + @Test + public void testDistanceParsing() { + DistanceUnit.Distance distance = DistanceUnit.Distance.parseDistance("1km"); + assertEquals(1.0, distance.value, 0.0001); + assertEquals(DistanceUnit.KILOMETERS, distance.unit); + + DistanceUnit.Distance defaultDistance = DistanceUnit.Distance.parseDistance("100"); + assertEquals(100.0, defaultDistance.value, 0.0001); + assertEquals(DistanceUnit.DEFAULT, defaultDistance.unit); + } + + @Test + public void testDistanceConversion() { + DistanceUnit.Distance distance = new DistanceUnit.Distance(1.0, DistanceUnit.KILOMETERS); + DistanceUnit.Distance converted = distance.convert(DistanceUnit.METERS); + assertEquals(1000.0, converted.value, 0.0001); + assertEquals(DistanceUnit.METERS, converted.unit); + } + + @Test + public void testDistanceEqualsAndHashCode() { + DistanceUnit.Distance d1 = new DistanceUnit.Distance(1.0, DistanceUnit.KILOMETERS); + DistanceUnit.Distance d2 = new DistanceUnit.Distance(1000.0, DistanceUnit.METERS); + assertEquals(d1, d2); + assertEquals(d1.hashCode(), d2.hashCode()); + } + + @Test(expected = IllegalArgumentException.class) + public void testFromStringInvalidUnit() { + DistanceUnit.fromString("invalid"); + } + +} diff --git a/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistanceTest.java b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistanceTest.java new file mode 100644 index 000000000..e8cf785e2 --- /dev/null +++ b/persistence-spi/src/test/java/org/apache/unomi/persistence/spi/conditions/geo/GeoDistanceTest.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.persistence.spi.conditions.geo; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class GeoDistanceTest { + + private static final double SRC_LAT = 40.7128; // Example source latitude + private static final double SRC_LON = -74.0060; // Example source longitude + private static final double DST_LAT = 34.0522; // Example destination latitude + private static final double DST_LON = -118.2437; // Example destination longitude + + @Test + public void testFromString() { + assertEquals(GeoDistance.PLANE, GeoDistance.fromString("plane")); + assertEquals(GeoDistance.ARC, GeoDistance.fromString("arc")); + } + + @Test(expected = IllegalArgumentException.class) + public void testFromStringInvalid() { + GeoDistance.fromString("invalid"); + } + + @Test + public void testCalculatePlane() { + double expectedDistanceInMeters = 3978199.0100920075; + double actualDistance = GeoDistance.PLANE.calculate(SRC_LAT, SRC_LON, DST_LAT, DST_LON, DistanceUnit.METERS); + assertEquals(expectedDistanceInMeters, actualDistance, 0.01); + } + + @Test + public void testCalculateArc() { + double expectedDistanceInMeters = 3935751.673226063; + double actualDistance = GeoDistance.ARC.calculate(SRC_LAT, SRC_LON, DST_LAT, DST_LON, DistanceUnit.METERS); + assertEquals(expectedDistanceInMeters, actualDistance, 0.01); + } + + +} diff --git a/plugins/baseplugin/pom.xml b/plugins/baseplugin/pom.xml index e072e1887..6ec4c65ce 100644 --- a/plugins/baseplugin/pom.xml +++ b/plugins/baseplugin/pom.xml @@ -59,12 +59,6 @@ joda-time provided - - org.apache.unomi - unomi-persistence-elasticsearch-core - ${project.version} - provided - org.apache.unomi unomi-persistence-spi diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java index 7c7d55e17..b98ce9150 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/GeoLocationByPointSessionConditionEvaluator.java @@ -22,8 +22,8 @@ import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; -import org.elasticsearch.common.geo.GeoDistance; -import org.elasticsearch.common.unit.DistanceUnit; +import org.apache.unomi.persistence.spi.conditions.geo.DistanceUnit; +import org.apache.unomi.persistence.spi.conditions.geo.GeoDistance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java index 8caf01322..6d9ce91e1 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionEvaluator.java @@ -25,6 +25,7 @@ import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; +import org.apache.unomi.persistence.spi.conditions.PastEventConditionPersistenceQueryBuilder; import org.apache.unomi.scripting.ScriptExecutor; import java.util.ArrayList; @@ -36,6 +37,7 @@ public class PastEventConditionEvaluator implements ConditionEvaluator { private PersistenceService persistenceService; private DefinitionsService definitionsService; private ScriptExecutor scriptExecutor; + private PastEventConditionPersistenceQueryBuilder pastEventConditionPersistenceQueryBuilder; public void setPersistenceService(PersistenceService persistenceService) { this.persistenceService = persistenceService; @@ -45,6 +47,10 @@ public void setDefinitionsService(DefinitionsService definitionsService) { this.definitionsService = definitionsService; } + public void setPastEventConditionPersistenceQueryBuilder(PastEventConditionPersistenceQueryBuilder pastEventConditionPersistenceQueryBuilder) { + this.pastEventConditionPersistenceQueryBuilder = pastEventConditionPersistenceQueryBuilder; + } + public void setScriptExecutor(ScriptExecutor scriptExecutor) { this.scriptExecutor = scriptExecutor; } @@ -70,10 +76,10 @@ public boolean eval(Condition condition, Item item, Map context, } } else { // TODO see for deprecation, this should not happen anymore each past event condition should have a generatedPropertyKey - count = persistenceService.queryCount(PastEventConditionESQueryBuilder.getEventCondition(condition, context, item.getItemId(), definitionsService, scriptExecutor), Event.ITEM_TYPE); + count = persistenceService.queryCount(pastEventConditionPersistenceQueryBuilder.getEventCondition(condition, context, item.getItemId(), definitionsService, scriptExecutor), Event.ITEM_TYPE); } - boolean eventsOccurred = PastEventConditionESQueryBuilder.getStrategyFromOperator((String) condition.getParameter("operator")); + boolean eventsOccurred = pastEventConditionPersistenceQueryBuilder.getStrategyFromOperator((String) condition.getParameter("operator")); if (eventsOccurred) { int minimumEventCount = parameters.get("minimumEventCount") == null ? 0 : (Integer) parameters.get("minimumEventCount"); int maximumEventCount = parameters.get("maximumEventCount") == null ? Integer.MAX_VALUE : (Integer) parameters.get("maximumEventCount"); diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java index c6e117305..a258b52aa 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PropertyConditionEvaluator.java @@ -21,19 +21,19 @@ import ognl.enhance.ExpressionAccessor; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.unomi.api.*; +import org.apache.unomi.api.Event; +import org.apache.unomi.api.GeoPoint; +import org.apache.unomi.api.Item; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessor; -import org.apache.unomi.scripting.ExpressionFilterFactory; -import org.apache.unomi.scripting.SecureFilteringClassLoader; +import org.apache.unomi.persistence.spi.PropertyHelper; import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluator; import org.apache.unomi.persistence.spi.conditions.ConditionEvaluatorDispatcher; -import org.apache.unomi.persistence.spi.PropertyHelper; -import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.common.joda.Joda; -import org.elasticsearch.common.joda.JodaDateMathParser; -import org.elasticsearch.common.unit.DistanceUnit; +import org.apache.unomi.persistence.spi.conditions.DateUtils; +import org.apache.unomi.persistence.spi.conditions.geo.DistanceUnit; +import org.apache.unomi.plugins.baseplugin.conditions.accessors.HardcodedPropertyAccessor; +import org.apache.unomi.scripting.ExpressionFilterFactory; +import org.apache.unomi.scripting.SecureFilteringClassLoader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +44,8 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.apache.unomi.persistence.spi.conditions.DateUtils.getDate; + /** * Evaluator for property comparison conditions */ @@ -99,7 +101,7 @@ private int compare(Object actualValue, String expectedValue, Object expectedVal private boolean compareValues(Object actualValue, Collection expectedValues, Collection expectedValuesInteger, Collection expectedValuesDouble, Collection expectedValuesDate, Collection expectedValuesDateExpr, String op) { Collection expectedDateExpr = null; if (expectedValuesDateExpr != null) { - expectedDateExpr = expectedValuesDateExpr.stream().map(PropertyConditionEvaluator::getDate).collect(Collectors.toList()); + expectedDateExpr = expectedValuesDateExpr.stream().map(DateUtils::getDate).collect(Collectors.toList()); } @SuppressWarnings("unchecked") Collection expected = ObjectUtils.firstNonNull(expectedValues, expectedValuesDate, expectedValuesInteger, expectedValuesDouble, expectedDateExpr); @@ -306,8 +308,8 @@ protected boolean isMatch(String op, Object actualValue, String expectedValue, O } final GeoPoint expectedCenter = GeoPoint.fromString(centerString); - final DistanceUnit expectedUnit = unitString != null ? DistanceUnit.fromString(unitString) : DistanceUnit.DEFAULT; - final double distanceInMeters = expectedUnit.convert(distance, DistanceUnit.METERS); + final DistanceUnit expectedUnit = unitString != null ? DistanceUnit.fromString(unitString) : DistanceUnit.METERS; + final double distanceInMeters = expectedUnit.toMeters(distance); return expectedCenter.distanceTo(actualCenter) <= distanceInMeters; } @@ -434,24 +436,6 @@ private ExpressionAccessor getPropertyAccessor(Item item, String expression, Ogn return accessor; } - public static Date getDate(Object value) { - if (value == null) { - return null; - } - if (value instanceof Date) { - return ((Date) value); - } else { - JodaDateMathParser parser = new JodaDateMathParser(Joda.forPattern("strictDateOptionalTime||epoch_millis")); - try { - return Date.from(parser.parse(value.toString(), System::currentTimeMillis)); - } catch (ElasticsearchParseException e) { - LOGGER.warn("unable to parse date. See debug log level for full stacktrace"); - LOGGER.debug("unable to parse date {}", value, e); - } - } - return null; - } - @SuppressWarnings("unchecked") private List getValueSet(Object expectedValue) { if (expectedValue instanceof List) { diff --git a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 67a2c537c..64cf0eef1 100644 --- a/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/plugins/baseplugin/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -49,89 +49,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -196,6 +114,7 @@ + diff --git a/plugins/hover-event/src/main/java/org/apache/unomi/plugins/events/hover/querybuilders/HoverEventConditionESQueryBuilder.java b/plugins/hover-event/src/main/java/org/apache/unomi/plugins/events/hover/querybuilders/HoverEventConditionESQueryBuilder.java index 978edef2a..36cc59b99 100644 --- a/plugins/hover-event/src/main/java/org/apache/unomi/plugins/events/hover/querybuilders/HoverEventConditionESQueryBuilder.java +++ b/plugins/hover-event/src/main/java/org/apache/unomi/plugins/events/hover/querybuilders/HoverEventConditionESQueryBuilder.java @@ -18,8 +18,8 @@ package org.apache.unomi.plugins.events.hover.querybuilders; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; -import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilder; +import org.apache.unomi.persistence.elasticsearch.ConditionESQueryBuilderDispatcher; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; From 16c6de9114fee82110534ea13239cc59daadbee5 Mon Sep 17 00:00:00 2001 From: Serge Huber Date: Sun, 22 Dec 2024 10:57:00 +0100 Subject: [PATCH 13/58] Work on making integration tests work with OpenSearch: - Removed elasticsearch-core from bundle watch requirements - Fix issues with date parsing due to case sensitivity - Improved test units for date parsing and date math handling - Modified HealthChecks to provide an OpenSearch check provider (not yet fully working) - Deactivate 1.x to 2.x migration integration test for OpenSearch (No OpenSearch users will be coming from 1.x) - Update OpenSearch past event query builder to latest changes done in ElasticSearch past event query builder - Various fixes in the integration tests to make them compatible with OpenSearch (removed hardcoded elasticsearch configuration and references) - Added new shell script in itests directory to make it easier to handle the dynamically generated Pax Exam Karaf test container directory. Documentation is also included in the README file inside the itests directory. --- .../unomi/healthcheck/HealthCheckConfig.java | 7 +- .../ElasticSearchHealthCheckProvider.java | 5 +- .../OpenSearchHealthCheckProvider.java | 129 ++++++++++++++++++ .../org.apache.unomi.healthcheck.cfg | 11 +- itests/README.md | 51 +++++++ .../java/org/apache/unomi/itests/AllITs.java | 4 +- .../java/org/apache/unomi/itests/BaseIT.java | 7 + ...erIT.java => ConditionQueryBuilderIT.java} | 4 +- .../apache/unomi/itests/HealthCheckIT.java | 54 +------- .../apache/unomi/itests/ProfileServiceIT.java | 14 +- .../ProfileServiceWithoutOverwriteIT.java | 8 +- .../itests/migration/Migrate16xTo220IT.java | 17 +++ .../org.apache.unomi.healthcheck.cfg | 9 +- .../OSGI-INF/blueprint/blueprint.xml | 1 - .../PastEventConditionOSQueryBuilder.java | 66 +++++---- .../META-INF/cxs/mappings/profile.json | 7 + .../persistence/spi/conditions/DateUtils.java | 2 +- .../conditions/datemath/DateMathParser.java | 17 ++- .../datemath/JavaDateFormatter.java | 12 ++ .../datemath/DateMathParserTest.java | 50 +++++++ .../datemath/JavaDateFormatterTest.java | 43 +++++- 21 files changed, 404 insertions(+), 114 deletions(-) create mode 100644 extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/OpenSearchHealthCheckProvider.java rename itests/src/test/java/org/apache/unomi/itests/{ConditionESQueryBuilderIT.java => ConditionQueryBuilderIT.java} (95%) diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java index e86018dc3..9cd7a2662 100644 --- a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/HealthCheckConfig.java @@ -40,7 +40,12 @@ public class HealthCheckConfig { public static final String CONFIG_ES_SSL_ENABLED = "esSSLEnabled"; public static final String CONFIG_ES_LOGIN = "esLogin"; public static final String CONFIG_ES_PASSWORD = "esPassword"; - public static final String CONFIG_TRUST_ALL_CERTIFICATES = "httpClient.trustAllCertificates"; + public static final String CONFIG_ES_TRUST_ALL_CERTIFICATES = "esHttpClient.trustAllCertificates"; + public static final String CONFIG_OS_ADDRESSES = "osAddresses"; + public static final String CONFIG_OS_SSL_ENABLED = "osSSLEnabled"; + public static final String CONFIG_OS_LOGIN = "osLogin"; + public static final String CONFIG_OS_PASSWORD = "osPassword"; + public static final String CONFIG_OS_TRUST_ALL_CERTIFICATES = "osHttpClient.trustAllCertificates"; public static final String CONFIG_AUTH_REALM = "authentication.realm"; public static final String ENABLED = "healthcheck.enabled"; public static final String PROVIDERS = "healthcheck.providers"; diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java index 361e68df7..1dc9e146e 100644 --- a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/ElasticSearchHealthCheckProvider.java @@ -26,11 +26,10 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import org.apache.unomi.healthcheck.HealthCheckConfig; -import org.apache.unomi.healthcheck.HealthCheckResponse; import org.apache.unomi.healthcheck.HealthCheckProvider; +import org.apache.unomi.healthcheck.HealthCheckResponse; import org.apache.unomi.healthcheck.util.CachedValue; import org.apache.unomi.shell.migration.utils.HttpUtils; import org.osgi.service.component.annotations.Activate; @@ -77,7 +76,7 @@ public void activate() { } try { httpClient = HttpUtils.initHttpClient( - Boolean.parseBoolean(config.get(HealthCheckConfig.CONFIG_TRUST_ALL_CERTIFICATES)), credentialsProvider); + Boolean.parseBoolean(config.get(HealthCheckConfig.CONFIG_ES_TRUST_ALL_CERTIFICATES)), credentialsProvider); } catch (IOException e) { LOGGER.error("Unable to initialize http client", e); } diff --git a/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/OpenSearchHealthCheckProvider.java b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/OpenSearchHealthCheckProvider.java new file mode 100644 index 000000000..3524d1daa --- /dev/null +++ b/extensions/healthcheck/src/main/java/org/apache/unomi/healthcheck/provider/OpenSearchHealthCheckProvider.java @@ -0,0 +1,129 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.unomi.healthcheck.provider; + +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpEntity; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.util.EntityUtils; +import org.apache.unomi.healthcheck.HealthCheckConfig; +import org.apache.unomi.healthcheck.HealthCheckProvider; +import org.apache.unomi.healthcheck.HealthCheckResponse; +import org.apache.unomi.healthcheck.util.CachedValue; +import org.apache.unomi.shell.migration.utils.HttpUtils; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * A Health Check that checks the status of the OpenSearch connectivity according to the provided configuration. + * This connectivity should be LIVE before any try to start Unomi. + */ +@Component(service = HealthCheckProvider.class, immediate = true) +public class OpenSearchHealthCheckProvider implements HealthCheckProvider { + + public static final String NAME = "opensearch"; + + private static final Logger LOGGER = LoggerFactory.getLogger(OpenSearchHealthCheckProvider.class.getName()); + private final CachedValue cache = new CachedValue<>(10, TimeUnit.SECONDS); + + @Reference(cardinality = ReferenceCardinality.MANDATORY) + private HealthCheckConfig config; + + private CloseableHttpClient httpClient; + + public OpenSearchHealthCheckProvider() { + LOGGER.info("Building OpenSearch health provider service..."); + } + + @Activate + public void activate() { + LOGGER.info("Activating OpenSearch health provider service..."); + CredentialsProvider credentialsProvider = null; + String login = config.get(HealthCheckConfig.CONFIG_OS_LOGIN); // Reuse ElasticSearch credentials key + if (StringUtils.isNotEmpty(login)) { + credentialsProvider = new BasicCredentialsProvider(); + UsernamePasswordCredentials credentials + = new UsernamePasswordCredentials(login, config.get(HealthCheckConfig.CONFIG_OS_PASSWORD)); + credentialsProvider.setCredentials(AuthScope.ANY, credentials); + } + try { + httpClient = HttpUtils.initHttpClient( + Boolean.parseBoolean(config.get(HealthCheckConfig.CONFIG_OS_TRUST_ALL_CERTIFICATES)), credentialsProvider); + } catch (IOException e) { + LOGGER.error("Unable to initialize http client", e); + } + } + + public void setConfig(HealthCheckConfig config) { + this.config = config; + } + + @Override public String name() { + return NAME; + } + + @Override public HealthCheckResponse execute() { + LOGGER.debug("Health check OpenSearch"); + if (cache.isStaled() || cache.getValue().isDown() || cache.getValue().isError()) { + cache.setValue(refresh()); + } + return cache.getValue(); + } + + private HealthCheckResponse refresh() { + LOGGER.debug("Refresh"); + HealthCheckResponse.Builder builder = new HealthCheckResponse.Builder(); + builder.name(NAME).down(); + String url = (config.get(HealthCheckConfig.CONFIG_ES_SSL_ENABLED).equals("true") ? "https://" : "http://") + .concat(config.get(HealthCheckConfig.CONFIG_ES_ADDRESSES).split(",")[0].trim()) + .concat("/_cluster/health"); + CloseableHttpResponse response = null; + try { + response = httpClient.execute(new HttpGet(url)); + if (response != null && response.getStatusLine().getStatusCode() == 200) { + builder.up(); + HttpEntity entity = response.getEntity(); + if (entity != null && EntityUtils.toString(entity).contains("\"status\":\"green\"")) { + builder.live(); + //TODO parse and add cluster data + } + } + } catch (IOException e) { + builder.error().withData("error", e.getMessage()); + LOGGER.error("Error while checking OpenSearch health", e); + } finally { + if (response != null) { + EntityUtils.consumeQuietly(response.getEntity()); + } + } + return builder.build(); + } +} diff --git a/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg b/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg index 4cbe767eb..b73f7ca4d 100644 --- a/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg +++ b/extensions/healthcheck/src/main/resources/org.apache.unomi.healthcheck.cfg @@ -20,12 +20,19 @@ esAddresses = ${org.apache.unomi.elasticsearch.addresses:-localhost:9200} esSSLEnabled = ${org.apache.unomi.elasticsearch.sslEnable:-false} esLogin = ${org.apache.unomi.elasticsearch.username:-} esPassword = ${org.apache.unomi.elasticsearch.password:-} -httpClient.trustAllCertificates = ${org.apache.unomi.elasticsearch.sslTrustAllCertificates:-false} +esHttpClient.trustAllCertificates = ${org.apache.unomi.elasticsearch.sslTrustAllCertificates:-false} + +# OpenSearch configuration +osAddresses = ${org.apache.unomi.opensearch.addresses:-localhost:9200} +osSSLEnabled = ${org.apache.unomi.opensearch.sslEnable:-true} +osLogin = ${org.apache.unomi.opensearch.username:-admin} +osPassword = ${org.apache.unomi.opensearch.password:-} +osHttpClient.trustAllCertificates = ${org.apache.unomi.opensearch.sslTrustAllCertificates:-true} # Security configuration authentication.realm = ${org.apache.unomi.security.realm:-karaf} # Health check configuration healthcheck.enabled = ${org.apache.unomi.healthcheck.enabled:-false} -healthcheck.providers = ${org.apache.unomi.healthcheck.providers:-cluster,elasticsearch,unomi,persistence} +healthcheck.providers = ${org.apache.unomi.healthcheck.providers:-cluster,elasticsearch,opensearch,unomi,persistence} healthcheck.timeout = ${org.apache.unomi.healthcheck.timeout:-400} diff --git a/itests/README.md b/itests/README.md index 85e5aca2d..c24eee02a 100644 --- a/itests/README.md +++ b/itests/README.md @@ -274,3 +274,54 @@ And the final step is, zipping the new version of the snapshot repository and re > In case you are using docker, do zip in the container and use `docker cp` to get the zip file from the docker container. Now you can modify the migration test class to test that your added data in 1.6.x is correctly migrated in 2.0.0 + +# Integration Tests + +This directory contains the integration tests for Apache Unomi. + +## Karaf Tools + +The `kt.sh` script (short for "Karaf Tools") provides convenient utilities for working with Karaf logs and directories during integration testing. Since Karaf test directories are created with unique UUIDs for each test run, this script helps locate and work with the latest test instance. + +### Usage + +```bash +./kt.sh COMMAND [ARGS] +``` + +### Available Commands + +| Command | Alias | Description | +|-------------|-------|-------------------------------------------------------| +| `log` | `l` | View the latest Karaf log file using less | +| `tail` | `t` | Tail the current Karaf log file | +| `grep` | `g` | Grep the latest Karaf log file (requires pattern) | +| `dir` | `d` | Print the latest Karaf directory path | +| `pushd` | `p` | Change to the latest Karaf directory using pushd | +| `help` | `h` | Show help message | + +### Examples + +```bash +# View log with less +./kt.sh log + +# Tail log file +./kt.sh tail + +# Search for ERROR in log file +./kt.sh grep ERROR + +# Print Karaf directory path +./kt.sh dir + +# Change to Karaf directory +./kt.sh pushd +``` + +### Tips + +- The script automatically finds the most recently created Karaf test directory +- All commands have short aliases (single letter) for faster typing +- Error handling is included for missing directories and files +- The script is particularly useful when debugging integration test failures diff --git a/itests/src/test/java/org/apache/unomi/itests/AllITs.java b/itests/src/test/java/org/apache/unomi/itests/AllITs.java index f415c3ab9..bc6614a17 100644 --- a/itests/src/test/java/org/apache/unomi/itests/AllITs.java +++ b/itests/src/test/java/org/apache/unomi/itests/AllITs.java @@ -17,8 +17,8 @@ package org.apache.unomi.itests; -import org.apache.unomi.itests.migration.Migrate16xTo220IT; import org.apache.unomi.itests.graphql.*; +import org.apache.unomi.itests.migration.Migrate16xTo220IT; import org.apache.unomi.itests.migration.MigrationIT; import org.junit.runner.RunWith; import org.junit.runners.Suite; @@ -35,7 +35,7 @@ MigrationIT.class, BasicIT.class, ConditionEvaluatorIT.class, - ConditionESQueryBuilderIT.class, + ConditionQueryBuilderIT.class, SegmentIT.class, ProfileServiceIT.class, ProfileImportBasicIT.class, diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java index 8e2bece4a..b598195ce 100644 --- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java @@ -293,10 +293,17 @@ public Option[] config() { editConfigurationFilePut("etc/org.ops4j.pax.logging.cfg", "log4j2.rootLogger.level", "INFO"), editConfigurationFilePut("etc/org.apache.karaf.features.cfg", "serviceRequirements", "disable"), editConfigurationFilePut("etc/system.properties", "my.system.property", System.getProperty("my.system.property")), + editConfigurationFilePut("etc/system.properties", SEARCH_ENGINE_PROPERTY, System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH)), editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.graphql.feature.activated", "true"), editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.elasticsearch.cluster.name", "contextElasticSearchITests"), editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.elasticsearch.addresses", "localhost:9400"), editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.elasticsearch.taskWaitingPollingInterval", "50"), + editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.opensearch.cluster.name", "contextElasticSearchITests"), + editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.opensearch.addresses", "localhost:9400"), + editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.opensearch.username", "admin"), + editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.opensearch.password", "Unomi.1ntegrat10n.Tests"), + editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.opensearch.sslEnable", "false"), + editConfigurationFilePut("etc/custom.system.properties", "org.apache.unomi.opensearch.sslTrustAllCertificates", "true"), systemProperty("org.ops4j.pax.exam.rbc.rmi.port").value("1199"), systemProperty("org.apache.unomi.hazelcast.group.name").value("cellar"), diff --git a/itests/src/test/java/org/apache/unomi/itests/ConditionESQueryBuilderIT.java b/itests/src/test/java/org/apache/unomi/itests/ConditionQueryBuilderIT.java similarity index 95% rename from itests/src/test/java/org/apache/unomi/itests/ConditionESQueryBuilderIT.java rename to itests/src/test/java/org/apache/unomi/itests/ConditionQueryBuilderIT.java index 06e57f484..882364db4 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ConditionESQueryBuilderIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ConditionQueryBuilderIT.java @@ -30,13 +30,13 @@ import java.util.List; /** - * Integration tests for various condition query builder types (elasticsearch). + * Integration tests for various condition query builder types (ElasticSearch or OpenSearch). * * @author Sergiy Shyrkov */ @RunWith(PaxExam.class) @ExamReactorStrategy(PerSuite.class) -public class ConditionESQueryBuilderIT extends ConditionEvaluatorIT { +public class ConditionQueryBuilderIT extends ConditionEvaluatorIT { @Override protected boolean eval(Condition c) { diff --git a/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java b/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java index 2ef00efa8..48d48e578 100644 --- a/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/HealthCheckIT.java @@ -17,78 +17,26 @@ package org.apache.unomi.itests; -import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule; -import org.apache.commons.io.IOUtils; -import org.apache.cxf.interceptor.security.AccessDeniedException; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.config.Registry; -import org.apache.http.config.RegistryBuilder; -import org.apache.http.conn.socket.ConnectionSocketFactory; -import org.apache.http.conn.socket.PlainConnectionSocketFactory; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.entity.ContentType; import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; -import org.apache.karaf.itests.KarafTestSupport; -import org.apache.unomi.api.services.DefinitionsService; -import org.apache.unomi.api.services.EventService; -import org.apache.unomi.api.services.ProfileService; -import org.apache.unomi.lifecycle.BundleWatcher; -import org.apache.unomi.persistence.spi.PersistenceService; -import org.junit.After; import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.ops4j.pax.exam.Configuration; -import org.ops4j.pax.exam.CoreOptions; -import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; -import org.ops4j.pax.exam.karaf.options.LogLevelOption.LogLevel; -import org.ops4j.pax.exam.options.MavenArtifactUrlReference; -import org.ops4j.pax.exam.options.extra.VMOption; import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy; import org.ops4j.pax.exam.spi.reactors.PerSuite; -import org.ops4j.pax.exam.util.Filter; -import org.osgi.service.cm.ConfigurationAdmin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.inject.Inject; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.stream.Stream; import static org.junit.Assert.fail; -import static org.ops4j.pax.exam.CoreOptions.systemProperty; -import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*; /** * Health Check Integration Tests @@ -110,7 +58,7 @@ public void testHealthCheck() { LOGGER.info("health check response: {}", response); Assert.assertEquals(5, response.size()); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("karaf") && r.getStatus() == HealthCheckResponse.Status.LIVE)); - Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("elasticsearch") && r.getStatus() == HealthCheckResponse.Status.LIVE)); + Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals(searchEngine) && r.getStatus() == HealthCheckResponse.Status.LIVE)); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("unomi") && r.getStatus() == HealthCheckResponse.Status.LIVE)); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("cluster") && r.getStatus() == HealthCheckResponse.Status.LIVE)); Assert.assertTrue(response.stream().anyMatch(r -> r.getName().equals("persistence") && r.getStatus() == HealthCheckResponse.Status.LIVE)); diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java index 623904938..3313a753d 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceIT.java @@ -154,21 +154,21 @@ public void testGetProfileWithScrolling() throws InterruptedException { public void testGetProfileWithWrongScrollerIdThrowException() throws InterruptedException, NoSuchFieldException, IllegalAccessException, IOException { boolean throwExceptionCurrent = false; - Configuration elasticSearchConfiguration = configurationAdmin.getConfiguration("org.apache.unomi.persistence.elasticsearch"); - if (elasticSearchConfiguration != null && elasticSearchConfiguration.getProperties().get("throwExceptions") != null) { + Configuration searchEngineConfiguration = configurationAdmin.getConfiguration("org.apache.unomi.persistence." + searchEngine); + if (searchEngineConfiguration != null && searchEngineConfiguration.getProperties().get("throwExceptions") != null) { try { - if (elasticSearchConfiguration.getProperties().get("throwExceptions") instanceof String) { - throwExceptionCurrent = Boolean.parseBoolean((String) elasticSearchConfiguration.getProperties().get("throwExceptions")); + if (searchEngineConfiguration.getProperties().get("throwExceptions") instanceof String) { + throwExceptionCurrent = Boolean.parseBoolean((String) searchEngineConfiguration.getProperties().get("throwExceptions")); } else { // already a boolean - throwExceptionCurrent = (Boolean) elasticSearchConfiguration.getProperties().get("throwExceptions"); + throwExceptionCurrent = (Boolean) searchEngineConfiguration.getProperties().get("throwExceptions"); } } catch (Throwable e) { // Not able to cast the property } } - updateConfiguration(PersistenceService.class.getName(), "org.apache.unomi.persistence.elasticsearch", "throwExceptions", true); + updateConfiguration(PersistenceService.class.getName(), "org.apache.unomi.persistence." + searchEngine, "throwExceptions", true); Query query = new Query(); query.setLimit(2); @@ -181,7 +181,7 @@ public void testGetProfileWithWrongScrollerIdThrowException() } catch (RuntimeException ex) { // Should get here since this scenario should throw exception } finally { - updateConfiguration(PersistenceService.class.getName(), "org.apache.unomi.persistence.elasticsearch", "throwExceptions", + updateConfiguration(PersistenceService.class.getName(), "org.apache.unomi.persistence." + searchEngine, "throwExceptions", throwExceptionCurrent); } } diff --git a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceWithoutOverwriteIT.java b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceWithoutOverwriteIT.java index c6d4daeac..6f2b375cb 100644 --- a/itests/src/test/java/org/apache/unomi/itests/ProfileServiceWithoutOverwriteIT.java +++ b/itests/src/test/java/org/apache/unomi/itests/ProfileServiceWithoutOverwriteIT.java @@ -44,10 +44,14 @@ public class ProfileServiceWithoutOverwriteIT extends BaseIT { @Configuration public Option[] config() { + + searchEngine = System.getProperty(SEARCH_ENGINE_PROPERTY, SEARCH_ENGINE_ELASTICSEARCH); + System.out.println("Search Engine: " + searchEngine); + List

    #oV0KEF0)BJzBe`Ws(`TS8;yk>md>;7F2v`f+R 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ⅅ0*l422+Ge>kvUgs#&df^aq}Ys-!B4>_BJY$f6y& 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 a1?P8z`6P35iH(VkJFYut?#Lk({QDokoWiI8 delta 494 zcmXxgyDvj=90leDPR40{(WO||RyZ+0 z?^V^O|0JVSNl2rVOGpttmsa+QseCcTg8(8}zzP!Bzz%ibfO?Rj0UDtRoX`v{-~u;z zzzYhrLK~>ygLdeEPVhq)1fUy&&;udpg)sC%KMX(w24M(>VFaQu3S%%16EF#}N-;HM zC^9c}ivL5>>nWQh+dcDON}4RQdCG5TAu5$wj7kq$@XBDDJnb0F;;U^aVSYPAxK`Z1 zT<&fVZ?ceHPS#V^uXR)EL37g28B5eE+UV_>dGlG5fd;us*4#9&-PT$e7nZ_O`bOl^ IOH=rM0hC6p>Hq)$ diff --git a/itests/src/test/resources/org.apache.unomi.router.cfg b/itests/src/test/resources/org.apache.unomi.router.cfg index 6d121a402..ddcc351b1 100644 --- a/itests/src/test/resources/org.apache.unomi.router.cfg +++ b/itests/src/test/resources/org.apache.unomi.router.cfg @@ -41,9 +41,3 @@ executions.error.report.size=200 #Allowed source endpoints config.allowedEndpoints=file,ftp,sftp,ftps - -# ElasticSearch configuration --elasticsearch.cluster.name=contextElasticSearchITests --elasticsearch.addresses=localhost:9400 -+search.engine.cluster.name=${env:SEARCH_ENGINE_CLUSTER_NAME:-contextElasticSearchITests} -+search.engine.addresses=localhost:9400 \ No newline at end of file diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml index 8dfa504ae..f7570ab51 100644 --- a/kar/src/main/feature/feature.xml +++ b/kar/src/main/feature/feature.xml @@ -16,12 +16,12 @@ ~ limitations under the License. --> - + mvn:org.apache.cxf.karaf/apache-cxf/${cxf.version}/xml/features mvn:org.apache.karaf.cellar/apache-karaf-cellar/${version.karaf.cellar}/xml/features - + wrap aries-blueprint war @@ -33,9 +33,6 @@ eventadmin feature shell-compat - mvn:org.apache.unomi/unomi-wab/${project.version}/cfg/unomicfg - mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/cfg/elasticsearchcfg - mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version}/cfg/opensearchcfg mvn:org.apache.unomi/unomi-plugins-request/${project.version}/cfg/requestcfg mvn:org.apache.unomi/unomi-plugins-base/${project.version}/cfg/pluginsbasecfg mvn:org.apache.unomi/unomi-services/${project.version}/cfg/servicescfg @@ -43,60 +40,86 @@ mvn:org.apache.unomi/unomi-services/${project.version}/cfg/clustercfg mvn:org.apache.unomi/unomi-services/${project.version}/xml/hazelcastconfig mvn:org.apache.unomi/cxs-geonames-services/${project.version}/cfg/geonamescfg - mvn:org.apache.unomi/unomi-groovy-actions-services/${project.version}/cfg/groovyactionscfg mvn:org.apache.unomi/unomi-json-schema-services/${project.version}/cfg/schemacfg - mvn:commons-io/commons-io/${apache.commons.io.version} - mvn:com.fasterxml.jackson.core/jackson-core/${version.jackson.core} - mvn:com.github.fge/btf/1.2 - mvn:com.github.fge/msg-simple/1.1 - mvn:com.google.guava/guava/16.0.1 - mvn:com.github.fge/jackson-coreutils/1.8 - mvn:com.github.fge/json-patch/1.9 - mvn:org.json/json/${org.json.version} - mvn:com.fasterxml.jackson.core/jackson-databind/${version.jackson.databind} - mvn:com.fasterxml.jackson.core/jackson-annotations/${version.jackson.core} - mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${version.jackson.core} - mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${version.jackson.jaxb} - mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${version.jackson.core} - mvn:org.yaml/snakeyaml/1.33 - mvn:com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/${version.jackson.core} - mvn:joda-time/joda-time/${joda-time.version} - mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/2.9.0 - mvn:javax.annotation/javax.annotation-api/1.3.2 - mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsr305/${jsr305.bundle.version} - mvn:commons-collections/commons-collections/${apache.commons.collections.version} - mvn:org.apache.unomi/unomi-lifecycle-watcher/${project.version} - mvn:org.apache.unomi/unomi-api/${project.version} - mvn:org.apache.unomi/unomi-common/${project.version} - mvn:org.apache.unomi/unomi-scripting/${project.version} - mvn:org.apache.unomi/unomi-metrics/${project.version} - mvn:org.apache.unomi/unomi-persistence-spi/${project.version} - mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version} - mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version} - mvn:org.apache.unomi/unomi-persistence-opensearch-conditions/${project.version} - mvn:org.apache.unomi/unomi-services/${project.version} - mvn:org.apache.unomi/unomi-json-schema-services/${project.version} - mvn:org.apache.unomi/unomi-json-schema-rest/${project.version} - mvn:org.apache.unomi/cxs-lists-extension-services/${project.version} - mvn:org.apache.unomi/cxs-lists-extension-rest/${project.version} - mvn:org.apache.unomi/cxs-geonames-services/${project.version} - mvn:org.apache.unomi/cxs-geonames-rest/${project.version} - mvn:org.apache.unomi/cxs-privacy-extension-services/${project.version} - mvn:org.apache.unomi/cxs-privacy-extension-rest/${project.version} - mvn:org.apache.unomi/unomi-rest/${project.version} - mvn:org.apache.unomi/unomi-wab/${project.version} - mvn:org.apache.unomi/unomi-plugins-base/${project.version} - mvn:org.apache.unomi/unomi-plugins-request/${project.version} - mvn:org.apache.unomi/unomi-plugins-mail/${project.version} - mvn:org.apache.unomi/unomi-plugins-optimization-test/${project.version} - mvn:org.apache.unomi/cxs-lists-extension-actions/${project.version} - mvn:org.apache.unomi/shell-dev-commands/${project.version} - mvn:org.apache.unomi/unomi-web-tracker-wab/${project.version} + mvn:commons-io/commons-io/${apache.commons.io.version} + mvn:com.fasterxml.jackson.core/jackson-core/${version.jackson.core} + mvn:com.github.fge/btf/1.2 + mvn:com.github.fge/msg-simple/1.1 + mvn:com.google.guava/guava/16.0.1 + mvn:com.github.fge/jackson-coreutils/1.8 + mvn:com.github.fge/json-patch/1.9 + mvn:org.json/json/${org.json.version} + mvn:com.fasterxml.jackson.core/jackson-databind/${version.jackson.databind} + mvn:com.fasterxml.jackson.datatype/jackson-datatype-jsr310/${version.jackson.databind} + mvn:com.fasterxml.jackson.core/jackson-annotations/${version.jackson.core} + mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-base/${version.jackson.core} + mvn:com.fasterxml.jackson.module/jackson-module-jaxb-annotations/${version.jackson.jaxb} + mvn:com.fasterxml.jackson.jaxrs/jackson-jaxrs-json-provider/${version.jackson.core} + mvn:org.yaml/snakeyaml/1.33 + mvn:com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/${version.jackson.core} + mvn:joda-time/joda-time/${joda-time.version} + mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/2.9.0 + mvn:javax.annotation/javax.annotation-api/1.3.2 + mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jsr305/${jsr305.bundle.version} + mvn:commons-collections/commons-collections/${apache.commons.collections.version} + mvn:org.apache.unomi/unomi-lifecycle-watcher/${project.version} + mvn:org.apache.unomi/unomi-api/${project.version} + mvn:org.apache.unomi/unomi-common/${project.version} + mvn:org.apache.unomi/unomi-scripting/${project.version} + mvn:org.apache.unomi/unomi-metrics/${project.version} + mvn:org.apache.unomi/unomi-persistence-spi/${project.version} + + + + mvn:org.apache.unomi/shell-commands/${project.version}/cfg/migration + mvn:org.apache.unomi/shell-commands/${project.version}/cfg/start + mvn:org.apache.httpcomponents/httpcore-osgi/${httpcore-osgi.version} + mvn:org.apache.httpcomponents/httpclient-osgi/${httpclient-osgi.version} + mvn:org.apache.groovy/groovy/${groovy.version} + mvn:org.apache.groovy/groovy-xml/${groovy.version} + mvn:org.apache.groovy/groovy-json/${groovy.version} + mvn:org.apache.unomi/shell-commands/${project.version} + + + + mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/cfg/elasticsearchcfg + mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version} + + + + mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version}/cfg/opensearchcfg + mvn:org.apache.unomi/unomi-persistence-opensearch-core/${project.version} + mvn:org.apache.unomi/unomi-persistence-opensearch-conditions/${project.version} + + + + mvn:org.apache.unomi/unomi-services/${project.version} + mvn:org.apache.unomi/unomi-json-schema-services/${project.version} + mvn:org.apache.unomi/unomi-json-schema-rest/${project.version} + mvn:org.apache.unomi/cxs-lists-extension-services/${project.version} + mvn:org.apache.unomi/cxs-lists-extension-rest/${project.version} + mvn:org.apache.unomi/cxs-geonames-services/${project.version} + mvn:org.apache.unomi/cxs-geonames-rest/${project.version} + mvn:org.apache.unomi/cxs-privacy-extension-services/${project.version} + mvn:org.apache.unomi/cxs-privacy-extension-rest/${project.version} + mvn:org.apache.unomi/unomi-rest/${project.version} + mvn:org.apache.unomi/unomi-plugins-base/${project.version} + mvn:org.apache.unomi/unomi-plugins-request/${project.version} + mvn:org.apache.unomi/unomi-plugins-mail/${project.version} + mvn:org.apache.unomi/unomi-plugins-optimization-test/${project.version} + mvn:org.apache.unomi/cxs-lists-extension-actions/${project.version} + mvn:org.apache.unomi/shell-dev-commands/${project.version} + + + + mvn:org.apache.unomi/unomi-wab/${project.version}/cfg/unomicfg + mvn:org.apache.unomi/unomi-web-tracker-wab/${project.version} + mvn:org.apache.unomi/unomi-wab/${project.version} + - mvn:org.apache.unomi/shell-commands/${project.version}/cfg/migration - mvn:org.apache.unomi/shell-commands/${project.version} + mvn:org.apache.unomi/healthcheck/${project.version}/cfg/healthcheck - mvn:org.apache.unomi/healthcheck/${project.version} + mvn:org.apache.unomi/healthcheck/${project.version} @@ -105,7 +128,6 @@ - unomi-kar - mvn:org.webjars/swagger-ui/3.23.8 + mvn:org.webjars/swagger-ui/3.23.8 diff --git a/lifecycle-watcher/pom.xml b/lifecycle-watcher/pom.xml index 444db2f3a..47687327f 100644 --- a/lifecycle-watcher/pom.xml +++ b/lifecycle-watcher/pom.xml @@ -40,12 +40,6 @@ ${project.version} provided - - org.apache.karaf.features - org.apache.karaf.features.core - ${version.karaf} - provided - diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java index e4a7069b3..de6fb6ba2 100644 --- a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java +++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java @@ -38,4 +38,8 @@ public interface BundleWatcher { boolean isStartupComplete(); boolean allAdditionalBundleStarted(); + + public void addRequiredBundle(String bundleName); + + public boolean removeRequiredBundle(String bundleName); } diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java index d64f3ac31..34666f467 100644 --- a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java +++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcherImpl.java @@ -17,17 +17,8 @@ package org.apache.unomi.lifecycle; import org.apache.commons.lang3.StringUtils; -import org.apache.karaf.features.FeaturesService; import org.apache.unomi.api.ServerInfo; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleEvent; -import org.osgi.framework.Filter; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceEvent; -import org.osgi.framework.ServiceListener; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.SynchronousBundleListener; +import org.osgi.framework.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,19 +27,8 @@ import java.io.InputStreamReader; import java.net.URL; import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.EnumSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TimerTask; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; +import java.util.*; +import java.util.concurrent.*; import java.util.stream.Collectors; /** @@ -59,15 +39,12 @@ public class BundleWatcherImpl implements SynchronousBundleListener, ServiceList private static final Logger LOGGER = LoggerFactory.getLogger(BundleWatcherImpl.class.getName()); - private static final String CDP_GRAPHQL_FEATURE = "cdp-graphql-feature"; - private long startupTime; private Map requiredBundles = new ConcurrentHashMap<>(); private Map requiredBundlesFromFeatures = new ConcurrentHashMap<>(); private ScheduledExecutorService scheduler; private ScheduledFuture scheduledFuture; - private FeaturesService featuresService; private String requiredServices; private Set requiredServicesFilters = new LinkedHashSet<>(); @@ -79,8 +56,6 @@ public class BundleWatcherImpl implements SynchronousBundleListener, ServiceList private Integer checkStartupStateRefreshInterval = 60; - private Set featuresToInstall = ConcurrentHashMap.newKeySet(); - private boolean installingFeatureStarted = false; private List serverInfos = new ArrayList<>(); public void setRequiredBundles(Map requiredBundles) { @@ -108,13 +83,8 @@ public void setBundleContext(BundleContext bundleContext) { this.bundleContext = bundleContext; } - public void setFeaturesService(FeaturesService featuresService) { - this.featuresService = featuresService; - } - public void init() { scheduler = Executors.newSingleThreadScheduledExecutor(); - prepareGraphQLFeatureToInstall(); checkExistingBundles(); bundleContext.addBundleListener(this); bundleContext.addServiceListener(this); @@ -268,36 +238,6 @@ private void displayLogsForInactiveServices() { }); } - private void prepareGraphQLFeatureToInstall() { - if (Boolean.parseBoolean(bundleContext.getProperty("org.apache.unomi.graphql.feature.activated"))) { - featuresToInstall.add(CDP_GRAPHQL_FEATURE); - requiredBundlesFromFeatures.put("org.apache.unomi.cdp-graphql-api-impl", false); - requiredBundlesFromFeatures.put("org.apache.unomi.graphql-ui", false); - } - } - - public boolean shouldInstallAdditionalFeatures() { - return !featuresToInstall.isEmpty(); - } - - private void installFeatures() { - List installedFeatures = new ArrayList<>(); - featuresToInstall.forEach(value -> { - try { - long featureStartupTime = System.currentTimeMillis(); - if (!featuresService.isInstalled(featuresService.getFeature(value))) { - System.out.println("Installing feature " + value); - featuresService.installFeature(value, EnumSet.of(FeaturesService.Option.NoAutoRefreshManagedBundles, - FeaturesService.Option.NoAutoRefreshUnmanagedBundles, FeaturesService.Option.NoAutoRefreshBundles)); - LOGGER.info("Feature {} successfully installed in {} ms", value, (System.currentTimeMillis() - featureStartupTime)); - } - installedFeatures.add(value); - } catch (Exception e) { - LOGGER.error("Error when installing {} feature", value, e); - } - }); - installedFeatures.forEach(value -> featuresToInstall.remove(value)); - } private TimerTask getBundleCheckTask() { return new TimerTask() { @@ -314,10 +254,6 @@ private TimerTask getAdditionalBundleCheckTask() { return new TimerTask() { @Override public void run() { - if (shouldInstallAdditionalFeatures() && !installingFeatureStarted) { - installingFeatureStarted = true; - installFeatures(); - } displayLogsForInactiveBundles(requiredBundlesFromFeatures); checkStartupComplete(); } @@ -455,4 +391,14 @@ public ServerInfo getBundleServerInfo(Bundle bundle) { } return serverInfo; } + + @Override + public void addRequiredBundle(String bundleName) { + requiredBundlesFromFeatures.put(bundleName, false); + } + + @Override + public boolean removeRequiredBundle(String bundleName) { + return requiredBundlesFromFeatures.remove(bundleName); + } } diff --git a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml index 015e5edbd..9fceda381 100644 --- a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml +++ b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -22,8 +22,6 @@ xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd"> - - @@ -36,7 +34,6 @@ - diff --git a/package/pom.xml b/package/pom.xml index 2a97c02ab..40e9bad13 100644 --- a/package/pom.xml +++ b/package/pom.xml @@ -376,32 +376,9 @@ cellar aries-blueprint shell-compat - unomi-kar - unomi-router-karaf-feature - unomi-groovy-actions - unomi-rest-ui + unomi-base + unomi-startup - 1.8 diff --git a/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/ElasticsearchPersistenceTest.java b/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/ElasticsearchPersistenceTest.java deleted file mode 100644 index c80734f94..000000000 --- a/persistence-elasticsearch/core/src/test/java/org/apache/unomi/persistence/elasticsearch/ElasticsearchPersistenceTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.unomi.persistence.elasticsearch; - -import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; -import org.apache.http.HttpHost; -import org.elasticsearch.action.ActionRequestValidationException; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.core.MainResponse; -import org.elasticsearch.client.indices.CreateIndexRequest; -import org.elasticsearch.client.indices.CreateIndexResponse; -import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.common.network.NetworkModule; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.core.internal.io.IOUtils; -import org.elasticsearch.env.Environment; -import org.elasticsearch.node.MockNode; -import org.elasticsearch.node.Node; -import org.elasticsearch.rest.RestStatus; -import org.elasticsearch.transport.Netty4Plugin; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.UUID; -import java.util.logging.Logger; - -@RunWith(com.carrotsearch.randomizedtesting.RandomizedRunner.class) -@ThreadLeakScope(value = ThreadLeakScope.Scope.NONE) -public class ElasticsearchPersistenceTest { - - private static final Logger logger = Logger.getLogger(ElasticsearchPersistenceTest.class.getName()); - - private static final String CLUSTER_NAME = "unomi-cluster-test"; - private static final String NODE_NAME = "unomi-node-test"; - private static final String HOST = "127.0.0.1"; - private static final int HTTP_PORT_NODE_1 = 9200+10; - private static final int HTTP_PORT_NODE_2 = 9201+10; - private static final int TRANSPORT_PORT_NODE_1 = 9300+10; - private static final int TRANSPORT_PORT_NODE_2 = 9301+10; - - private static RestHighLevelClient restHighLevelClient; - - private static Node node1; - private static Node node2; - - @BeforeClass - public static void setup() throws Exception { - Collection plugins = Arrays.asList(Netty4Plugin.class); - - Settings settingsNode1 = Settings.builder() - .put(ClusterName.CLUSTER_NAME_SETTING.getKey(), CLUSTER_NAME) - .put(Node.NODE_NAME_SETTING.getKey(), NODE_NAME + "-1") - .put(NetworkModule.HTTP_TYPE_KEY, Netty4Plugin.NETTY_HTTP_TRANSPORT_NAME) - .put(Environment.PATH_HOME_SETTING.getKey(), "target/data-1") - .put(Environment.PATH_DATA_SETTING.getKey(), "target/data-1") - .put("network.host", HOST) - .put("http.port", HTTP_PORT_NODE_1) - .put(NetworkModule.TRANSPORT_TYPE_KEY, Netty4Plugin.NETTY_TRANSPORT_NAME) - .put("transport.port", TRANSPORT_PORT_NODE_1) - .build(); - node1 = new MockNode(settingsNode1, plugins); - node1.start(); - - Settings settingsNode2 = Settings.builder() - .put(ClusterName.CLUSTER_NAME_SETTING.getKey(), CLUSTER_NAME) - .put(Node.NODE_NAME_SETTING.getKey(), NODE_NAME + "-2") - .put(NetworkModule.HTTP_TYPE_KEY, Netty4Plugin.NETTY_HTTP_TRANSPORT_NAME) - .put(Environment.PATH_HOME_SETTING.getKey(), "target/data-2") - .put(Environment.PATH_DATA_SETTING.getKey(), "target/data-2") - .put("network.host", HOST) - .put("http.port", HTTP_PORT_NODE_2) - .put(NetworkModule.TRANSPORT_TYPE_KEY, Netty4Plugin.NETTY_TRANSPORT_NAME) - .put("transport.port", TRANSPORT_PORT_NODE_2) - .build(); - node2 = new MockNode(settingsNode2, plugins); - node2.start(); - - restHighLevelClient = new RestHighLevelClient(RestClient.builder( - new HttpHost(HOST, HTTP_PORT_NODE_1, "http"), - new HttpHost(HOST, HTTP_PORT_NODE_2, "http"))); - } - - @AfterClass - public static void teardown() throws Exception { - IOUtils.close(restHighLevelClient); - if (node1 != null) { - node1.close(); - } - if (node2 != null) { - node2.close(); - } - } - - @Test - public void testGetClusterInfo() throws Exception { - MainResponse response = restHighLevelClient.info(RequestOptions.DEFAULT); - logger.info("Cluster getMinimumIndexCompatibilityVersion: " + response.getVersion().getMinimumIndexCompatibilityVersion()); - logger.info("Cluster getMinimumWireCompatibilityVersion: " + response.getVersion().getMinimumWireCompatibilityVersion()); - logger.info("Cluster number: " + response.getVersion().getNumber()); - } - - @Test - public void testCreateIndex() throws Exception { - restHighLevelClient.info(RequestOptions.DEFAULT.toBuilder().addHeader("name", "value").build()); - final String indexName = "unomi-index-" + new Date().getTime(); - CreateIndexRequest request = new CreateIndexRequest(indexName); - CreateIndexResponse response = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT); - if (response.isAcknowledged()) { - logger.info(">>> Create index :: ok :: name = " + response.index()); - } else { - logger.info(">>> Create index :: not acknowledged"); - } - -// ClusterHealthResponse actionGet = restHighLevelClient.cluster() -// .health(Requests.clusterHealthRequest("unomi-index-1").waitForGreenStatus().waitForEvents(Priority.LANGUID) -// .waitForNoRelocatingShards(true), RequestOptions.DEFAULT); -// Assert.assertNotNull(actionGet); -// -// switch (actionGet.getStatus()) { -// case GREEN: -// logger.info(">>> Cluster State :: GREEN"); -// break; -// case YELLOW: -// logger.info(">>> Cluster State :: YELLOW"); -// break; -// case RED: -// logger.info(">>> Cluster State :: RED"); -// break; -// } -// Assert.assertNotEquals(actionGet.getStatus(), ClusterHealthStatus.RED); - - IndexRequest indexRequest = new IndexRequest(indexName); - indexRequest.id(UUID.randomUUID().toString()); - String type = "{\"type\":\"unomi-type\"}"; - String source = "{\"name\":\"unomi-name\"}"; - indexRequest.source(XContentType.JSON, type, source); - ActionRequestValidationException exception = indexRequest.validate(); - Assert.assertNull(exception); - - IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT); - Assert.assertNotNull(indexResponse); - if (indexResponse.status() == RestStatus.CREATED) { - logger.info(">>> Insert data created"); - } else { - logger.info(">>> Insert data ko :: " + indexResponse.status().name()); - } - Assert.assertEquals(indexResponse.status(), RestStatus.CREATED); - } - -} diff --git a/persistence-spi/pom.xml b/persistence-spi/pom.xml index 337004450..1e108cdd3 100644 --- a/persistence-spi/pom.xml +++ b/persistence-spi/pom.xml @@ -52,6 +52,11 @@ jackson-module-jaxb-annotations provided + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + provided + commons-collections commons-collections diff --git a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java index 65d09b0c7..2e6892416 100644 --- a/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java +++ b/persistence-spi/src/main/java/org/apache/unomi/persistence/spi/CustomObjectMapper.java @@ -58,6 +58,7 @@ public CustomObjectMapper() { public CustomObjectMapper(Map> deserializers) { super(); super.registerModule(new JaxbAnnotationModule()); + super.registerModule(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule()); configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); setSerializationInclusion(JsonInclude.Include.NON_NULL); ISO8601DateFormat dateFormat = new ISO8601DateFormat(); diff --git a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java index 401726f7e..b2481e794 100644 --- a/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java +++ b/plugins/baseplugin/src/main/java/org/apache/unomi/plugins/baseplugin/conditions/PastEventConditionESQueryBuilder.java @@ -20,16 +20,16 @@ import org.apache.unomi.api.Event; import org.apache.unomi.api.Profile; import org.apache.unomi.api.conditions.Condition; -import org.apache.unomi.api.conditions.ConditionType; import org.apache.unomi.api.services.DefinitionsService; import org.apache.unomi.api.services.SegmentService; -import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; +import org.apache.unomi.api.utils.ConditionBuilder; import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilder; import org.apache.unomi.persistence.elasticsearch.conditions.ConditionESQueryBuilderDispatcher; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; +import org.apache.unomi.persistence.spi.conditions.ConditionContextHelper; import org.apache.unomi.scripting.ScriptExecutor; -import org.elasticsearch.index.query.*; +import org.elasticsearch.index.query.QueryBuilder; import java.util.*; import java.util.stream.Collectors; @@ -88,7 +88,8 @@ public QueryBuilder buildQuery(Condition condition, Map context, // TODO see for deprecation, this should not happen anymore each past event condition should have a generatedPropertyKey Condition eventCondition = getEventCondition(condition, context, null, definitionsService, scriptExecutor); Set ids = getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, maximumEventCount); - return dispatcher.buildFilter(getProfileIdsCondition(ids, eventsOccurred), context); + ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); + return dispatcher.buildFilter(conditionBuilder.condition("idsCondition").parameter("ids", ids).parameter("match", eventsOccurred).build(), context); } } @@ -111,7 +112,8 @@ public long count(Condition condition, Map context, ConditionESQ } Set profileIds = getProfileIdsMatchingEventCount(eventCondition, minimumEventCount, maximumEventCount); - return eventsOccurred ? profileIds.size() : persistenceService.queryCount(getProfileIdsCondition(profileIds, false), Profile.ITEM_TYPE); + ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); + return eventsOccurred ? profileIds.size() : persistenceService.queryCount(conditionBuilder.condition("idsCondition").parameter("ids", profileIds).parameter("match", false).build(), Profile.ITEM_TYPE); } } @@ -122,44 +124,38 @@ protected static boolean getStrategyFromOperator(String operator) { return operator == null || operator.equals("eventsOccurred"); } - private Condition getProfileIdsCondition(Set ids, boolean shouldMatch) { - Condition idsCondition = new Condition(); - idsCondition.setConditionType(definitionsService.getConditionType("idsCondition")); - idsCondition.setParameter("ids", ids); - idsCondition.setParameter("match", shouldMatch); - return idsCondition; - } - private Condition getProfileConditionForCounter(String generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount, boolean eventsOccurred) { - String generatedPropertyName = "systemProperties.pastEvents." + generatedPropertyKey; - ConditionType profilePropertyConditionType = definitionsService.getConditionType("profilePropertyCondition"); if (eventsOccurred) { - Condition counterIsBetweenBoundaries = new Condition(); - counterIsBetweenBoundaries.setConditionType(profilePropertyConditionType); - counterIsBetweenBoundaries.setParameter("propertyName", generatedPropertyName); - counterIsBetweenBoundaries.setParameter("comparisonOperator", "between"); - counterIsBetweenBoundaries.setParameter("propertyValuesInteger", Arrays.asList(minimumEventCount, maximumEventCount)); - return counterIsBetweenBoundaries; + return createEventOccurredCondition(generatedPropertyKey, minimumEventCount, maximumEventCount); } else { - Condition counterMissing = new Condition(); - counterMissing.setConditionType(profilePropertyConditionType); - counterMissing.setParameter("propertyName", generatedPropertyName); - counterMissing.setParameter("comparisonOperator", "missing"); - - Condition counterZero = new Condition(); - counterZero.setConditionType(profilePropertyConditionType); - counterZero.setParameter("propertyName", generatedPropertyName); - counterZero.setParameter("comparisonOperator", "equals"); - counterZero.setParameter("propertyValueInteger", 0); - - Condition counterCondition = new Condition(); - counterCondition.setConditionType(definitionsService.getConditionType("booleanCondition")); - counterCondition.setParameter("operator", "or"); - counterCondition.setParameter("subConditions", Arrays.asList(counterMissing, counterZero)); - return counterCondition; + return createEventNotOccurredCondition(generatedPropertyKey); } } + private Condition createEventOccurredCondition(String generatedPropertyKey, Integer minimumEventCount, Integer maximumEventCount) { + ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); + ConditionBuilder.ConditionItem subConditionCount = conditionBuilder.profileProperty("systemProperties.pastEvents.count").between(minimumEventCount, maximumEventCount); + ConditionBuilder.ConditionItem subConditionKey = conditionBuilder.profileProperty("systemProperties.pastEvents.key").equalTo(generatedPropertyKey); + ConditionBuilder.ConditionItem booleanCondition = conditionBuilder.and(subConditionCount, subConditionKey); + return conditionBuilder.nested(booleanCondition, "systemProperties.pastEvents").build(); + } + + private Condition createEventNotOccurredCondition(String generatedPropertyKey) { + ConditionBuilder.ConditionItem counterMissing = createPastEventMustNotExistCondition(generatedPropertyKey); + ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); + ConditionBuilder.ConditionItem counterZero = conditionBuilder.profileProperty("systemProperties.pastEvents.count").equalTo(0); + ConditionBuilder.ConditionItem keyEquals = conditionBuilder.profileProperty("systemProperties.pastEvents.key").equalTo(generatedPropertyKey); + ConditionBuilder.ConditionItem keyExistsAndCounterZero = conditionBuilder.and(counterZero, keyEquals); + ConditionBuilder.ConditionItem nestedKeyExistsAndCounterZero = conditionBuilder.nested(keyExistsAndCounterZero, "systemProperties.pastEvents"); + return conditionBuilder.or(counterMissing, nestedKeyExistsAndCounterZero).build(); + } + + private ConditionBuilder.ConditionItem createPastEventMustNotExistCondition(String generatedPropertyKey) { + ConditionBuilder conditionBuilder = definitionsService.getConditionBuilder(); + ConditionBuilder.ConditionItem keyEquals = conditionBuilder.profileProperty("systemProperties.pastEvents.key").equalTo(generatedPropertyKey); + return conditionBuilder.not(keyEquals); + } + private Set getProfileIdsMatchingEventCount(Condition eventCondition, int minimumEventCount, int maximumEventCount) { boolean noBoundaries = minimumEventCount == 1 && maximumEventCount == Integer.MAX_VALUE; if (pastEventsDisablePartitions) { diff --git a/pom.xml b/pom.xml index 1afd5dd23..3b52e4d8e 100644 --- a/pom.xml +++ b/pom.xml @@ -763,6 +763,13 @@ ${version.jackson.core} provided + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${version.jackson.databind} + provided + + diff --git a/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java b/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java index eff0f90bb..1b4fd840c 100644 --- a/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java +++ b/services/src/main/java/org/apache/unomi/services/impl/events/EventServiceImpl.java @@ -20,33 +20,22 @@ import inet.ipaddr.IPAddress; import inet.ipaddr.IPAddressString; import org.apache.commons.lang3.StringUtils; -import org.apache.unomi.api.Event; -import org.apache.unomi.api.EventProperty; -import org.apache.unomi.api.Metadata; -import org.apache.unomi.api.PartialList; -import org.apache.unomi.api.PropertyType; -import org.apache.unomi.api.Session; -import org.apache.unomi.api.ValueType; +import org.apache.unomi.api.*; import org.apache.unomi.api.actions.ActionPostExecutor; import org.apache.unomi.api.conditions.Condition; import org.apache.unomi.api.query.Query; -import org.apache.unomi.api.services.*; +import org.apache.unomi.api.services.DefinitionsService; +import org.apache.unomi.api.services.EventListenerService; +import org.apache.unomi.api.services.EventService; +import org.apache.unomi.api.utils.ParserHelper; import org.apache.unomi.persistence.spi.PersistenceService; import org.apache.unomi.persistence.spi.aggregate.TermsAggregate; -import org.apache.unomi.api.utils.ParserHelper; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; public class EventServiceImpl implements EventService { @@ -127,6 +116,7 @@ public String authenticateThirdPartyServer(String key, String ip) { for (Map.Entry entry : thirdPartyServers.entrySet()) { ThirdPartyServer server = entry.getValue(); if (server.getKey().equals(key)) { + // This is a fix to support proper IPv6 parsing if (ip != null) { if (ip.startsWith("[") && ip.endsWith("]")) { // This can happen with IPv6 addresses, we must remove the markers since our IPAddress library doesn't support them. diff --git a/tools/shell-commands/pom.xml b/tools/shell-commands/pom.xml index 707c9f806..b867d1ae2 100644 --- a/tools/shell-commands/pom.xml +++ b/tools/shell-commands/pom.xml @@ -37,6 +37,13 @@ provided + + org.apache.karaf.features + org.apache.karaf.features.core + ${version.karaf} + provided + + org.apache.httpcomponents httpclient-osgi @@ -107,6 +114,12 @@ ${version.jackson.databind} provided + + org.apache.unomi + unomi-lifecycle-watcher + ${project.version} + provided + @@ -149,6 +162,13 @@ cfg migration + + + src/main/resources/org.apache.unomi.start.cfg + + cfg + start + diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java index caf962277..2d4adb64e 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/actions/Start.java @@ -19,6 +19,7 @@ import org.apache.karaf.shell.api.action.Action; import org.apache.karaf.shell.api.action.Argument; import org.apache.karaf.shell.api.action.Command; +import org.apache.karaf.shell.api.action.Option; import org.apache.karaf.shell.api.action.lifecycle.Reference; import org.apache.karaf.shell.api.action.lifecycle.Service; import org.apache.unomi.shell.services.UnomiManagementService; @@ -33,6 +34,9 @@ public class Start implements Action { @Argument(name = "persistence", description = "Persistence implementation to use (elasticsearch/opensearch)", valueToShowInHelp = "elasticsearch") private String selectedPersistenceImplementation = "elasticsearch"; + @Option(name = "-i", aliases = "--install-only", description = "Only install features, don't start them", required = false, multiValued = false) + boolean installOnly = false; + public Object execute() throws Exception { if (!selectedPersistenceImplementation.equals("elasticsearch") && !selectedPersistenceImplementation.equals("opensearch")) { @@ -40,7 +44,7 @@ public Object execute() throws Exception { selectedPersistenceImplementation = "elasticsearch"; } System.out.println("Starting Apache Unomi with persistence implementation: " + selectedPersistenceImplementation); - unomiManagementService.startUnomi(selectedPersistenceImplementation); + unomiManagementService.startUnomi(selectedPersistenceImplementation, !installOnly); return null; } diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationConfig.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationConfig.java index bc89e92e1..f75929642 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationConfig.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/service/MigrationConfig.java @@ -49,27 +49,29 @@ public class MigrationConfig { public static final String ROLLOVER_MAX_AGE = "rolloverMaxAge"; public static final String ROLLOVER_MAX_SIZE = "rolloverMaxSize"; public static final String ROLLOVER_MAX_DOCS = "rolloverMaxDocs"; + public static final String SEARCH_ENGINE = "searchEngine"; protected static final Map configProperties; static { Map m = new HashMap<>(); - m.put(CONFIG_ES_ADDRESSES, new MigrationConfigProperty("Enter ElasticSearch TARGET address (default: localhost:9200): ", "localhost:9200")); - m.put(CONFIG_ES_SSL_ENABLED, new MigrationConfigProperty("Should the ElasticSearch TARGET connection be established using SSL (https) protocol ? (yes/no)", null)); - m.put(CONFIG_ES_LOGIN, new MigrationConfigProperty("Enter ElasticSearch TARGET login (default: none): ", "")); - m.put(CONFIG_ES_PASSWORD, new MigrationConfigProperty("Enter ElasticSearch TARGET password (default: none): ", "")); + m.put(SEARCH_ENGINE, new MigrationConfigProperty("Enter search engine to use (default: elasticsearch): ", "elasticsearch")); + m.put(CONFIG_ES_ADDRESSES, new MigrationConfigProperty("Enter search engine TARGET address (default: localhost:9200): ", "localhost:9200")); + m.put(CONFIG_ES_SSL_ENABLED, new MigrationConfigProperty("Should the search engine TARGET connection be established using SSL (https) protocol ? (yes/no)", null)); + m.put(CONFIG_ES_LOGIN, new MigrationConfigProperty("Enter search engine TARGET login (default: none): ", "")); + m.put(CONFIG_ES_PASSWORD, new MigrationConfigProperty("Enter search engine TARGET password (default: none): ", "")); m.put(CONFIG_TRUST_ALL_CERTIFICATES, new MigrationConfigProperty("We need to initialize a HttpClient, do we need to trust all certificates ? (yes/no)", null)); - m.put(INDEX_PREFIX, new MigrationConfigProperty("Enter ElasticSearch Unomi indices prefix (default: context): ", "context")); - m.put(NUMBER_OF_SHARDS, new MigrationConfigProperty("Enter ElasticSearch index mapping configuration: number_of_shards (default: 5): ", "5")); - m.put(NUMBER_OF_REPLICAS, new MigrationConfigProperty("Enter ElasticSearch index mapping configuration: number_of_replicas (default: 0): ", "0")); - m.put(TOTAL_FIELDS_LIMIT, new MigrationConfigProperty("Enter ElasticSearch index mapping configuration: mapping.total_fields.limit (default: 1000): ", "1000")); - m.put(MAX_DOC_VALUE_FIELDS_SEARCH, new MigrationConfigProperty("Enter ElasticSearch index mapping configuration: max_docvalue_fields_search (default: 1000): ", "1000")); - m.put(MONTHLY_NUMBER_OF_SHARDS, new MigrationConfigProperty("Enter ElasticSearch monthly index (event, session) mapping configuration: number_of_shards (default: 5): ", "5")); - m.put(MONTHLY_NUMBER_OF_REPLICAS, new MigrationConfigProperty("Enter ElasticSearch monthly index (event, session) mapping configuration: number_of_replicas (default: 0): ", "0")); - m.put(MONTHLY_TOTAL_FIELDS_LIMIT, new MigrationConfigProperty("Enter ElasticSearch monthly index (event, session) mapping configuration: mapping.total_fields.limit (default: 1000): ", "1000")); - m.put(MONTHLY_MAX_DOC_VALUE_FIELDS_SEARCH, new MigrationConfigProperty("Enter ElasticSearch monthly index (event, session) mapping configuration: max_docvalue_fields_search (default: 1000): ", "1000")); + m.put(INDEX_PREFIX, new MigrationConfigProperty("Enter search engine Unomi indices prefix (default: context): ", "context")); + m.put(NUMBER_OF_SHARDS, new MigrationConfigProperty("Enter search engine index mapping configuration: number_of_shards (default: 5): ", "5")); + m.put(NUMBER_OF_REPLICAS, new MigrationConfigProperty("Enter search engine index mapping configuration: number_of_replicas (default: 0): ", "0")); + m.put(TOTAL_FIELDS_LIMIT, new MigrationConfigProperty("Enter search engine index mapping configuration: mapping.total_fields.limit (default: 1000): ", "1000")); + m.put(MAX_DOC_VALUE_FIELDS_SEARCH, new MigrationConfigProperty("Enter search engine index mapping configuration: max_docvalue_fields_search (default: 1000): ", "1000")); + m.put(MONTHLY_NUMBER_OF_SHARDS, new MigrationConfigProperty("Enter search engine monthly index (event, session) mapping configuration: number_of_shards (default: 5): ", "5")); + m.put(MONTHLY_NUMBER_OF_REPLICAS, new MigrationConfigProperty("Enter search engine monthly index (event, session) mapping configuration: number_of_replicas (default: 0): ", "0")); + m.put(MONTHLY_TOTAL_FIELDS_LIMIT, new MigrationConfigProperty("Enter search engine monthly index (event, session) mapping configuration: mapping.total_fields.limit (default: 1000): ", "1000")); + m.put(MONTHLY_MAX_DOC_VALUE_FIELDS_SEARCH, new MigrationConfigProperty("Enter search engine monthly index (event, session) mapping configuration: max_docvalue_fields_search (default: 1000): ", "1000")); m.put(MIGRATION_HISTORY_RECOVER, new MigrationConfigProperty("We found an existing migration attempt, should we restart from it ? (this will avoid redoing steps already completed successfully) (yes/no)", null)); - m.put(ROLLOVER_MAX_AGE, new MigrationConfigProperty("Enter ElasticSearch index rollover configuration: max_age (default: null): ", null)); - m.put(ROLLOVER_MAX_SIZE, new MigrationConfigProperty("Enter ElasticSearch index rollover configuration: max_size (default: 30gb): ", "30gb")); - m.put(ROLLOVER_MAX_DOCS, new MigrationConfigProperty("Enter ElasticSearch index rollover configuration: max_docs (default: null): ", null)); + m.put(ROLLOVER_MAX_AGE, new MigrationConfigProperty("Enter search engine index rollover configuration: max_age (default: null): ", null)); + m.put(ROLLOVER_MAX_SIZE, new MigrationConfigProperty("Enter search engine index rollover configuration: max_size (default: 30gb): ", "30gb")); + m.put(ROLLOVER_MAX_DOCS, new MigrationConfigProperty("Enter search engine index rollover configuration: max_docs (default: null): ", null)); configProperties = Collections.unmodifiableMap(m); } diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java index e08cbb733..5068c0976 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/migration/utils/MigrationUtils.java @@ -86,7 +86,7 @@ public static String getFileWithoutComments(BundleContext bundleContext, final S in.close(); return value.toString(); } catch (final Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Error reading file " + resource, e); } } @@ -196,7 +196,7 @@ public static void deleteIndex(CloseableHttpClient httpClient, String esAddress, } } - public static void reIndex(CloseableHttpClient httpClient, BundleContext bundleContext, String esAddress, String indexName, String newIndexSettings, String painlessScript, MigrationContext migrationContext) throws Exception { + public static void reIndex(CloseableHttpClient httpClient, BundleContext bundleContext, String esAddress, String indexName, String newIndexSettings, String painlessScript, MigrationContext migrationContext, String migrationUniqueName) throws Exception { if (indexName.endsWith("-cloned")) { // We should never reIndex a clone ... return; @@ -208,7 +208,7 @@ public static void reIndex(CloseableHttpClient httpClient, BundleContext bundleC String setIndexReadOnlyRequest = resourceAsString(bundleContext, "requestBody/2.0.0/base_set_index_readonly_request.json"); - migrationContext.performMigrationStep("Reindex step for: " + indexName + " (clone creation)", () -> { + migrationContext.performMigrationStep(migrationUniqueName + " - reindex step for: " + indexName + " (clone creation)", () -> { // Delete clone in case it already exists, could be incomplete from a previous reindex attempt, so better create a fresh one. if (indexExists(httpClient, esAddress, indexNameCloned)) { HttpUtils.executeDeleteRequest(httpClient, esAddress + "/" + indexNameCloned, null); @@ -219,7 +219,7 @@ public static void reIndex(CloseableHttpClient httpClient, BundleContext bundleC HttpUtils.executePostRequest(httpClient, esAddress + "/" + indexName + "/_clone/" + indexNameCloned, null, null); }); - migrationContext.performMigrationStep("Reindex step for: " + indexName + " (recreate the index and perform the re-indexation)", () -> { + migrationContext.performMigrationStep(migrationUniqueName + " - reindex step for: " + indexName + " (recreate the index and perform the re-indexation)", () -> { // Delete original index if it still exists if (indexExists(httpClient, esAddress, indexName)) { HttpUtils.executeDeleteRequest(httpClient, esAddress + "/" + indexName, null); @@ -232,14 +232,14 @@ public static void reIndex(CloseableHttpClient httpClient, BundleContext bundleC waitForTaskToFinish(httpClient, esAddress, task.getString("task"), migrationContext); }); - migrationContext.performMigrationStep("Reindex step for: " + indexName + " (delete clone)", () -> { + migrationContext.performMigrationStep(migrationUniqueName + " - reindex step for: " + indexName + " (delete clone)", () -> { // Delete original index if it still exists if (indexExists(httpClient, esAddress, indexNameCloned)) { HttpUtils.executeDeleteRequest(httpClient, esAddress + "/" + indexNameCloned, null); } }); - migrationContext.performMigrationStep("Reindex step for: " + indexName + " (refresh at the end)", () -> { + migrationContext.performMigrationStep(migrationUniqueName + " - reindex step for: " + indexName + " (refresh at the end)", () -> { // Do a refresh HttpUtils.executePostRequest(httpClient, esAddress + "/" + indexName + "/_refresh", null, null); diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java index 46a805d75..5258cafa8 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/UnomiManagementService.java @@ -25,10 +25,12 @@ public interface UnomiManagementService { /** - * This method will start Apache Unomi + * This method will start Apache Unomi with the specified persistence implementation + * @param selectedPersistenceImplementation the persistence implementation to use + * @param mustStartFeatures true if features should be started, false if they should not * @throws BundleException if there was an error starting Unomi's bundles */ - void startUnomi(String selectedPersistenceImplementation) throws BundleException; + void startUnomi(String selectedPersistenceImplementation, boolean mustStartFeatures) throws BundleException; /** * This method will stop Apache Unomi diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceConfiguration.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceConfiguration.java new file mode 100644 index 000000000..a306fd840 --- /dev/null +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceConfiguration.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.unomi.shell.services.internal; + +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; + +@ObjectClassDefinition( + name = "Unomi Management Configuration", + description = "Configuration for Unomi Management Service" +) +public @interface UnomiManagementServiceConfiguration { + + @AttributeDefinition( + name = "Start Features", + description = "A semicolon-separated list of start features in the format 'key:feature1,feature2;key2:feature3'." + ) + String startFeatures() default ""; + +} diff --git a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java index fa95a8d9d..f97ee3038 100644 --- a/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java +++ b/tools/shell-commands/src/main/java/org/apache/unomi/shell/services/internal/UnomiManagementServiceImpl.java @@ -17,9 +17,12 @@ package org.apache.unomi.shell.services.internal; import org.apache.commons.lang3.StringUtils; +import org.apache.karaf.features.Feature; +import org.apache.karaf.features.FeatureState; +import org.apache.karaf.features.FeaturesService; +import org.apache.unomi.lifecycle.BundleWatcher; import org.apache.unomi.shell.migration.MigrationService; import org.apache.unomi.shell.services.UnomiManagementService; -import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.service.component.ComponentContext; @@ -27,37 +30,89 @@ import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; +import org.osgi.service.metatype.annotations.Designate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** - * TODO We really should replace this with Karaf Features that we activate. We could still keep the starting mechanism - * to work properly with the migration process but we should remove the hardcoded list of packages in this class. + * Implementation of the {@link UnomiManagementService} interface, providing functionality to manage + * the lifecycle of Apache Unomi, including the installation and activation of features using + * Karaf's {@link org.apache.karaf.features.FeaturesService}. + * + *