From ef0cd5667099e9e90b754e64e36a506ba585adb5 Mon Sep 17 00:00:00 2001 From: Radhika Kundam Date: Mon, 4 May 2026 14:39:11 -0700 Subject: [PATCH 01/51] ATLAS-5235: ATLAS-5236: Create new branch atlas-2.6 and updated version to 2.6.0-SNAPSHOT --- addons/couchbase-bridge/pom.xml | 2 +- addons/falcon-bridge-shim/pom.xml | 2 +- addons/falcon-bridge/pom.xml | 2 +- addons/hbase-bridge-shim/pom.xml | 2 +- addons/hbase-bridge/pom.xml | 2 +- addons/hbase-testing-util/pom.xml | 2 +- addons/hdfs-model/pom.xml | 2 +- addons/hive-bridge-shim/pom.xml | 2 +- addons/hive-bridge/pom.xml | 2 +- addons/impala-bridge-shim/pom.xml | 2 +- addons/impala-bridge/pom.xml | 2 +- addons/impala-hook-api/pom.xml | 2 +- addons/kafka-bridge/pom.xml | 2 +- addons/sqoop-bridge-shim/pom.xml | 2 +- addons/sqoop-bridge/pom.xml | 2 +- addons/storm-bridge-shim/pom.xml | 2 +- addons/storm-bridge/pom.xml | 2 +- addons/trino-extractor/pom.xml | 2 +- atlas-examples/pom.xml | 2 +- atlas-examples/sample-app/pom.xml | 2 +- authorization/pom.xml | 2 +- build-tools/pom.xml | 2 +- client/client-v1/pom.xml | 2 +- client/client-v2/pom.xml | 2 +- client/common/pom.xml | 2 +- client/pom.xml | 2 +- common/pom.xml | 2 +- dashboard/pom.xml | 2 +- dashboardv2/pom.xml | 2 +- dev-support/atlas-docker/.env | 2 +- distro/pom.xml | 2 +- docs/pom.xml | 2 +- graphdb/api/pom.xml | 2 +- graphdb/common/pom.xml | 2 +- graphdb/graphdb-impls/pom.xml | 2 +- graphdb/janus/pom.xml | 2 +- graphdb/janusgraph-rdbms/pom.xml | 2 +- graphdb/pom.xml | 2 +- hbase-shaded-client-fixed/pom.xml | 2 +- intg/pom.xml | 2 +- notification/pom.xml | 2 +- plugin-classloader/pom.xml | 2 +- pom.xml | 2 +- repository/pom.xml | 2 +- server-api/pom.xml | 2 +- test-tools/pom.xml | 2 +- tools/atlas-index-repair/pom.xml | 2 +- tools/classification-updater/pom.xml | 2 +- tools/notification-analyzer/pom.xml | 2 +- webapp/pom.xml | 2 +- 50 files changed, 50 insertions(+), 50 deletions(-) diff --git a/addons/couchbase-bridge/pom.xml b/addons/couchbase-bridge/pom.xml index 6c2765ede99..3848518144f 100644 --- a/addons/couchbase-bridge/pom.xml +++ b/addons/couchbase-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/falcon-bridge-shim/pom.xml b/addons/falcon-bridge-shim/pom.xml index 480d325de2d..25d45947f6e 100755 --- a/addons/falcon-bridge-shim/pom.xml +++ b/addons/falcon-bridge-shim/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/falcon-bridge/pom.xml b/addons/falcon-bridge/pom.xml index 7dfe6c55afc..3f54d6ebc5f 100644 --- a/addons/falcon-bridge/pom.xml +++ b/addons/falcon-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/hbase-bridge-shim/pom.xml b/addons/hbase-bridge-shim/pom.xml index f934e3bbf09..afb240f32db 100644 --- a/addons/hbase-bridge-shim/pom.xml +++ b/addons/hbase-bridge-shim/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/hbase-bridge/pom.xml b/addons/hbase-bridge/pom.xml index cc16fd8ace8..a55f8bcaf2d 100644 --- a/addons/hbase-bridge/pom.xml +++ b/addons/hbase-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/hbase-testing-util/pom.xml b/addons/hbase-testing-util/pom.xml index 2fb66c557d1..f8cd500d218 100644 --- a/addons/hbase-testing-util/pom.xml +++ b/addons/hbase-testing-util/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/hdfs-model/pom.xml b/addons/hdfs-model/pom.xml index a51e714175e..71f8546f183 100644 --- a/addons/hdfs-model/pom.xml +++ b/addons/hdfs-model/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/hive-bridge-shim/pom.xml b/addons/hive-bridge-shim/pom.xml index 08a9ee7c42f..6b406048c99 100755 --- a/addons/hive-bridge-shim/pom.xml +++ b/addons/hive-bridge-shim/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/hive-bridge/pom.xml b/addons/hive-bridge/pom.xml index 1ed368367a7..20e8b483b67 100755 --- a/addons/hive-bridge/pom.xml +++ b/addons/hive-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/impala-bridge-shim/pom.xml b/addons/impala-bridge-shim/pom.xml index cf72b08a6dd..73727a211f3 100644 --- a/addons/impala-bridge-shim/pom.xml +++ b/addons/impala-bridge-shim/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/impala-bridge/pom.xml b/addons/impala-bridge/pom.xml index 0d2ffcb8d4b..66648b5c043 100644 --- a/addons/impala-bridge/pom.xml +++ b/addons/impala-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/impala-hook-api/pom.xml b/addons/impala-hook-api/pom.xml index 805df8fb182..c21dfde7c39 100644 --- a/addons/impala-hook-api/pom.xml +++ b/addons/impala-hook-api/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/kafka-bridge/pom.xml b/addons/kafka-bridge/pom.xml index 239ee739800..10910ac33a1 100644 --- a/addons/kafka-bridge/pom.xml +++ b/addons/kafka-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/sqoop-bridge-shim/pom.xml b/addons/sqoop-bridge-shim/pom.xml index 3a4ec5dbc45..ba5011a33b4 100755 --- a/addons/sqoop-bridge-shim/pom.xml +++ b/addons/sqoop-bridge-shim/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/sqoop-bridge/pom.xml b/addons/sqoop-bridge/pom.xml index ea1bc94bab3..29b0cf2bd8d 100644 --- a/addons/sqoop-bridge/pom.xml +++ b/addons/sqoop-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/storm-bridge-shim/pom.xml b/addons/storm-bridge-shim/pom.xml index 9f9dd0e765e..a130d41d7f9 100755 --- a/addons/storm-bridge-shim/pom.xml +++ b/addons/storm-bridge-shim/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/storm-bridge/pom.xml b/addons/storm-bridge/pom.xml index f1d13054ecd..c7fcb303fcc 100644 --- a/addons/storm-bridge/pom.xml +++ b/addons/storm-bridge/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/addons/trino-extractor/pom.xml b/addons/trino-extractor/pom.xml index a7a66b937ea..c6fe37cd6db 100644 --- a/addons/trino-extractor/pom.xml +++ b/addons/trino-extractor/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ diff --git a/atlas-examples/pom.xml b/atlas-examples/pom.xml index 6eb1d235e53..db9c011d291 100644 --- a/atlas-examples/pom.xml +++ b/atlas-examples/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-examples diff --git a/atlas-examples/sample-app/pom.xml b/atlas-examples/sample-app/pom.xml index 6e49207d6eb..69c531c446d 100644 --- a/atlas-examples/sample-app/pom.xml +++ b/atlas-examples/sample-app/pom.xml @@ -21,7 +21,7 @@ org.apache.atlas atlas-examples - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT sample-app diff --git a/authorization/pom.xml b/authorization/pom.xml index af95d5f01e5..11a11431a86 100644 --- a/authorization/pom.xml +++ b/authorization/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-authorization diff --git a/build-tools/pom.xml b/build-tools/pom.xml index 6f5dc4d0de0..bfd0d279041 100644 --- a/build-tools/pom.xml +++ b/build-tools/pom.xml @@ -21,7 +21,7 @@ org.apache.atlas atlas-buildtools - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT jar Apache Atlas Server Build Tools diff --git a/client/client-v1/pom.xml b/client/client-v1/pom.xml index cd12d33690c..a07a94e8720 100644 --- a/client/client-v1/pom.xml +++ b/client/client-v1/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-client - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-client-v1 diff --git a/client/client-v2/pom.xml b/client/client-v2/pom.xml index b1df49d7a6c..be63524a905 100644 --- a/client/client-v2/pom.xml +++ b/client/client-v2/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-client - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-client-v2 diff --git a/client/common/pom.xml b/client/common/pom.xml index 517c3030a29..a4a674037e5 100644 --- a/client/common/pom.xml +++ b/client/common/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-client - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-client-common diff --git a/client/pom.xml b/client/pom.xml index 535bfc190e3..07db2b64322 100755 --- a/client/pom.xml +++ b/client/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-client diff --git a/common/pom.xml b/common/pom.xml index d722f559111..e3d1e6dbd17 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-common diff --git a/dashboard/pom.xml b/dashboard/pom.xml index 17bcf14f1e5..0dbf439003e 100644 --- a/dashboard/pom.xml +++ b/dashboard/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-dashboard diff --git a/dashboardv2/pom.xml b/dashboardv2/pom.xml index e868034445f..a0a7a796fd1 100644 --- a/dashboardv2/pom.xml +++ b/dashboardv2/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-dashboardv2 diff --git a/dev-support/atlas-docker/.env b/dev-support/atlas-docker/.env index a03cebf7164..2081d35fa84 100644 --- a/dev-support/atlas-docker/.env +++ b/dev-support/atlas-docker/.env @@ -17,7 +17,7 @@ ATLAS_BUILD_JAVA_VERSION=8 # Valid values: 8, 11, 17 ATLAS_SERVER_JAVA_VERSION=8 -ATLAS_VERSION=3.0.0-SNAPSHOT +ATLAS_VERSION=2.6.0-SNAPSHOT UBUNTU_VERSION=20.04 HADOOP_VERSION=3.4.2 HBASE_VERSION=2.6.4 diff --git a/distro/pom.xml b/distro/pom.xml index d7e95888949..92337395260 100644 --- a/distro/pom.xml +++ b/distro/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../pom.xml diff --git a/docs/pom.xml b/docs/pom.xml index 0c1fa82cdae..a700cea47e0 100755 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-docs diff --git a/graphdb/api/pom.xml b/graphdb/api/pom.xml index 47875803346..54c19fe233b 100644 --- a/graphdb/api/pom.xml +++ b/graphdb/api/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-graphdb - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-graphdb-api diff --git a/graphdb/common/pom.xml b/graphdb/common/pom.xml index 9fe390067cc..2ce58b3a758 100644 --- a/graphdb/common/pom.xml +++ b/graphdb/common/pom.xml @@ -16,7 +16,7 @@ under the License. --> org.apache.atlas atlas-graphdb - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-graphdb-common diff --git a/graphdb/graphdb-impls/pom.xml b/graphdb/graphdb-impls/pom.xml index 896a4f0c103..aee6dbecddc 100644 --- a/graphdb/graphdb-impls/pom.xml +++ b/graphdb/graphdb-impls/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-graphdb - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../pom.xml diff --git a/graphdb/janus/pom.xml b/graphdb/janus/pom.xml index cd07c909800..1af2158a413 100644 --- a/graphdb/janus/pom.xml +++ b/graphdb/janus/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-graphdb - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-graphdb-janus diff --git a/graphdb/janusgraph-rdbms/pom.xml b/graphdb/janusgraph-rdbms/pom.xml index 80301dac09a..d60a240cf3e 100644 --- a/graphdb/janusgraph-rdbms/pom.xml +++ b/graphdb/janusgraph-rdbms/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas atlas-graphdb - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT janusgraph-rdbms diff --git a/graphdb/pom.xml b/graphdb/pom.xml index c4c07948ccd..9a32d92cd3d 100644 --- a/graphdb/pom.xml +++ b/graphdb/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-graphdb diff --git a/hbase-shaded-client-fixed/pom.xml b/hbase-shaded-client-fixed/pom.xml index 09e75bae4aa..e52e2dc4f04 100644 --- a/hbase-shaded-client-fixed/pom.xml +++ b/hbase-shaded-client-fixed/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT hbase-shaded-client-fixed diff --git a/intg/pom.xml b/intg/pom.xml index 68ce290b35e..ae850e5601f 100644 --- a/intg/pom.xml +++ b/intg/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-intg diff --git a/notification/pom.xml b/notification/pom.xml index 97bbe839a31..f2f6cd8a992 100644 --- a/notification/pom.xml +++ b/notification/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-notification diff --git a/plugin-classloader/pom.xml b/plugin-classloader/pom.xml index 7e82ff2c7f3..41864a6d45b 100644 --- a/plugin-classloader/pom.xml +++ b/plugin-classloader/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-plugin-classloader diff --git a/pom.xml b/pom.xml index 08fbd2b8593..af23e06eae4 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT pom apache-atlas diff --git a/repository/pom.xml b/repository/pom.xml index 000c5197ac2..7c535dd0df6 100644 --- a/repository/pom.xml +++ b/repository/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-repository diff --git a/server-api/pom.xml b/server-api/pom.xml index 67db728011f..0758f9392ca 100644 --- a/server-api/pom.xml +++ b/server-api/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-server-api diff --git a/test-tools/pom.xml b/test-tools/pom.xml index efbbbb28ac6..c06194b6370 100644 --- a/test-tools/pom.xml +++ b/test-tools/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-testtools diff --git a/tools/atlas-index-repair/pom.xml b/tools/atlas-index-repair/pom.xml index 0b12730d771..e99eda9ffe0 100644 --- a/tools/atlas-index-repair/pom.xml +++ b/tools/atlas-index-repair/pom.xml @@ -21,7 +21,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ atlas-index-repair-tool diff --git a/tools/classification-updater/pom.xml b/tools/classification-updater/pom.xml index 7a2606b042b..7e271f2b863 100644 --- a/tools/classification-updater/pom.xml +++ b/tools/classification-updater/pom.xml @@ -21,7 +21,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ atlas-classification-updater diff --git a/tools/notification-analyzer/pom.xml b/tools/notification-analyzer/pom.xml index 76904ea5d61..70f54196585 100644 --- a/tools/notification-analyzer/pom.xml +++ b/tools/notification-analyzer/pom.xml @@ -21,7 +21,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT ../../ atlas-notification-analyzer diff --git a/webapp/pom.xml b/webapp/pom.xml index 9f5c5bb4e6f..07c4186a90a 100755 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -22,7 +22,7 @@ org.apache.atlas apache-atlas - 3.0.0-SNAPSHOT + 2.6.0-SNAPSHOT atlas-webapp From fc0fa14a4c58e33a500fdda038986defe44231ea Mon Sep 17 00:00:00 2001 From: sheetalshah1007 Date: Thu, 7 May 2026 18:39:42 +0530 Subject: [PATCH 02/51] ATLAS-5156: Import failure due to missing support for handling multiple relationship types under a single attribute (#478) (cherry picked from commit a0acdc234a1b2055e7ddaecde1785ba3edf2adf9) --- .../store/graph/v2/EntityGraphMapper.java | 91 ++- ...phMapperMultipleRelationshipTypesTest.java | 742 ++++++++++++++++++ 2 files changed, 825 insertions(+), 8 deletions(-) create mode 100644 repository/src/test/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapperMultipleRelationshipTypesTest.java diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java index 3b7f4a51076..418887918c1 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java @@ -1507,20 +1507,14 @@ private void mapRelationshipAttributes(AtlasEntity entity, AtlasEntityType entit if (op.equals(CREATE)) { for (String attrName : entityType.getRelationshipAttributes().keySet()) { Object attrValue = entity.getRelationshipAttribute(attrName); - String relationType = AtlasEntityUtil.getRelationshipType(attrValue); - AtlasAttribute attribute = entityType.getRelationshipAttribute(attrName, relationType); - - mapAttribute(attribute, attrValue, vertex, op, context); + mapRelationshipAttribute(entityType, attrName, attrValue, vertex, op, context); } } else if (op.equals(UPDATE) || op.equals(PARTIAL_UPDATE)) { // relationship attributes mapping for (String attrName : entityType.getRelationshipAttributes().keySet()) { if (entity.hasRelationshipAttribute(attrName)) { Object attrValue = entity.getRelationshipAttribute(attrName); - String relationType = AtlasEntityUtil.getRelationshipType(attrValue); - AtlasAttribute attribute = entityType.getRelationshipAttribute(attrName, relationType); - - mapAttribute(attribute, attrValue, vertex, op, context); + mapRelationshipAttribute(entityType, attrName, attrValue, vertex, op, context); } } } @@ -1533,6 +1527,87 @@ private void mapRelationshipAttributes(AtlasEntity entity, AtlasEntityType entit LOG.debug("<== mapRelationshipAttributes({}, {})", op, entity.getTypeName()); } + private void mapRelationshipAttribute(AtlasEntityType entityType, String attrName, Object attrValue, AtlasVertex vertex, EntityOperation op, EntityMutationContext context) throws AtlasBaseException { + LOG.debug("==> mapRelationshipAttribute({}, {})", attrName, entityType.getTypeName()); + Set relationshipTypeNames = entityType.getAttributeRelationshipTypes(attrName); + + if (shouldMapRelationshipAttributeUsingInferredType(relationshipTypeNames, attrValue)) { + String relationType = relationshipTypeNames.size() == 1 + ? relationshipTypeNames.iterator().next() + : AtlasEntityUtil.getRelationshipType(attrValue); + mapRelationshipAttributeUsingInferredType(entityType, attrName, attrValue, relationType, vertex, op, context); + return; + } + + if (attrValue instanceof Collection) { + Collection relatedObjects = (Collection) attrValue; + + // Group related objects by their appropriate relationship type + // e.g., hive_table elements should use hive_table_db relationship, delta_table elements should use delta_table_db + Map> elementsByRelationshipType = groupElementsByRelationshipType( + relatedObjects, attrName, relationshipTypeNames); + + for (Map.Entry> entry : elementsByRelationshipType.entrySet()) { + String relationshipTypeName = entry.getKey(); + List filteredElements = entry.getValue(); + + AtlasAttribute attribute = entityType.getRelationshipAttribute(attrName, relationshipTypeName); + + if (attribute != null && CollectionUtils.isNotEmpty(filteredElements)) { + // Use the same collection type as the original (List or Set) + Object filteredValue = createCollectionOfSameType(attrValue, filteredElements); + + LOG.debug("Processing relationship type {} for attribute {} with {} elements", relationshipTypeName, attrName, filteredElements.size()); + + mapAttribute(attribute, filteredValue, vertex, op, context); + } + } + } else if (attrValue instanceof Map) { + LOG.warn("mapRelationshipAttribute: attribute {} on {}: Map-valued relationship attribute is not supported; use a list or set of references", + attrName, entityType.getTypeName()); + } + + LOG.debug("<== mapRelationshipAttribute({}, {})", attrName, entityType.getTypeName()); + } + + private boolean isAttributeWithMultipleRelationshipTypes(Set relationshipTypeNames) { + return CollectionUtils.isNotEmpty(relationshipTypeNames) && relationshipTypeNames.size() > 1; + } + + private boolean shouldMapRelationshipAttributeUsingInferredType(Set relationshipTypeNames, Object attrValue) { + return !isAttributeWithMultipleRelationshipTypes(relationshipTypeNames) + || (!(attrValue instanceof Collection) && !(attrValue instanceof Map)); + } + + private void mapRelationshipAttributeUsingInferredType(AtlasEntityType entityType, String attrName, Object attrValue, String relationType, AtlasVertex vertex, EntityOperation op, EntityMutationContext context) throws AtlasBaseException { + AtlasAttribute attribute = entityType.getRelationshipAttribute(attrName, relationType); + mapAttribute(attribute, attrValue, vertex, op, context); + } + + private Map> groupElementsByRelationshipType(Collection relatedObjects, String attrName, Set relationshipTypeNames) { + Map> elementsByRelationshipType = new HashMap<>(); + + // Group related objects by their appropriate relationship type + for (Object element : relatedObjects) { + String relationshipType = AtlasEntityUtil.getRelationshipType(element); + + if (StringUtils.isEmpty(relationshipType) || !relationshipTypeNames.contains(relationshipType)) { + continue; + } + + elementsByRelationshipType.computeIfAbsent(relationshipType, k -> new ArrayList<>()).add(element); + } + + return elementsByRelationshipType; + } + + private Object createCollectionOfSameType(Object originalValue, List filteredElements) { + if (originalValue instanceof Set) { + return new HashSet<>(filteredElements); + } + return filteredElements; + } + private void mapAttribute(AtlasAttribute attribute, Object attrValue, AtlasVertex vertex, EntityOperation op, EntityMutationContext context) throws AtlasBaseException { boolean isDeletedEntity = context.isDeletedEntity(vertex); AtlasType attrType = attribute.getAttributeType(); diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapperMultipleRelationshipTypesTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapperMultipleRelationshipTypesTest.java new file mode 100644 index 00000000000..aa2727933ea --- /dev/null +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapperMultipleRelationshipTypesTest.java @@ -0,0 +1,742 @@ +/** + * 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.atlas.repository.store.graph.v2; + +import org.apache.atlas.RequestContext; +import org.apache.atlas.TestModules; +import org.apache.atlas.TestUtilsV2; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntity; +import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; +import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.AtlasObjectId; +import org.apache.atlas.model.instance.AtlasRelatedObjectId; +import org.apache.atlas.model.instance.EntityMutationResponse; +import org.apache.atlas.model.typedef.AtlasEntityDef; +import org.apache.atlas.model.typedef.AtlasRelationshipDef; +import org.apache.atlas.model.typedef.AtlasRelationshipEndDef; +import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality; +import org.apache.atlas.model.typedef.AtlasTypesDef; +import org.apache.atlas.repository.graphdb.AtlasEdge; +import org.apache.atlas.repository.graphdb.AtlasEdgeDirection; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.apache.atlas.type.AtlasEntityType; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.apache.atlas.TestUtilsV2.randomString; +import static org.apache.atlas.type.AtlasTypeUtil.createClassTypeDef; +import static org.apache.atlas.type.AtlasTypeUtil.createOptionalAttrDef; +import static org.apache.atlas.type.AtlasTypeUtil.createUniqueRequiredAttrDef; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; + +/** + * Test class to verify handling of multiple relationship types for the same attribute. + * This covers the scenario where a hive_db can have both hive_table and delta_table + * entities in its "tables" attribute, using different relationship types. + */ +@Guice(modules = TestModules.TestOnlyModule.class) +public class EntityGraphMapperMultipleRelationshipTypesTest extends AtlasEntityTestBase { + private static final String HIVE_DB_TYPE = "hive_db"; + private static final String HIVE_TABLE_TYPE = "hive_table"; + private static final String DELTA_TABLE_TYPE = "delta_table"; + private static final String INVALID_TABLE_TYPE = "invalid_table"; + private static final String HIVE_COLUMN_TYPE = "hive_column"; + + private static final String HIVE_TABLE_DB_RELATIONSHIP = "hive_table_db"; + private static final String DELTA_TABLE_DB_RELATIONSHIP = "delta_table_db"; + private static final String HIVE_TABLE_COLUMNS_RELATIONSHIP = "hive_table_columns"; + private static final String HIVE_TABLE_PARTITIONKEYS_RELATIONSHIP = "hive_table_partitionkeys"; + + private static final String TABLES_ATTR_NAME = "tables"; + + @BeforeClass + public void setUp() throws Exception { + super.setUp(); + + // Create type definitions with multiple relationship types for the same attribute + AtlasTypesDef typesDef = createTypesWithMultipleRelationshipTypes(); + createTypesDef(new AtlasTypesDef[] {typesDef}); + } + + @BeforeTest + public void init() throws Exception { + RequestContext.clear(); + RequestContext.get().setUser(TestUtilsV2.TEST_USER, null); + } + + /** + * Test CREATE operation with mixed relationship types in a collection. + * Creates a hive_db with both hive_table and delta_table entities. + */ + @Test + public void testCreateWithMixedRelationshipTypes() throws Exception { + init(); + + // Create a new hive_db with mixed table types + AtlasEntity dbEntity = new AtlasEntity(HIVE_DB_TYPE); + dbEntity.setAttribute("name", "test_db_" + randomString()); + dbEntity.setAttribute("description", "Test database with mixed tables"); + + // Create hive_table entities + AtlasEntity hiveTable1 = createHiveTableEntity("ht1_" + randomString()); + AtlasEntity hiveTable2 = createHiveTableEntity("ht2_" + randomString()); + + // Create delta_table entities + AtlasEntity deltaTable1 = createDeltaTableEntity("dt1_" + randomString()); + AtlasEntity deltaTable2 = createDeltaTableEntity("dt2_" + randomString()); + + // Create all entities first + AtlasEntitiesWithExtInfo entitiesToCreate = new AtlasEntitiesWithExtInfo(); + entitiesToCreate.addEntity(hiveTable1); + entitiesToCreate.addEntity(hiveTable2); + entitiesToCreate.addEntity(deltaTable1); + entitiesToCreate.addEntity(deltaTable2); + entitiesToCreate.addEntity(dbEntity); + + EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesToCreate), false); + + assertNotNull(response); + List createdEntities = response.getCreatedEntities(); + assertNotNull(createdEntities); + assertEquals(createdEntities.size(), 5); + + // Find the created entities + String createdDbGuid = null; + String createdHiveTable1Guid = null; + String createdHiveTable2Guid = null; + String createdDeltaTable1Guid = null; + String createdDeltaTable2Guid = null; + + for (AtlasEntityHeader header : createdEntities) { + if (HIVE_DB_TYPE.equals(header.getTypeName())) { + createdDbGuid = header.getGuid(); + } else if (HIVE_TABLE_TYPE.equals(header.getTypeName())) { + if (createdHiveTable1Guid == null) { + createdHiveTable1Guid = header.getGuid(); + } else { + createdHiveTable2Guid = header.getGuid(); + } + } else if (DELTA_TABLE_TYPE.equals(header.getTypeName())) { + if (createdDeltaTable1Guid == null) { + createdDeltaTable1Guid = header.getGuid(); + } else { + createdDeltaTable2Guid = header.getGuid(); + } + } + } + + assertNotNull(createdDbGuid); + assertNotNull(createdHiveTable1Guid); + assertNotNull(createdHiveTable2Guid); + assertNotNull(createdDeltaTable1Guid); + assertNotNull(createdDeltaTable2Guid); + + // Now update the db entity to include the tables using relationship attributes + AtlasEntity dbEntityUpdate = new AtlasEntity(HIVE_DB_TYPE); + dbEntityUpdate.setGuid(createdDbGuid); + dbEntityUpdate.setAttribute("name", "db1"); + + List tableRefs = new ArrayList<>(); + tableRefs.add(new AtlasRelatedObjectId(new AtlasObjectId(createdHiveTable1Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + tableRefs.add(new AtlasRelatedObjectId(new AtlasObjectId(createdHiveTable2Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + tableRefs.add(new AtlasRelatedObjectId(new AtlasObjectId(createdDeltaTable1Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + tableRefs.add(new AtlasRelatedObjectId(new AtlasObjectId(createdDeltaTable2Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + + dbEntityUpdate.setRelationshipAttribute(TABLES_ATTR_NAME, tableRefs); + + AtlasEntityWithExtInfo dbEntityExtInfo = new AtlasEntityWithExtInfo(dbEntityUpdate); + EntityMutationResponse updateResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntityExtInfo), false); + + assertNotNull(updateResponse); + + // Verify relationships were created correctly + verifyRelationships(createdDbGuid, createdHiveTable1Guid, createdHiveTable2Guid, + createdDeltaTable1Guid, createdDeltaTable2Guid); + } + + /** + * Test UPDATE operation with mixed relationship types. + * Simulates incremental import scenario where a new delta_table is added. + */ + @Test(dependsOnMethods = "testCreateWithMixedRelationshipTypes") + public void testUpdateWithMixedRelationshipTypesIncremental() throws Exception { + init(); + + // Create initial entities (simulating existing state) + AtlasEntity dbEntity = createHiveDbEntity("mixdb_" + randomString()); + AtlasEntity hiveTable1 = createHiveTableEntity("ht1_" + randomString()); + AtlasEntity hiveTable2 = createHiveTableEntity("ht2_" + randomString()); + AtlasEntity deltaTable1 = createDeltaTableEntity("dt1_" + randomString()); + AtlasEntity deltaTable2 = createDeltaTableEntity("dt2_" + randomString()); + + // Create all entities + AtlasEntitiesWithExtInfo entitiesToCreate = new AtlasEntitiesWithExtInfo(); + entitiesToCreate.addEntity(hiveTable1); + entitiesToCreate.addEntity(hiveTable2); + entitiesToCreate.addEntity(deltaTable1); + entitiesToCreate.addEntity(deltaTable2); + entitiesToCreate.addEntity(dbEntity); + + EntityMutationResponse createResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesToCreate), false); + + assertNotNull(createResponse); + List createdEntities = createResponse.getCreatedEntities(); + assertEquals(createdEntities.size(), 5); + + // Extract GUIDs + String dbGuid = findEntityGuid(createdEntities, HIVE_DB_TYPE); + String ht1Guid = findEntityGuid(createdEntities, HIVE_TABLE_TYPE, 0); + String ht2Guid = findEntityGuid(createdEntities, HIVE_TABLE_TYPE, 1); + String dt1Guid = findEntityGuid(createdEntities, DELTA_TABLE_TYPE, 0); + String dt2Guid = findEntityGuid(createdEntities, DELTA_TABLE_TYPE, 1); + + // Set up initial relationships + AtlasEntity dbEntityWithTables = new AtlasEntity(HIVE_DB_TYPE); + dbEntityWithTables.setGuid(dbGuid); + dbEntityWithTables.setAttribute("name", "db2"); + + List initialTables = new ArrayList<>(); + initialTables.add(new AtlasRelatedObjectId(new AtlasObjectId(ht1Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + initialTables.add(new AtlasRelatedObjectId(new AtlasObjectId(ht2Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + initialTables.add(new AtlasRelatedObjectId(new AtlasObjectId(dt1Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + initialTables.add(new AtlasRelatedObjectId(new AtlasObjectId(dt2Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + + dbEntityWithTables.setRelationshipAttribute(TABLES_ATTR_NAME, initialTables); + AtlasEntityWithExtInfo dbEntityExtInfo = new AtlasEntityWithExtInfo(dbEntityWithTables); + entityStore.createOrUpdate(new AtlasEntityStream(dbEntityExtInfo), false); + + // Now simulate incremental import: add a new delta_table + AtlasEntity newDeltaTable = createDeltaTableEntity("dt3_" + randomString()); + AtlasEntitiesWithExtInfo newEntity = new AtlasEntitiesWithExtInfo(); + newEntity.addEntity(newDeltaTable); + + EntityMutationResponse newTableResponse = entityStore.createOrUpdate(new AtlasEntityStream(newEntity), false); + String dt3Guid = findEntityGuid(newTableResponse.getCreatedEntities(), DELTA_TABLE_TYPE); + + // Update db entity to include the new delta_table (incremental update) + AtlasEntity dbEntityUpdate = new AtlasEntity(HIVE_DB_TYPE); + dbEntityUpdate.setGuid(dbGuid); + dbEntityUpdate.setAttribute("name", dbEntityWithTables.getAttribute("name")); + + // Include all existing tables plus the new one + List allTables = new ArrayList<>(); + allTables.add(new AtlasRelatedObjectId(new AtlasObjectId(ht1Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + allTables.add(new AtlasRelatedObjectId(new AtlasObjectId(ht2Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + allTables.add(new AtlasRelatedObjectId(new AtlasObjectId(dt1Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + allTables.add(new AtlasRelatedObjectId(new AtlasObjectId(dt2Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + allTables.add(new AtlasRelatedObjectId(new AtlasObjectId(dt3Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + + dbEntityUpdate.setRelationshipAttribute(TABLES_ATTR_NAME, allTables); + + AtlasEntityWithExtInfo updateExtInfo = new AtlasEntityWithExtInfo(dbEntityUpdate); + EntityMutationResponse updateResponse = entityStore.createOrUpdate(new AtlasEntityStream(updateExtInfo), false); + + assertNotNull(updateResponse); + + // Verify all relationships are correct + verifyRelationships(dbGuid, ht1Guid, ht2Guid, dt1Guid, dt2Guid, dt3Guid); + } + + /** + * Test that validates the correct relationship types are used for each entity type. + * This ensures hive_table uses hive_table_db and delta_table uses delta_table_db. + */ + @Test + public void testRelationshipTypeValidation() throws Exception { + init(); + + // Create entities + AtlasEntity dbEntity = createHiveDbEntity("validate_db_" + randomString()); + AtlasEntity hiveTable = createHiveTableEntity("validate_ht_" + randomString()); + AtlasEntity deltaTable = createDeltaTableEntity("validate_dt_" + randomString()); + + AtlasEntitiesWithExtInfo entitiesToCreate = new AtlasEntitiesWithExtInfo(); + entitiesToCreate.addEntity(dbEntity); + entitiesToCreate.addEntity(hiveTable); + entitiesToCreate.addEntity(deltaTable); + + EntityMutationResponse createResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesToCreate), false); + + String dbGuid = findEntityGuid(createResponse.getCreatedEntities(), HIVE_DB_TYPE); + String htGuid = findEntityGuid(createResponse.getCreatedEntities(), HIVE_TABLE_TYPE); + String dtGuid = findEntityGuid(createResponse.getCreatedEntities(), DELTA_TABLE_TYPE); + + // Update db with mixed tables + AtlasEntity dbEntityUpdate = new AtlasEntity(HIVE_DB_TYPE); + dbEntityUpdate.setGuid(dbGuid); + dbEntityUpdate.setAttribute("name", dbEntity.getAttributes().get("name")); + + List tables = new ArrayList<>(); + tables.add(new AtlasRelatedObjectId(new AtlasObjectId(htGuid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + tables.add(new AtlasRelatedObjectId(new AtlasObjectId(dtGuid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + + dbEntityUpdate.setRelationshipAttribute(TABLES_ATTR_NAME, tables); + + AtlasEntityWithExtInfo dbEntityExtInfo = new AtlasEntityWithExtInfo(dbEntityUpdate); + + // This should not throw an exception about invalid relationship types + try { + EntityMutationResponse updateResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntityExtInfo), false); + assertNotNull(updateResponse); + + // Verify relationships exist with correct types + AtlasEntityType dbType = typeRegistry.getEntityTypeByName(HIVE_DB_TYPE); + Set relationshipTypes = dbType.getAttributeRelationshipTypes(TABLES_ATTR_NAME); + assertTrue(relationshipTypes.contains(HIVE_TABLE_DB_RELATIONSHIP)); + assertTrue(relationshipTypes.contains(DELTA_TABLE_DB_RELATIONSHIP)); + } catch (AtlasBaseException e) { + // Should not get the error: "invalid relationshipDef: delta_table_db: end type 1: hive_db, end type 2: hive_table" + if (e.getMessage().contains("invalid relationshipDef") && e.getMessage().contains("delta_table_db")) { + fail("Should not use delta_table_db relationship for hive_table entities: " + e.getMessage()); + } + throw e; + } + } + + /** Same mixed-type {@code tables} payload as a list and as a set; two batches so each hive_db GUID is easy to resolve. */ + @Test + public void testMixedRelationshipTypesWithListAndSetCollection() throws Exception { + init(); + + AtlasEntity dbList = createHiveDbEntity("list_db_" + randomString()); + AtlasEntity hiveTbl = createHiveTableEntity("mix_ht_" + randomString()); + AtlasEntity deltaTbl = createDeltaTableEntity("mix_dt_" + randomString()); + + AtlasEntitiesWithExtInfo listBatch = new AtlasEntitiesWithExtInfo(); + listBatch.addEntity(dbList); + listBatch.addEntity(hiveTbl); + listBatch.addEntity(deltaTbl); + + EntityMutationResponse listResp = entityStore.createOrUpdate(new AtlasEntityStream(listBatch), false); + assertNotNull(listResp); + + String dbListGuid = findEntityGuid(listResp.getCreatedEntities(), HIVE_DB_TYPE); + String htGuid = findEntityGuid(listResp.getCreatedEntities(), HIVE_TABLE_TYPE); + String dtGuid = findEntityGuid(listResp.getCreatedEntities(), DELTA_TABLE_TYPE); + + AtlasRelatedObjectId hiveRef = new AtlasRelatedObjectId(new AtlasObjectId(htGuid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP); + AtlasRelatedObjectId deltaRef = new AtlasRelatedObjectId(new AtlasObjectId(dtGuid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP); + + List asList = new ArrayList<>(); + asList.add(hiveRef); + asList.add(deltaRef); + + AtlasEntity updateList = new AtlasEntity(HIVE_DB_TYPE); + updateList.setGuid(dbListGuid); + updateList.setAttribute("name", dbList.getAttribute("name")); + updateList.setRelationshipAttribute(TABLES_ATTR_NAME, asList); + assertNotNull(entityStore.createOrUpdate(new AtlasEntityStream(new AtlasEntityWithExtInfo(updateList)), false)); + verifyRelationships(dbListGuid, htGuid, dtGuid); + + AtlasEntity dbSet = createHiveDbEntity("set_db_" + randomString()); + AtlasEntity hiveTbl2 = createHiveTableEntity("mix_ht2_" + randomString()); + AtlasEntity deltaTbl2 = createDeltaTableEntity("mix_dt2_" + randomString()); + + AtlasEntitiesWithExtInfo setBatch = new AtlasEntitiesWithExtInfo(); + setBatch.addEntity(dbSet); + setBatch.addEntity(hiveTbl2); + setBatch.addEntity(deltaTbl2); + + EntityMutationResponse setResp = entityStore.createOrUpdate(new AtlasEntityStream(setBatch), false); + assertNotNull(setResp); + + String dbSetGuid = findEntityGuid(setResp.getCreatedEntities(), HIVE_DB_TYPE); + String ht2Guid = findEntityGuid(setResp.getCreatedEntities(), HIVE_TABLE_TYPE); + String dt2Guid = findEntityGuid(setResp.getCreatedEntities(), DELTA_TABLE_TYPE); + + Set asSet = new HashSet<>(); + asSet.add(new AtlasRelatedObjectId(new AtlasObjectId(ht2Guid, HIVE_TABLE_TYPE), HIVE_TABLE_DB_RELATIONSHIP)); + asSet.add(new AtlasRelatedObjectId(new AtlasObjectId(dt2Guid, DELTA_TABLE_TYPE), DELTA_TABLE_DB_RELATIONSHIP)); + + AtlasEntity updateSet = new AtlasEntity(HIVE_DB_TYPE); + updateSet.setGuid(dbSetGuid); + updateSet.setAttribute("name", dbSet.getAttribute("name")); + updateSet.setRelationshipAttribute(TABLES_ATTR_NAME, asSet); + assertNotNull(entityStore.createOrUpdate(new AtlasEntityStream(new AtlasEntityWithExtInfo(updateSet)), false)); + verifyRelationships(dbSetGuid, ht2Guid, dt2Guid); + } + + // Helper methods + + private AtlasTypesDef createTypesWithMultipleRelationshipTypes() { + AtlasTypesDef typesDef = new AtlasTypesDef(); + + // Create hive_db entity type + AtlasEntityDef hiveDbDef = createClassTypeDef(HIVE_DB_TYPE, "Hive Database", + Collections.emptySet(), + createUniqueRequiredAttrDef("name", "string"), + createOptionalAttrDef("description", "string")); + + // Create hive_table entity type + AtlasEntityDef hiveTableDef = createClassTypeDef(HIVE_TABLE_TYPE, "Hive Table", + Collections.emptySet(), + createUniqueRequiredAttrDef("name", "string"), + createOptionalAttrDef("description", "string")); + + // Create delta_table entity type + AtlasEntityDef deltaTableDef = createClassTypeDef(DELTA_TABLE_TYPE, "Delta Table", + Collections.emptySet(), + createUniqueRequiredAttrDef("name", "string"), + createOptionalAttrDef("description", "string")); + + // Create hive_column entity type + AtlasEntityDef hiveColumnDef = createClassTypeDef(HIVE_COLUMN_TYPE, "Hive Column", + Collections.emptySet(), + createUniqueRequiredAttrDef("name", "string"), + createOptionalAttrDef("isPartition", "boolean")); + + // Create invalid_table entity type (not part of any relationshipDef for tables) + AtlasEntityDef invalidTableDef = createClassTypeDef(INVALID_TABLE_TYPE, "Invalid Table", + Collections.emptySet(), + createUniqueRequiredAttrDef("name", "string"), + createOptionalAttrDef("description", "string")); + + typesDef.getEntityDefs().add(hiveDbDef); + typesDef.getEntityDefs().add(hiveTableDef); + typesDef.getEntityDefs().add(deltaTableDef); + typesDef.getEntityDefs().add(hiveColumnDef); + typesDef.getEntityDefs().add(invalidTableDef); + + // Create hive_table_db relationship + AtlasRelationshipDef hiveTableDbRel = new AtlasRelationshipDef(); + hiveTableDbRel.setName(HIVE_TABLE_DB_RELATIONSHIP); + hiveTableDbRel.setServiceType("hive"); + hiveTableDbRel.setTypeVersion("1.0"); + hiveTableDbRel.setRelationshipCategory(AtlasRelationshipDef.RelationshipCategory.AGGREGATION); + hiveTableDbRel.setRelationshipLabel("__hive_table.db"); + hiveTableDbRel.setPropagateTags(AtlasRelationshipDef.PropagateTags.NONE); + + AtlasRelationshipEndDef hiveTableEnd = new AtlasRelationshipEndDef(); + hiveTableEnd.setType(HIVE_TABLE_TYPE); + hiveTableEnd.setName("db"); + hiveTableEnd.setIsContainer(false); + hiveTableEnd.setCardinality(Cardinality.SINGLE); + hiveTableEnd.setIsLegacyAttribute(true); + + AtlasRelationshipEndDef hiveDbEnd = new AtlasRelationshipEndDef(); + hiveDbEnd.setType(HIVE_DB_TYPE); + hiveDbEnd.setName(TABLES_ATTR_NAME); + hiveDbEnd.setIsContainer(true); + hiveDbEnd.setCardinality(Cardinality.SET); + hiveDbEnd.setIsLegacyAttribute(false); + + hiveTableDbRel.setEndDef1(hiveTableEnd); + hiveTableDbRel.setEndDef2(hiveDbEnd); + + // Create delta_table_db relationship + AtlasRelationshipDef deltaTableDbRel = new AtlasRelationshipDef(); + deltaTableDbRel.setName(DELTA_TABLE_DB_RELATIONSHIP); + deltaTableDbRel.setServiceType("hive"); + deltaTableDbRel.setTypeVersion("1.0"); + deltaTableDbRel.setRelationshipCategory(AtlasRelationshipDef.RelationshipCategory.AGGREGATION); + deltaTableDbRel.setRelationshipLabel("__delta_table.db"); + deltaTableDbRel.setPropagateTags(AtlasRelationshipDef.PropagateTags.NONE); + + AtlasRelationshipEndDef deltaTableEnd = new AtlasRelationshipEndDef(); + deltaTableEnd.setType(DELTA_TABLE_TYPE); + deltaTableEnd.setName("db"); + deltaTableEnd.setIsContainer(false); + deltaTableEnd.setCardinality(Cardinality.SINGLE); + deltaTableEnd.setIsLegacyAttribute(true); + + AtlasRelationshipEndDef deltaDbEnd = new AtlasRelationshipEndDef(); + deltaDbEnd.setType(HIVE_DB_TYPE); + deltaDbEnd.setName(TABLES_ATTR_NAME); + deltaDbEnd.setIsContainer(true); + deltaDbEnd.setCardinality(Cardinality.SET); + deltaDbEnd.setIsLegacyAttribute(false); + + deltaTableDbRel.setEndDef1(deltaTableEnd); + deltaTableDbRel.setEndDef2(deltaDbEnd); + + // Create hive_table_columns relationship + AtlasRelationshipDef hiveTableColumnsRel = new AtlasRelationshipDef(); + hiveTableColumnsRel.setName(HIVE_TABLE_COLUMNS_RELATIONSHIP); + hiveTableColumnsRel.setServiceType("hive"); + hiveTableColumnsRel.setTypeVersion("1.2"); + hiveTableColumnsRel.setRelationshipCategory(AtlasRelationshipDef.RelationshipCategory.COMPOSITION); + hiveTableColumnsRel.setRelationshipLabel("__hive_table.columns"); + hiveTableColumnsRel.setPropagateTags(AtlasRelationshipDef.PropagateTags.NONE); + + AtlasRelationshipEndDef tableColumnsEnd = new AtlasRelationshipEndDef(); + tableColumnsEnd.setType(HIVE_TABLE_TYPE); + tableColumnsEnd.setName("columns"); + tableColumnsEnd.setIsContainer(true); + tableColumnsEnd.setCardinality(Cardinality.SET); + tableColumnsEnd.setIsLegacyAttribute(true); + + AtlasRelationshipEndDef columnTableEnd = new AtlasRelationshipEndDef(); + columnTableEnd.setType(HIVE_COLUMN_TYPE); + columnTableEnd.setName("table"); + columnTableEnd.setIsContainer(false); + columnTableEnd.setCardinality(Cardinality.SINGLE); + columnTableEnd.setIsLegacyAttribute(true); + + hiveTableColumnsRel.setEndDef1(tableColumnsEnd); + hiveTableColumnsRel.setEndDef2(columnTableEnd); + + // Create hive_table_partitionkeys relationship + AtlasRelationshipDef hiveTablePartitionKeysRel = new AtlasRelationshipDef(); + hiveTablePartitionKeysRel.setName(HIVE_TABLE_PARTITIONKEYS_RELATIONSHIP); + hiveTablePartitionKeysRel.setServiceType("hive"); + hiveTablePartitionKeysRel.setTypeVersion("1.2"); + hiveTablePartitionKeysRel.setRelationshipCategory(AtlasRelationshipDef.RelationshipCategory.COMPOSITION); + hiveTablePartitionKeysRel.setRelationshipLabel("__hive_table.partitionKeys"); + hiveTablePartitionKeysRel.setPropagateTags(AtlasRelationshipDef.PropagateTags.NONE); + + AtlasRelationshipEndDef tablePkEnd = new AtlasRelationshipEndDef(); + tablePkEnd.setType(HIVE_TABLE_TYPE); + tablePkEnd.setName("partitionKeys"); + tablePkEnd.setIsContainer(true); + tablePkEnd.setCardinality(Cardinality.SET); + tablePkEnd.setIsLegacyAttribute(true); + + AtlasRelationshipEndDef columnPkEnd = new AtlasRelationshipEndDef(); + columnPkEnd.setType(HIVE_COLUMN_TYPE); + columnPkEnd.setName("table"); + columnPkEnd.setIsContainer(false); + columnPkEnd.setCardinality(Cardinality.SINGLE); + columnPkEnd.setIsLegacyAttribute(true); + + hiveTablePartitionKeysRel.setEndDef1(tablePkEnd); + hiveTablePartitionKeysRel.setEndDef2(columnPkEnd); + + typesDef.getRelationshipDefs().add(hiveTableDbRel); + typesDef.getRelationshipDefs().add(deltaTableDbRel); + typesDef.getRelationshipDefs().add(hiveTableColumnsRel); + typesDef.getRelationshipDefs().add(hiveTablePartitionKeysRel); + + return typesDef; + } + + private AtlasEntity createHiveDbEntity(String name) { + return createNewEntity(HIVE_DB_TYPE, name, "Test database: " + name); + } + + private AtlasEntity createHiveTableEntity(String name) { + return createNewEntity(HIVE_TABLE_TYPE, name, "Test hive table: " + name); + } + + private AtlasEntity createDeltaTableEntity(String name) { + return createNewEntity(DELTA_TABLE_TYPE, name, "Test delta table: " + name); + } + + private AtlasEntity createNewEntity(String typeName, String name, String description) { + AtlasEntity entity = new AtlasEntity(typeName); + entity.setAttribute("name", name); + entity.setAttribute("description", description); + return entity; + } + + private String findEntityGuid(List entities, String typeName) { + return findEntityGuid(entities, typeName, 0); + } + + private String findEntityGuid(List entities, String typeName, int index) { + int count = 0; + for (AtlasEntityHeader header : entities) { + if (typeName.equals(header.getTypeName())) { + if (count == index) { + return header.getGuid(); + } + count++; + } + } + return null; + } + + private void verifyRelationships(String dbGuid, String... tableGuids) { + AtlasVertex dbVertex = AtlasGraphUtilsV2.findByGuid(graph, dbGuid); + assertNotNull(dbVertex, "Database vertex should exist"); + + // Verify relationships exist + for (String tableGuid : tableGuids) { + AtlasVertex tableVertex = AtlasGraphUtilsV2.findByGuid(graph, tableGuid); + assertNotNull(tableVertex, "Table vertex should exist for guid: " + tableGuid); + + // Check that there's an edge between db and table + boolean found = false; + Iterable outEdges = dbVertex.getEdges(AtlasEdgeDirection.OUT); + for (AtlasEdge edge : outEdges) { + String edgeGuid = AtlasGraphUtilsV2.getIdFromVertex(edge.getInVertex()); + if (tableGuid.equals(edgeGuid)) { + found = true; + break; + } + } + if (!found) { + Iterable inEdges = dbVertex.getEdges(AtlasEdgeDirection.IN); + for (AtlasEdge edge : inEdges) { + String edgeGuid = AtlasGraphUtilsV2.getIdFromVertex(edge.getOutVertex()); + if (tableGuid.equals(edgeGuid)) { + found = true; + break; + } + } + } + assertTrue(found, "Relationship should exist between db and table: " + tableGuid); + } + } + + /** + * Test that hive_table_columns and hive_table_partitionkeys relationships + * (which share the same end types hive_table <-> hive_column) are both + * mapped correctly by EntityGraphMapper. + * + * Normal columns: viewTime, userid, page_url, referrer_url, ip + * Partition columns: dt, country + */ + @Test + public void testHiveTableColumnsAndPartitionKeysRelationships() throws Exception { + init(); + + // STEP 1: Create the table first so we have a real GUID to satisfy hive_column.table + AtlasEntity tableEntity = createHiveTableEntity("cols_pk_table_" + randomString()); + + AtlasEntitiesWithExtInfo tableOnly = new AtlasEntitiesWithExtInfo(); + tableOnly.addEntity(tableEntity); + + EntityMutationResponse createResponse = entityStore.createOrUpdate(new AtlasEntityStream(tableOnly), false); + assertNotNull(createResponse); + + List createdEntities = createResponse.getCreatedEntities(); + assertNotNull(createdEntities); + + String tableGuid = findEntityGuid(createdEntities, HIVE_TABLE_TYPE); + assertNotNull(tableGuid); + + // STEP 2: Create columns with mandatory hive_column.table relationship set + // Normal (non-partition) columns + AtlasRelatedObjectId tableRefColumns = + new AtlasRelatedObjectId(new AtlasObjectId(tableGuid, HIVE_TABLE_TYPE), HIVE_TABLE_COLUMNS_RELATIONSHIP); + + AtlasEntity colViewTime = createNewEntity(HIVE_COLUMN_TYPE, "viewTime", "non-partition column"); + colViewTime.setAttribute("isPartition", false); + colViewTime.setRelationshipAttribute("table", tableRefColumns); + + AtlasEntity colUserId = createNewEntity(HIVE_COLUMN_TYPE, "userid", "non-partition column"); + colUserId.setAttribute("isPartition", false); + colUserId.setRelationshipAttribute("table", tableRefColumns); + + AtlasEntity colPageUrl = createNewEntity(HIVE_COLUMN_TYPE, "page_url", "non-partition column"); + colPageUrl.setAttribute("isPartition", false); + colPageUrl.setRelationshipAttribute("table", tableRefColumns); + + AtlasEntity colReferrerUrl = createNewEntity(HIVE_COLUMN_TYPE, "referrer_url", "non-partition column"); + colReferrerUrl.setAttribute("isPartition", false); + colReferrerUrl.setRelationshipAttribute("table", tableRefColumns); + + AtlasEntity colIp = createNewEntity(HIVE_COLUMN_TYPE, "ip", "non-partition column"); + colIp.setAttribute("isPartition", false); + colIp.setRelationshipAttribute("table", tableRefColumns); + + // Partition columns use the partitionKeys relationship type + AtlasRelatedObjectId tableRefPartitionKeys = + new AtlasRelatedObjectId(new AtlasObjectId(tableGuid, HIVE_TABLE_TYPE), HIVE_TABLE_PARTITIONKEYS_RELATIONSHIP); + + AtlasEntity colDt = createNewEntity(HIVE_COLUMN_TYPE, "dt", "partition column"); + colDt.setAttribute("isPartition", true); + colDt.setRelationshipAttribute("table", tableRefPartitionKeys); + + AtlasEntity colCountry = createNewEntity(HIVE_COLUMN_TYPE, "country", "partition column"); + colCountry.setAttribute("isPartition", true); + colCountry.setRelationshipAttribute("table", tableRefPartitionKeys); + + AtlasEntitiesWithExtInfo colsOnly = new AtlasEntitiesWithExtInfo(); + colsOnly.addEntity(colViewTime); + colsOnly.addEntity(colUserId); + colsOnly.addEntity(colPageUrl); + colsOnly.addEntity(colReferrerUrl); + colsOnly.addEntity(colIp); + colsOnly.addEntity(colDt); + colsOnly.addEntity(colCountry); + + EntityMutationResponse colsCreateResponse = entityStore.createOrUpdate(new AtlasEntityStream(colsOnly), false); + assertNotNull(colsCreateResponse); + + List colCreated = colsCreateResponse.getCreatedEntities(); + assertNotNull(colCreated); + + String colViewTimeGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 0); + String colUserIdGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 1); + String colPageUrlGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 2); + String colReferrerUrlGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 3); + String colIpGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 4); + String colDtGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 5); + String colCountryGuid = findEntityGuid(colCreated, HIVE_COLUMN_TYPE, 6); + + assertNotNull(colViewTimeGuid); + assertNotNull(colUserIdGuid); + assertNotNull(colPageUrlGuid); + assertNotNull(colReferrerUrlGuid); + assertNotNull(colIpGuid); + assertNotNull(colDtGuid); + assertNotNull(colCountryGuid); + + // Verify graph edges: __hive_table.columns should point only to normal columns, + // and __hive_table.partitionKeys only to partition columns. + AtlasVertex tableVertex = AtlasGraphUtilsV2.findByGuid(graph, tableGuid); + assertNotNull(tableVertex, "Table vertex should exist"); + + Set columnTargets = new java.util.HashSet<>(); + Set partitionKeyTargets = new java.util.HashSet<>(); + + for (Object o : tableVertex.getEdges(AtlasEdgeDirection.OUT)) { + AtlasEdge edge = (AtlasEdge) o; + + if ("__hive_table.columns".equals(edge.getLabel())) { + columnTargets.add(AtlasGraphUtilsV2.getIdFromVertex(edge.getInVertex())); + } else if ("__hive_table.partitionKeys".equals(edge.getLabel())) { + partitionKeyTargets.add(AtlasGraphUtilsV2.getIdFromVertex(edge.getInVertex())); + } + } + + // Normal columns must be in columns set and not in partitionKeys set + assertTrue(columnTargets.contains(colViewTimeGuid)); + assertTrue(columnTargets.contains(colUserIdGuid)); + assertTrue(columnTargets.contains(colPageUrlGuid)); + assertTrue(columnTargets.contains(colReferrerUrlGuid)); + assertTrue(columnTargets.contains(colIpGuid)); + + assertTrue(!partitionKeyTargets.contains(colViewTimeGuid)); + assertTrue(!partitionKeyTargets.contains(colUserIdGuid)); + assertTrue(!partitionKeyTargets.contains(colPageUrlGuid)); + assertTrue(!partitionKeyTargets.contains(colReferrerUrlGuid)); + assertTrue(!partitionKeyTargets.contains(colIpGuid)); + + // Partition columns must be in partitionKeys set and not in columns set + assertTrue(partitionKeyTargets.contains(colDtGuid)); + assertTrue(partitionKeyTargets.contains(colCountryGuid)); + + assertTrue(!columnTargets.contains(colDtGuid)); + assertTrue(!columnTargets.contains(colCountryGuid)); + } +} From e4402530516995b1a66c735e74daa72deee86172 Mon Sep 17 00:00:00 2001 From: UmeshPatil-1 Date: Fri, 8 May 2026 16:39:41 +0530 Subject: [PATCH 03/51] ATLAS-4988: BusinessMetadata with attribute of data type Array takes time to Delete. (#490) (cherry picked from commit ae973e76db131c86417e91c9b43102c0677fe436) --- .../java/org/apache/atlas/AtlasClientV2.java | 26 ++- .../org/apache/atlas/AtlasClientV2Test.java | 22 +++ .../java/org/apache/atlas/AtlasErrorCode.java | 1 + .../atlas/type/AtlasBusinessMetadataType.java | 43 ++++ .../java/org/apache/atlas/TestUtilsV2.java | 15 ++ .../repository/store/graph/AtlasDefStore.java | 20 +- .../store/graph/AtlasTypeDefGraphStore.java | 30 +-- .../graph/v2/AtlasAbstractDefStoreV2.java | 24 ++- .../v2/AtlasBusinessMetadataDefStoreV2.java | 186 +++++++++++++----- .../graph/v2/AtlasTypeDefGraphStoreV2.java | 18 +- .../apache/atlas/store/AtlasTypeDefStore.java | 4 +- .../graph/AtlasTypeDefGraphStoreTest.java | 8 +- .../AtlasBusinessMetadataDefStoreV2Test.java | 79 ++++++++ .../org/apache/atlas/web/rest/TypesREST.java | 41 +++- .../atlas/web/adapters/TypeDefsRESTTest.java | 20 +- .../apache/atlas/web/rest/TypesRESTTest.java | 71 +++++-- 16 files changed, 486 insertions(+), 122 deletions(-) diff --git a/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java b/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java index 31687acda8a..04e4376d629 100644 --- a/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java +++ b/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java @@ -349,11 +349,33 @@ public AtlasTypesDef updateAtlasTypeDefs(AtlasTypesDef typesDef) throws AtlasSer * @param typesDef A composite object that captures all types to be deleted */ public void deleteAtlasTypeDefs(AtlasTypesDef typesDef) throws AtlasServiceException { - callAPI(API_V2.DELETE_TYPE_DEFS, (Class) null, AtlasType.toJson(typesDef)); + deleteAtlasTypeDefs(typesDef, false); + } + + public void deleteAtlasTypeDefs(AtlasTypesDef typesDef, boolean forceDelete) throws AtlasServiceException { + MultivaluedMap queryParams = null; + + if (forceDelete) { + queryParams = new MultivaluedMapImpl(); + queryParams.add("force", "true"); + } + + callAPI(API_V2.DELETE_TYPE_DEFS, (Class) null, AtlasType.toJson(typesDef), queryParams); } public void deleteTypeByName(String typeName) throws AtlasServiceException { - callAPI(API_V2.DELETE_TYPE_DEF_BY_NAME, (Class) null, null, typeName); + callAPI(API_V2.DELETE_TYPE_DEF_BY_NAME, (Class) null, null, typeName); + } + + public void deleteTypeByName(String typeName, boolean forceDelete) throws AtlasServiceException { + MultivaluedMap queryParams = null; + + if (forceDelete) { + queryParams = new MultivaluedMapImpl(); + queryParams.add("force", "true"); + } + + callAPI(API_V2.DELETE_TYPE_DEF_BY_NAME, (Class) null, queryParams, typeName); } // Entity APIs diff --git a/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java b/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java index be180b56ab0..f4942d7f59c 100644 --- a/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java +++ b/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java @@ -82,6 +82,7 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -808,6 +809,7 @@ private static class TestableAtlasClientV2 extends AtlasClientV2 { private Object mockResponse; private Class expectedReturnType; private boolean shouldThrowException; + private javax.ws.rs.core.MultivaluedMap lastQueryParams; public TestableAtlasClientV2() { super(mock(WebResource.class), mock(Configuration.class)); @@ -823,8 +825,13 @@ public void setShouldThrowException(boolean shouldThrow) { this.shouldThrowException = shouldThrow; } + public javax.ws.rs.core.MultivaluedMap getLastQueryParams() { + return lastQueryParams; + } + @Override public T callAPI(API api, Class responseType, Object requestObject, String... params) throws AtlasServiceException { + lastQueryParams = null; return handleCallAPI(responseType); } @@ -838,11 +845,13 @@ public T callAPI(API api, GenericType responseType, Object requestObject, @Override public T callAPI(API api, Class responseType, javax.ws.rs.core.MultivaluedMap queryParams, String... params) throws AtlasServiceException { + lastQueryParams = queryParams; return handleCallAPI(responseType); } @Override public T callAPI(API api, Class responseType, Object requestObject, javax.ws.rs.core.MultivaluedMap queryParams, String... params) throws AtlasServiceException { + lastQueryParams = queryParams; return handleCallAPI(responseType); } @@ -1053,6 +1062,19 @@ public void testDeleteAtlasTypeDefsRealExecution() throws Exception { // Should not throw exception client.deleteAtlasTypeDefs(input); assertTrue(true); + assertNull(client.getLastQueryParams()); + } + + @Test + public void testDeleteAtlasTypeDefsRealExecutionWithForceDelete() throws Exception { + TestableAtlasClientV2 client = new TestableAtlasClientV2(); + client.setMockResponse(null, Object.class); + + AtlasTypesDef input = new AtlasTypesDef(); + client.deleteAtlasTypeDefs(input, true); + + assertNotNull(client.getLastQueryParams()); + assertEquals(client.getLastQueryParams().getFirst("force"), "true"); } @Test diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java index ca7220243ab..a5aa58a1ba4 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -183,6 +183,7 @@ public enum AtlasErrorCode { BLANK_NAME_ATTRIBUTE(400, "ATLAS-400-00-104", "Name Attribute can't be empty!"), BLANK_VALUE_ATTRIBUTE(400, "ATLAS-400-00-105", "Value Attribute can't be empty!"), INVALID_RELATIONSHIP_LABEL(400, "ATLAS-400-00-106", "Invalid relationship label {0}. The referenced entity type {1} could not be resolved from the type registry."), + NON_INDEXABLE_BM_DELETE_NOT_ALLOWED(400, "ATLAS-400-00-107", "Deletion not allowed for non-indexable Business Metadata ''{0}'' without force=true. Non-indexable attributes cannot be validated efficiently for references; use force=true to skip validation and delete (warning: orphaned references may remain)."), UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"), diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasBusinessMetadataType.java b/intg/src/main/java/org/apache/atlas/type/AtlasBusinessMetadataType.java index ccea47c7281..ed29bdd7a2d 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasBusinessMetadataType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasBusinessMetadataType.java @@ -44,12 +44,18 @@ public class AtlasBusinessMetadataType extends AtlasStructType { private final AtlasBusinessMetadataDef businessMetadataDef; + private boolean hasNonIndexableAttributes; + public AtlasBusinessMetadataType(AtlasBusinessMetadataDef businessMetadataDef) { super(businessMetadataDef); this.businessMetadataDef = businessMetadataDef; } + public boolean hasNonIndexableAttributes() { + return hasNonIndexableAttributes; + } + @Override public AtlasStruct createDefaultValue() { return null; // there is no runtime instance for businessMetadataDef, so return null @@ -71,6 +77,8 @@ void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException Map a = new HashMap<>(); + hasNonIndexableAttributes = false; + for (AtlasAttribute attribute : super.allAttributes.values()) { AtlasAttributeDef attributeDef = attribute.getAttributeDef(); String attrName = attribute.getName(); @@ -115,10 +123,16 @@ void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException bmAttribute = new AtlasBusinessAttribute(attribute, entityTypes); } + if (!hasNonIndexableAttributes && !attributeDef.getIsIndexable()) { + hasNonIndexableAttributes = true; + } + a.put(attrName, bmAttribute); } super.allAttributes = Collections.unmodifiableMap(a); + LOG.debug("CACHE-POPULATE [Phase1] BM='{}' hasNonIndexableAttributes={} totalAttributes={}", + getTypeName(), hasNonIndexableAttributes, a.size()); } @Override @@ -137,6 +151,29 @@ void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseExc } } + @Override + void resolveReferencesPhase3(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + super.resolveReferencesPhase3(typeRegistry); + + for (AtlasAttribute attribute : super.allAttributes.values()) { + AtlasBusinessAttribute bmAttribute = (AtlasBusinessAttribute) attribute; + Set entityTypes = bmAttribute.getApplicableEntityTypes(); + + if (CollectionUtils.isNotEmpty(entityTypes)) { + Set expandedTypeNames = new HashSet<>(); + + for (AtlasEntityType entityType : entityTypes) { + expandedTypeNames.add(entityType.getTypeName()); + expandedTypeNames.addAll(entityType.getAllSubTypes()); + } + + bmAttribute.applicableEntityTypeNamesWithSubTypes = Collections.unmodifiableSet(expandedTypeNames); + LOG.debug("CACHE-POPULATE [Phase3] BM='{}' attr='{}' expandedTypes={}", + getTypeName(), bmAttribute.getName(), expandedTypeNames); + } + } + } + public AtlasBusinessMetadataDef getBusinessMetadataDef() { return businessMetadataDef; } @@ -146,6 +183,8 @@ public static class AtlasBusinessAttribute extends AtlasAttribute { private final int maxStringLength; private final String validPattern; + private Set applicableEntityTypeNamesWithSubTypes = Collections.emptySet(); + public AtlasBusinessAttribute(AtlasAttribute attribute, Set applicableEntityTypes) { super(attribute); @@ -171,6 +210,10 @@ public Set getApplicableEntityTypes() { return applicableEntityTypes; } + public Set getApplicableEntityTypeNamesWithSubTypes() { + return applicableEntityTypeNamesWithSubTypes; + } + public String getValidPattern() { return validPattern; } diff --git a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java index 27ad72bf8d8..27fb27d1c22 100755 --- a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java +++ b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java @@ -625,6 +625,11 @@ public static AtlasTypesDef defineBusinessMetadataTypes() { createOptionalAttrDef("attrSuperBoolean", AtlasBusinessMetadataDef.ATLAS_TYPE_BOOLEAN, options, description), createOptionalAttrDef("attrSuperString", AtlasBusinessMetadataDef.ATLAS_TYPE_STRING, options, description)); + setBusinessMetadataAttributesIndexable(bmNoApplicableTypes); + setBusinessMetadataAttributesIndexable(bmWithAllTypes); + setBusinessMetadataAttributesIndexable(bmWithAllTypesMV); + setBusinessMetadataAttributesIndexable(bmWithSuperType); + AtlasTypesDef ret = AtlasTypeUtil.getTypesDef(new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), @@ -635,6 +640,16 @@ public static AtlasTypesDef defineBusinessMetadataTypes() { return ret; } + private static void setBusinessMetadataAttributesIndexable(AtlasBusinessMetadataDef def) { + if (def == null || CollectionUtils.isEmpty(def.getAttributeDefs())) { + return; + } + + for (AtlasAttributeDef ad : def.getAttributeDefs()) { + ad.setIsIndexable(true); + } + } + public static AtlasTypesDef defineHiveTypes() { String description = "_description"; AtlasEntityDef superTypeDefinition = diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasDefStore.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasDefStore.java index a956eecb41f..59828fd09e3 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasDefStore.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasDefStore.java @@ -45,9 +45,25 @@ public interface AtlasDefStore { AtlasVertex preDeleteByName(String name) throws AtlasBaseException; - void deleteByName(String name, AtlasVertex preDeleteResult) throws AtlasBaseException; - AtlasVertex preDeleteByGuid(String guid) throws AtlasBaseException; + void deleteByName(String name, AtlasVertex preDeleteResult) throws AtlasBaseException; + void deleteByGuid(String guid, AtlasVertex preDeleteResult) throws AtlasBaseException; + + default AtlasVertex preDeleteByName(String name, boolean forceDelete) throws AtlasBaseException { + return preDeleteByName(name); + } + + default void deleteByName(String name, AtlasVertex preDeleteResult, boolean forceDelete) throws AtlasBaseException { + deleteByName(name, preDeleteResult); + } + + default AtlasVertex preDeleteByGuid(String guid, boolean forceDelete) throws AtlasBaseException { + return preDeleteByGuid(guid); + } + + default void deleteByGuid(String guid, AtlasVertex preDeleteResult, boolean forceDelete) throws AtlasBaseException { + deleteByGuid(guid, preDeleteResult); + } } diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java index 4776912cd13..06a5bcee989 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java @@ -539,15 +539,19 @@ public AtlasTypesDef createUpdateTypesDef(AtlasTypesDef typesToCreate, AtlasType @Override @GraphTransaction public void deleteTypesDef(AtlasTypesDef typesDef) throws AtlasBaseException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasTypeDefGraphStore.deleteTypesDef(enums={}, structs={}, classfications={}, entities={}, relationships={}, businessMetadataDefs={})", - CollectionUtils.size(typesDef.getEnumDefs()), - CollectionUtils.size(typesDef.getStructDefs()), - CollectionUtils.size(typesDef.getClassificationDefs()), - CollectionUtils.size(typesDef.getEntityDefs()), - CollectionUtils.size(typesDef.getRelationshipDefs()), - CollectionUtils.size(typesDef.getBusinessMetadataDefs())); - } + deleteTypesDef(typesDef, false); + } + + @GraphTransaction + public void deleteTypesDef(AtlasTypesDef typesDef, boolean forceDelete) throws AtlasBaseException { + LOG.debug("==> AtlasTypeDefGraphStore.deleteTypesDef(enums={}, structs={}, classfications={}, entities={}, relationships={}, businessMetadataDefs={}, forceDelete={})", + CollectionUtils.size(typesDef.getEnumDefs()), + CollectionUtils.size(typesDef.getStructDefs()), + CollectionUtils.size(typesDef.getClassificationDefs()), + CollectionUtils.size(typesDef.getEntityDefs()), + CollectionUtils.size(typesDef.getRelationshipDefs()), + CollectionUtils.size(typesDef.getBusinessMetadataDefs()), + forceDelete); AtlasTransientTypeRegistry ttr = lockTypeRegistryAndReleasePostCommit(); @@ -678,9 +682,9 @@ public void deleteTypesDef(AtlasTypesDef typesDef) throws AtlasBaseException { if (CollectionUtils.isNotEmpty(typesDef.getBusinessMetadataDefs())) { for (AtlasBusinessMetadataDef businessMetadataDef : typesDef.getBusinessMetadataDefs()) { if (StringUtils.isNotBlank(businessMetadataDef.getGuid())) { - businessMetadataDefStore.deleteByGuid(businessMetadataDef.getGuid(), null); + businessMetadataDefStore.deleteByGuid(businessMetadataDef.getGuid(), null, forceDelete); } else { - businessMetadataDefStore.deleteByName(businessMetadataDef.getName(), null); + businessMetadataDefStore.deleteByName(businessMetadataDef.getName(), null, forceDelete); } } } @@ -777,7 +781,7 @@ public AtlasBaseTypeDef getByGuid(String guid) throws AtlasBaseException { @Override @GraphTransaction - public void deleteTypeByName(String typeName) throws AtlasBaseException { + public void deleteTypeByName(String typeName, boolean forceDelete) throws AtlasBaseException { AtlasType atlasType = typeRegistry.getType(typeName); if (atlasType == null) { @@ -801,7 +805,7 @@ public void deleteTypeByName(String typeName) throws AtlasBaseException { typesDef.setStructDefs(Collections.singletonList((AtlasStructDef) baseTypeDef)); } - deleteTypesDef(typesDef); + deleteTypesDef(typesDef, forceDelete); } @Override diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasAbstractDefStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasAbstractDefStoreV2.java index 609275c4b61..49bbb509652 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasAbstractDefStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasAbstractDefStoreV2.java @@ -148,24 +148,34 @@ public boolean isValidName(String typeName) { @Override public void deleteByName(String name, AtlasVertex preDeleteResult) throws AtlasBaseException { - LOG.debug("==> AtlasAbstractDefStoreV1.deleteByName({}, {})", name, preDeleteResult); + deleteByName(name, preDeleteResult, false); + } + + @Override + public void deleteByGuid(String guid, AtlasVertex preDeleteResult) throws AtlasBaseException { + deleteByGuid(guid, preDeleteResult, false); + } + + @Override + public void deleteByName(String name, AtlasVertex preDeleteResult, boolean forceDelete) throws AtlasBaseException { + LOG.debug("==> AtlasAbstractDefStoreV2.deleteByName({}, {}, {})", name, preDeleteResult, forceDelete); - AtlasVertex vertex = (preDeleteResult == null) ? preDeleteByName(name) : preDeleteResult; + AtlasVertex vertex = (preDeleteResult == null) ? preDeleteByName(name, forceDelete) : preDeleteResult; typeDefStore.deleteTypeVertex(vertex); - LOG.debug("<== AtlasAbstractDefStoreV1.deleteByName({}, {})", name, preDeleteResult); + LOG.debug("<== AtlasAbstractDefStoreV2.deleteByName({}, {}, {})", name, preDeleteResult, forceDelete); } @Override - public void deleteByGuid(String guid, AtlasVertex preDeleteResult) throws AtlasBaseException { - LOG.debug("==> AtlasAbstractDefStoreV1.deleteByGuid({}, {})", guid, preDeleteResult); + public void deleteByGuid(String guid, AtlasVertex preDeleteResult, boolean forceDelete) throws AtlasBaseException { + LOG.debug("==> AtlasAbstractDefStoreV2.deleteByGuid({}, {}, {})", guid, preDeleteResult, forceDelete); - AtlasVertex vertex = (preDeleteResult == null) ? preDeleteByGuid(guid) : preDeleteResult; + AtlasVertex vertex = (preDeleteResult == null) ? preDeleteByGuid(guid, forceDelete) : preDeleteResult; typeDefStore.deleteTypeVertex(vertex); - LOG.debug("<== AtlasAbstractDefStoreV1.deleteByGuid({}, {})", guid, preDeleteResult); + LOG.debug("<== AtlasAbstractDefStoreV2.deleteByGuid({}, {}, {})", guid, preDeleteResult, forceDelete); } public boolean isInvalidTypeDefName(String typeName) { diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java index 3543c2322e1..c53c3a78ec1 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2.java @@ -21,23 +21,21 @@ import org.apache.atlas.authorize.AtlasAuthorizationUtils; import org.apache.atlas.authorize.AtlasPrivilege; import org.apache.atlas.authorize.AtlasTypeAccessRequest; -import org.apache.atlas.discovery.EntityDiscoveryService; -import org.apache.atlas.discovery.SearchContext; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.TypeCategory; -import org.apache.atlas.model.discovery.AtlasSearchResult; -import org.apache.atlas.model.discovery.SearchParameters; import org.apache.atlas.model.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef; import org.apache.atlas.model.typedef.AtlasStructDef; import org.apache.atlas.repository.Constants; +import org.apache.atlas.repository.graphdb.AtlasGraph; +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.type.AtlasBusinessMetadataType; +import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.typesystem.types.DataTypes; -import org.apache.atlas.utils.AtlasJson; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -47,6 +45,7 @@ import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; @@ -56,13 +55,13 @@ public class AtlasBusinessMetadataDefStoreV2 extends AtlasAbstractDefStoreV2 { private static final Logger LOG = LoggerFactory.getLogger(AtlasBusinessMetadataDefStoreV2.class); - private final EntityDiscoveryService entityDiscoveryService; + private final AtlasGraph graph; @Inject - public AtlasBusinessMetadataDefStoreV2(AtlasTypeDefGraphStoreV2 typeDefStore, AtlasTypeRegistry typeRegistry, EntityDiscoveryService entityDiscoveryService) { + public AtlasBusinessMetadataDefStoreV2(AtlasTypeDefGraphStoreV2 typeDefStore, AtlasTypeRegistry typeRegistry, AtlasGraph graph) { super(typeDefStore, typeRegistry); - this.entityDiscoveryService = entityDiscoveryService; + this.graph = graph; } @Override @@ -258,8 +257,14 @@ public AtlasBusinessMetadataDef updateByGuid(String guid, AtlasBusinessMetadataD return ret; } + @Override public AtlasVertex preDeleteByName(String name) throws AtlasBaseException { - LOG.debug("==> AtlasBusinessMetadataDefStoreV2.preDeleteByName({})", name); + return preDeleteByName(name, false); + } + + @Override + public AtlasVertex preDeleteByName(String name, boolean forceDelete) throws AtlasBaseException { + LOG.debug("==> AtlasBusinessMetadataDefStoreV2.preDeleteByName({}, {})", name, forceDelete); AtlasBusinessMetadataDef existingDef = typeRegistry.getBusinessMetadataDefByName(name); @@ -271,15 +276,21 @@ public AtlasVertex preDeleteByName(String name) throws AtlasBaseException { throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); } - checkBusinessMetadataRef(existingDef.getName()); + validateDeletion(existingDef, forceDelete, name); - LOG.debug("<== AtlasBusinessMetadataDefStoreV2.preDeleteByName({}): {}", name, ret); + LOG.debug("<== AtlasBusinessMetadataDefStoreV2.preDeleteByName({}, {}): {}", name, forceDelete, ret); return ret; } + @Override public AtlasVertex preDeleteByGuid(String guid) throws AtlasBaseException { - LOG.debug("==> AtlasBusinessMetadataDefStoreV2.preDeleteByGuid({})", guid); + return preDeleteByGuid(guid, false); + } + + @Override + public AtlasVertex preDeleteByGuid(String guid, boolean forceDelete) throws AtlasBaseException { + LOG.debug("==> AtlasBusinessMetadataDefStoreV2.preDeleteByGuid({}, {})", guid, forceDelete); AtlasBusinessMetadataDef existingDef = typeRegistry.getBusinessMetadataDefByGuid(guid); @@ -291,15 +302,49 @@ public AtlasVertex preDeleteByGuid(String guid) throws AtlasBaseException { throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); } - if (existingDef != null) { - checkBusinessMetadataRef(existingDef.getName()); - } + validateDeletion(existingDef, forceDelete, guid); - LOG.debug("<== AtlasBusinessMetadataDefStoreV2.preDeleteByGuid({}): ret={}", guid, ret); + LOG.debug("<== AtlasBusinessMetadataDefStoreV2.preDeleteByGuid({}, {}): ret={}", guid, forceDelete, ret); return ret; } + private void validateDeletion(AtlasBusinessMetadataDef businessMetadataDef, boolean forceDelete, String identifier) throws AtlasBaseException { + if (businessMetadataDef == null) { + return; + } + + if (forceDelete) { + LOG.warn("Force-deleting BusinessMetadata '{}'. Skipping validation - orphaned references may remain.", businessMetadataDef.getName()); + return; + } + + if (hasNonIndexableAttribute(businessMetadataDef)) { + LOG.warn("Deletion blocked for non-indexable Business Metadata '{}' without force-delete flag", businessMetadataDef.getName()); + throw new AtlasBaseException(AtlasErrorCode.NON_INDEXABLE_BM_DELETE_NOT_ALLOWED, businessMetadataDef.getName()); + } + + checkBusinessMetadataRef(businessMetadataDef, identifier); + } + + private boolean hasNonIndexableAttribute(AtlasBusinessMetadataDef businessMetadataDef) { + AtlasBusinessMetadataType bmType = typeRegistry.getBusinessMetadataTypeByName(businessMetadataDef.getName()); + + if (bmType != null && bmType.hasNonIndexableAttributes()) { + return true; + } + + if (CollectionUtils.isNotEmpty(businessMetadataDef.getAttributeDefs())) { + for (AtlasStructDef.AtlasAttributeDef attributeDef : businessMetadataDef.getAttributeDefs()) { + if (!attributeDef.getIsIndexable()) { + return true; + } + } + } + + return false; + } + @Override public void validateType(AtlasBaseTypeDef typeDef) throws AtlasBaseException { super.validateType(typeDef); @@ -360,47 +405,100 @@ private AtlasBusinessMetadataDef toBusinessMetadataDef(AtlasVertex vertex) throw return ret; } - private void checkBusinessMetadataRef(String typeName) throws AtlasBaseException { - AtlasBusinessMetadataDef businessMetadataDef = typeRegistry.getBusinessMetadataDefByName(typeName); + private void checkBusinessMetadataRef(AtlasBusinessMetadataDef businessMetadataDef, String identifier) throws AtlasBaseException { + if (businessMetadataDef == null || CollectionUtils.isEmpty(businessMetadataDef.getAttributeDefs())) { + return; + } - if (businessMetadataDef != null) { - List attributeDefs = businessMetadataDef.getAttributeDefs(); + AtlasBusinessMetadataType bmType = typeRegistry.getBusinessMetadataTypeByName(businessMetadataDef.getName()); - for (AtlasStructDef.AtlasAttributeDef attributeDef : attributeDefs) { - String qualifiedName = AtlasStructType.AtlasAttribute.getQualifiedAttributeName(businessMetadataDef, attributeDef.getName()); - String vertexPropertyName = AtlasStructType.AtlasAttribute.generateVertexPropertyName(businessMetadataDef, attributeDef, qualifiedName); - Set applicableTypes = AtlasJson.fromJson(attributeDef.getOption(AtlasBusinessMetadataDef.ATTR_OPTION_APPLICABLE_ENTITY_TYPES), Set.class); + for (AtlasStructDef.AtlasAttributeDef attributeDef : businessMetadataDef.getAttributeDefs()) { + Set allApplicableTypes; - if (CollectionUtils.isNotEmpty(applicableTypes) && isBusinessAttributePresent(vertexPropertyName, applicableTypes)) { - throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, typeName); - } + if (bmType != null) { + AtlasBusinessMetadataType.AtlasBusinessAttribute bmAttr = + (AtlasBusinessMetadataType.AtlasBusinessAttribute) bmType.getAttribute(attributeDef.getName()); + Set cachedTypes = bmAttr != null ? bmAttr.getApplicableEntityTypeNamesWithSubTypes() : Collections.emptySet(); + + allApplicableTypes = CollectionUtils.isNotEmpty(cachedTypes) ? cachedTypes : getApplicableTypesWithSubTypes(attributeDef); + } else { + allApplicableTypes = getApplicableTypesWithSubTypes(attributeDef); } + + LOG.debug("REF-CHECK [ApplicableTypes] BM='{}' attr='{}' types={}", + businessMetadataDef.getName(), attributeDef.getName(), allApplicableTypes); + + if (CollectionUtils.isEmpty(allApplicableTypes)) { + continue; + } + + validateAttributeReferences(businessMetadataDef, attributeDef, allApplicableTypes, identifier); } } - private boolean isBusinessAttributePresent(String attrName, Set applicableTypes) throws AtlasBaseException { - SearchParameters.FilterCriteria criteria = new SearchParameters.FilterCriteria(); + private void validateAttributeReferences(AtlasBusinessMetadataDef bmDef, AtlasStructDef.AtlasAttributeDef attributeDef, + Set allApplicableTypes, String identifier) throws AtlasBaseException { + String qualifiedName = AtlasStructType.AtlasAttribute.getQualifiedAttributeName(bmDef, attributeDef.getName()); + String vertexPropertyName = AtlasStructType.AtlasAttribute.generateVertexPropertyName(bmDef, attributeDef, qualifiedName); + boolean isPresent = isBusinessAttributePresentInGraph(vertexPropertyName, allApplicableTypes); - criteria.setAttributeName(attrName); - criteria.setOperator(SearchParameters.Operator.NOT_EMPTY); + if (isPresent) { + LOG.warn("Cannot delete BusinessMetadata '{}' (request='{}') - attribute '{}' (vertex property: '{}') has references in entity types: {}", + bmDef.getName(), identifier, attributeDef.getName(), vertexPropertyName, allApplicableTypes); + throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, bmDef.getName()); + } + } - SearchParameters.FilterCriteria entityFilters = new SearchParameters.FilterCriteria(); + private boolean isBusinessAttributePresentInGraph(String vertexPropertyName, Set allApplicableTypes) throws AtlasBaseException { + if (CollectionUtils.isEmpty(allApplicableTypes)) { + return false; + } - entityFilters.setCondition(SearchParameters.FilterCriteria.Condition.OR); - entityFilters.setCriterion(Collections.singletonList(criteria)); + try { + List typesList = new ArrayList<>(allApplicableTypes); - SearchParameters searchParameters = new SearchParameters(); + AtlasGraphQuery query = graph.query() + .has(vertexPropertyName, AtlasGraphQuery.ComparisionOperator.NOT_EQUAL, (Object) null); - searchParameters.setTypeName(String.join(SearchContext.TYPENAME_DELIMITER, applicableTypes)); - searchParameters.setExcludeDeletedEntities(true); - searchParameters.setIncludeSubClassifications(false); - searchParameters.setEntityFilters(entityFilters); - searchParameters.setAttributes(Collections.singleton(attrName)); - searchParameters.setOffset(0); - searchParameters.setLimit(1); + List orConditions = new ArrayList<>(); + orConditions.add(query.createChildQuery().in(Constants.ENTITY_TYPE_PROPERTY_KEY, typesList)); + orConditions.add(query.createChildQuery().in(Constants.SUPER_TYPES_PROPERTY_KEY, typesList)); - AtlasSearchResult atlasSearchResult = entityDiscoveryService.searchWithParameters(searchParameters); + query.or(orConditions); - return CollectionUtils.isNotEmpty(atlasSearchResult.getEntities()); + Iterable vertices = query.vertices(1); + + if (vertices != null && vertices.iterator().hasNext()) { + return true; + } + } catch (Exception e) { + throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, + e, String.format("failed to validate BusinessMetadata references for property %s", vertexPropertyName)); + } + return false; + } + + /** + * Expands configured applicable entity types to include all concrete sub-types. + * Without this expansion, deletion checks can miss references present only on inherited child entity types. + */ + private Set getApplicableTypesWithSubTypes(AtlasStructDef.AtlasAttributeDef attributeDef) { + String applicableTypesJson = attributeDef.getOption(ATTR_OPTION_APPLICABLE_ENTITY_TYPES); + Set applicableTypeNames = StringUtils.isBlank(applicableTypesJson) ? null : AtlasType.fromJson(applicableTypesJson, Set.class); + + if (CollectionUtils.isEmpty(applicableTypeNames)) { + return Collections.emptySet(); + } + + Set result = new HashSet<>(applicableTypeNames); + + for (String typeName : applicableTypeNames) { + AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName); + + if (entityType != null) { + result.addAll(entityType.getAllSubTypes()); + } + } + return result; } } diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java index 57146521ab8..09f4dcc9bbf 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasTypeDefGraphStoreV2.java @@ -21,7 +21,6 @@ import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.RequestContext; import org.apache.atlas.annotation.GraphTransaction; -import org.apache.atlas.discovery.EntityDiscoveryService; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.listener.TypeDefChangeListener; import org.apache.atlas.model.typedef.AtlasBaseTypeDef; @@ -64,7 +63,7 @@ import static org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2.VERTEX_TYPE; /** - * Graph persistence store for TypeDef - v1 + * Graph persistence store for TypeDef - v2 */ @Singleton @Component @@ -73,16 +72,13 @@ public class AtlasTypeDefGraphStoreV2 extends AtlasTypeDefGraphStore { protected final AtlasGraph atlasGraph; - private final EntityDiscoveryService entityDiscoveryService; - @Inject - public AtlasTypeDefGraphStoreV2(AtlasTypeRegistry typeRegistry, List typeDefChangeListeners, AtlasGraph atlasGraph, EntityDiscoveryService entityDiscoveryService) { + public AtlasTypeDefGraphStoreV2(AtlasTypeRegistry typeRegistry, List typeDefChangeListeners, AtlasGraph atlasGraph) { super(typeRegistry, typeDefChangeListeners); - this.atlasGraph = atlasGraph; - this.entityDiscoveryService = entityDiscoveryService; + this.atlasGraph = atlasGraph; - LOG.debug("<== AtlasTypeDefGraphStoreV1()"); + LOG.debug("<== AtlasTypeDefGraphStoreV2()"); } public static String getCurrentUser() { @@ -177,17 +173,17 @@ protected AtlasDefStore getRelationshipDefStore(AtlasTypeR @Override protected AtlasDefStore getBusinessMetadataDefStore(AtlasTypeRegistry typeRegistry) { - return new AtlasBusinessMetadataDefStoreV2(this, typeRegistry, this.entityDiscoveryService); + return new AtlasBusinessMetadataDefStoreV2(this, typeRegistry, this.atlasGraph); } @Override @GraphTransaction public void init() throws AtlasBaseException { - LOG.info("==> AtlasTypeDefGraphStoreV1.init()"); + LOG.info("==> AtlasTypeDefGraphStoreV2.init()"); super.init(); - LOG.info("<== AtlasTypeDefGraphStoreV1.init()"); + LOG.info("<== AtlasTypeDefGraphStoreV2.init()"); } AtlasGraph getAtlasGraph() { diff --git a/repository/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java b/repository/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java index 792f714ad3f..64d8cf1c073 100644 --- a/repository/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java +++ b/repository/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java @@ -102,6 +102,8 @@ AtlasClassificationDef updateClassificationDefByGuid(String guid, AtlasClassific void deleteTypesDef(AtlasTypesDef typesDef) throws AtlasBaseException; + void deleteTypesDef(AtlasTypesDef typesDef, boolean forceDelete) throws AtlasBaseException; + AtlasTypesDef searchTypesDef(SearchFilter searchFilter) throws AtlasBaseException; /* Generic operation */ @@ -109,7 +111,7 @@ AtlasClassificationDef updateClassificationDefByGuid(String guid, AtlasClassific AtlasBaseTypeDef getByGuid(String guid) throws AtlasBaseException; - void deleteTypeByName(String typeName) throws AtlasBaseException; + void deleteTypeByName(String typeName, boolean forceDelete) throws AtlasBaseException; void notifyLoadCompletion(); } diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java index f84d1f4610e..90603af0341 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java @@ -369,10 +369,10 @@ public void deleteTypeByName() throws IOException { AtlasTypesDef typesDef = TestResourceFileUtils.readObjectFromJson(".", hivedbV2Json, AtlasTypesDef.class); typeDefStore.createTypesDef(typesDef); - typeDefStore.deleteTypeByName(hiveDB2); - typeDefStore.deleteTypeByName(relationshipDefName); - typeDefStore.deleteTypeByName(hostEntityDef); - typeDefStore.deleteTypeByName(clusterEntityDef); + typeDefStore.deleteTypeByName(hiveDB2, false); + typeDefStore.deleteTypeByName(relationshipDefName, false); + typeDefStore.deleteTypeByName(hostEntityDef, false); + typeDefStore.deleteTypeByName(clusterEntityDef, false); } catch (AtlasBaseException e) { fail("Deletion should've succeeded"); } diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2Test.java index a93ff804072..7f0fa866c71 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasBusinessMetadataDefStoreV2Test.java @@ -59,6 +59,7 @@ import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.fail; /* Please note that for these tests, since the typeRegistry can be injected only once, * any new tests should make sure that they flush the type registry at the end of the test. @@ -206,6 +207,39 @@ public void deleteBusinessMetadataDefWithNoAssignedTypes() throws AtlasBaseExcep } } + @Test + public void deleteBusinessMetadataDefWithMixedIndexableAttributesWithoutForceShouldFail() throws AtlasBaseException { + createBusinessMetadataTypesWithMixedIndexability(businessMetadataName); + + AtlasBusinessMetadataDef businessMetadataDef = findBusinessMetadataDef(businessMetadataName); + assertNotNull(businessMetadataDef); + + typesDefs = new AtlasTypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(businessMetadataDef)); + + try { + typeDefStore.deleteTypesDef(typesDefs, false); + fail("Deletion without force should fail when BM has non-indexable attributes"); + } catch (AtlasBaseException e) { + assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.NON_INDEXABLE_BM_DELETE_NOT_ALLOWED); + } + } + + @Test + public void deleteBusinessMetadataDefWithMixedIndexableAttributesWithForceShouldSucceed() throws AtlasBaseException { + createBusinessMetadataTypesWithMixedIndexability(businessMetadataName); + + AtlasBusinessMetadataDef businessMetadataDef = findBusinessMetadataDef(businessMetadataName); + assertNotNull(businessMetadataDef); + + typesDefs = new AtlasTypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(businessMetadataDef)); + + typeDefStore.deleteTypesDef(typesDefs, true); + + for (AtlasBusinessMetadataDef def : typeRegistry.getAllBusinessMetadataDefs()) { + assertNotEquals(def.getName(), businessMetadataName); + } + } + @Test public void updateBusinessMetadataDefs() throws AtlasBaseException { createBusinessMetadataTypes(businessMetadataName); @@ -494,6 +528,29 @@ private AtlasBusinessMetadataDef createBusinessMetadataDefWithoutAssignedTypes(S return businessMetadataDef1; } + private void createBusinessMetadataTypesWithMixedIndexability(String businessMetadataName) throws AtlasBaseException { + List businessMetadataDefs = new ArrayList<>(typesDefs.getBusinessMetadataDefs()); + + businessMetadataDefs.add(createBusinessMetadataDefWithMixedIndexability(businessMetadataName)); + + typesDefs.setBusinessMetadataDefs(businessMetadataDefs); + + AtlasTypesDef createdTypesDef = typeDefStore.createTypesDef(typesDefs); + + assertEquals(createdTypesDef.getBusinessMetadataDefs(), businessMetadataDefs, "Data integrity issue while persisting"); + } + + private AtlasBusinessMetadataDef createBusinessMetadataDefWithMixedIndexability(String businessMetadataName) { + AtlasBusinessMetadataDef businessMetadataDef = new AtlasBusinessMetadataDef(businessMetadataName, "test_mixed_indexability", null); + + addBusinessAttribute(businessMetadataDef, "mixed_indexable_attr", Collections.singleton("hive_table"), "string", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, true); + addBusinessAttribute(businessMetadataDef, "mixed_non_indexable_attr", Collections.singleton("hive_table"), "string", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, false); + + TestUtilsV2.populateSystemAttributes(businessMetadataDef); + + return businessMetadataDef; + } + private AtlasBusinessMetadataDef createBusinessMetadataDef2(String businessMetadataName) { AtlasBusinessMetadataDef businessMetadataDef1 = new AtlasBusinessMetadataDef(businessMetadataName, "test_description", null); @@ -525,6 +582,28 @@ private void addBusinessAttribute(AtlasBusinessMetadataDef businessMetadataDef, attributeDef.setOption(ATTR_MAX_STRING_LENGTH, "20"); } + attributeDef.setIsOptional(true); + attributeDef.setValuesMinCount(0); + attributeDef.setValuesMaxCount(1); + attributeDef.setIsUnique(false); + attributeDef.setDisplayName(name); + attributeDef.setIsIndexable(true); + + businessMetadataDef.addAttribute(attributeDef); + } + + private void addBusinessAttribute(AtlasBusinessMetadataDef businessMetadataDef, String name, Set applicableEntityTypes, String typeName, + AtlasStructDef.AtlasAttributeDef.Cardinality cardinality, boolean isIndexable) { + AtlasStructDef.AtlasAttributeDef attributeDef = new AtlasStructDef.AtlasAttributeDef(name, typeName); + + attributeDef.setCardinality(cardinality); + attributeDef.setOption(ATTR_OPTION_APPLICABLE_ENTITY_TYPES, AtlasType.toJson(applicableEntityTypes)); + + if (typeName.contains(AtlasBaseTypeDef.ATLAS_TYPE_STRING)) { + attributeDef.setOption(ATTR_MAX_STRING_LENGTH, "20"); + } + + attributeDef.setIsIndexable(isIndexable); attributeDef.setIsOptional(true); attributeDef.setValuesMinCount(0); attributeDef.setValuesMaxCount(1); diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java index e42b7627b11..9a2b679a0a2 100644 --- a/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java +++ b/webapp/src/main/java/org/apache/atlas/web/rest/TypesREST.java @@ -43,12 +43,14 @@ import javax.servlet.http.HttpServletRequest; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; @@ -399,25 +401,35 @@ public AtlasTypesDef updateAtlasTypeDefs(final AtlasTypesDef typesDef) throws At } /** - * Bulk delete API for all types - * @param typesDef A composite object that captures all types to be deleted + * Bulk delete API for all types. + * + * @param typesDef A composite object that captures all types to be deleted. + * @param forceDelete Supported only for BusinessMetadata typedefs: + * If true, bypasses pre-delete validation checks and forcefully removes the type definition. + * For BusinessMetadata only: + * - If isIndexable=true and force=false: performs normal graph scan validation + * - If isIndexable=false and force=false: blocks deletion (requires force=true) + * - If force=true: skips all validation and deletes the type + * Defaults to false for backward compatibility. * @throws AtlasBaseException * @HTTP 204 On successful deletion of the requested type definitions - * @HTTP 400 On validation failure for any type definitions + * @HTTP 400 On validation failure for any type definitions or when attempting to delete + * non-indexable BusinessMetadata without force-delete parameter */ @DELETE @Path("/typedefs") @Experimental @Timed - public void deleteAtlasTypeDefs(final AtlasTypesDef typesDef) throws AtlasBaseException { + public void deleteAtlasTypeDefs(final AtlasTypesDef typesDef, + @QueryParam("force") @DefaultValue("false") final boolean forceDelete) throws AtlasBaseException { AtlasPerfTracer perf = null; try { if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { - perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesREST.deleteAtlasTypeDefs(" + AtlasTypeUtil.toDebugString(typesDef) + ")"); + perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesREST.deleteAtlasTypeDefs(" + AtlasTypeUtil.toDebugString(typesDef) + ", force=" + forceDelete + ")"); } - typeDefStore.deleteTypesDef(typesDef); + typeDefStore.deleteTypesDef(typesDef, forceDelete); } finally { AtlasPerfTracer.log(perf); } @@ -426,22 +438,31 @@ public void deleteAtlasTypeDefs(final AtlasTypesDef typesDef) throws AtlasBaseEx /** * Delete API for type identified by its name. * @param typeName Name of the type to be deleted. + * @param forceDelete Supported only for BusinessMetadata typedefs: + * If true, bypasses pre-delete validation checks and forcefully removes the type definition. + * For BusinessMetadata only: + * - If isIndexable=true and force=false: performs normal graph scan validation + * - If isIndexable=false and force=false: blocks deletion (requires force=true) + * - If force=true: skips all validation and deletes the type + * Defaults to false for backward compatibility. * @throws AtlasBaseException * @HTTP 204 On successful deletion of the requested type definitions - * @HTTP 400 On validation failure for any type definitions + * @HTTP 400 On validation failure for any type definitions or when attempting to delete + * non-indexable BusinessMetadata without force-delete parameter */ @DELETE @Path("/typedef/name/{typeName}") @Timed - public void deleteAtlasTypeByName(@PathParam("typeName") final String typeName) throws AtlasBaseException { + public void deleteAtlasTypeByName(@PathParam("typeName") final String typeName, + @QueryParam("force") @DefaultValue("false") final boolean forceDelete) throws AtlasBaseException { AtlasPerfTracer perf = null; try { if (AtlasPerfTracer.isPerfTraceEnabled(PERF_LOG)) { - perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesREST.deleteAtlasTypeByName(" + typeName + ")"); + perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, "TypesREST.deleteAtlasTypeByName(" + typeName + ", force=" + forceDelete + ")"); } - typeDefStore.deleteTypeByName(typeName); + typeDefStore.deleteTypeByName(typeName, forceDelete); } finally { AtlasPerfTracer.log(perf); } diff --git a/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java b/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java index 0c74dc1d388..3ef8ed65af4 100644 --- a/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/adapters/TypeDefsRESTTest.java @@ -108,7 +108,7 @@ public void testDeleteAtlasBusinessTypeDefs() throws AtlasBaseException { AtlasErrorCode errorCode = null; try { - typesREST.deleteAtlasTypeByName(bmWithAllTypes); + typesREST.deleteAtlasTypeByName(bmWithAllTypes, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -124,7 +124,7 @@ public void testDeleteAtlasBusinessTypeDefs() throws AtlasBaseException { errorCode = null; try { - typesREST.deleteAtlasTypeByName(bmWithAllTypes); + typesREST.deleteAtlasTypeByName(bmWithAllTypes, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -135,7 +135,7 @@ public void testDeleteAtlasBusinessTypeDefs() throws AtlasBaseException { entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithAllTypes, objectMap); - typesREST.deleteAtlasTypeByName(bmWithAllTypes); + typesREST.deleteAtlasTypeByName(bmWithAllTypes, false); } @Test @@ -155,7 +155,7 @@ public void testDeleteAtlasBusinessTypeDefs_2() throws AtlasBaseException { AtlasErrorCode errorCode = null; try { - typesREST.deleteAtlasTypeByName(bmWithSuperType); + typesREST.deleteAtlasTypeByName(bmWithSuperType, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -171,7 +171,7 @@ public void testDeleteAtlasBusinessTypeDefs_2() throws AtlasBaseException { errorCode = null; try { - typesREST.deleteAtlasTypeByName(bmWithSuperType); + typesREST.deleteAtlasTypeByName(bmWithSuperType, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -182,7 +182,7 @@ public void testDeleteAtlasBusinessTypeDefs_2() throws AtlasBaseException { entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithSuperType, objectMap); - typesREST.deleteAtlasTypeByName(bmWithSuperType); + typesREST.deleteAtlasTypeByName(bmWithSuperType, false); } @Test @@ -209,7 +209,7 @@ public void testDeleteAtlasBusinessTypeDefs_3() throws AtlasBaseException { AtlasErrorCode errorCode = null; try { - typesREST.deleteAtlasTypeDefs(atlasTypesDef); + typesREST.deleteAtlasTypeDefs(atlasTypesDef, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -227,7 +227,7 @@ public void testDeleteAtlasBusinessTypeDefs_3() throws AtlasBaseException { errorCode = null; try { - typesREST.deleteAtlasTypeDefs(atlasTypesDef); + typesREST.deleteAtlasTypeDefs(atlasTypesDef, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -243,7 +243,7 @@ public void testDeleteAtlasBusinessTypeDefs_3() throws AtlasBaseException { errorCode = null; try { - typesREST.deleteAtlasTypeDefs(atlasTypesDef); + typesREST.deleteAtlasTypeDefs(atlasTypesDef, false); } catch (AtlasBaseException e) { errorCode = e.getAtlasErrorCode(); } @@ -254,7 +254,7 @@ public void testDeleteAtlasBusinessTypeDefs_3() throws AtlasBaseException { entityREST.removeBusinessAttributes(dbEntity.getGuid(), bmWithAllTypesMV, objectMap); - typesREST.deleteAtlasTypeDefs(atlasTypesDef); + typesREST.deleteAtlasTypeDefs(atlasTypesDef, false); } private void createTestEntity() throws AtlasBaseException { diff --git a/webapp/src/test/java/org/apache/atlas/web/rest/TypesRESTTest.java b/webapp/src/test/java/org/apache/atlas/web/rest/TypesRESTTest.java index 257a4b5ec58..bd44ab077f1 100644 --- a/webapp/src/test/java/org/apache/atlas/web/rest/TypesRESTTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/rest/TypesRESTTest.java @@ -532,7 +532,7 @@ public void testUpdateAtlasTypeDefs_WithException() throws AtlasBaseException { @Test public void testDeleteAtlasTypeDefs_Success() throws AtlasBaseException { // Setup - doNothing().when(typeDefStore).deleteTypesDef(mockTypesDef); + doNothing().when(typeDefStore).deleteTypesDef(mockTypesDef, false); try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class); MockedStatic mockedAtlasTypeUtil = mockStatic(AtlasTypeUtil.class)) { @@ -540,17 +540,17 @@ public void testDeleteAtlasTypeDefs_Success() throws AtlasBaseException { mockedAtlasTypeUtil.when(() -> AtlasTypeUtil.toDebugString(mockTypesDef)).thenReturn("debug_string"); // Execute - typesREST.deleteAtlasTypeDefs(mockTypesDef); + typesREST.deleteAtlasTypeDefs(mockTypesDef, false); // Verify - verify(typeDefStore).deleteTypesDef(mockTypesDef); + verify(typeDefStore).deleteTypesDef(mockTypesDef, false); } } @Test public void testDeleteAtlasTypeDefs_WithPerfTracerEnabled() throws AtlasBaseException { // Setup - doNothing().when(typeDefStore).deleteTypesDef(mockTypesDef); + doNothing().when(typeDefStore).deleteTypesDef(mockTypesDef, false); try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class); MockedStatic mockedAtlasTypeUtil = mockStatic(AtlasTypeUtil.class)) { @@ -559,10 +559,10 @@ public void testDeleteAtlasTypeDefs_WithPerfTracerEnabled() throws AtlasBaseExce mockedAtlasTypeUtil.when(() -> AtlasTypeUtil.toDebugString(mockTypesDef)).thenReturn("debug_string"); // Execute - typesREST.deleteAtlasTypeDefs(mockTypesDef); + typesREST.deleteAtlasTypeDefs(mockTypesDef, false); // Verify - verify(typeDefStore).deleteTypesDef(mockTypesDef); + verify(typeDefStore).deleteTypesDef(mockTypesDef, false); mockedPerfTracer.verify(() -> AtlasPerfTracer.isPerfTraceEnabled(any())); mockedPerfTracer.verify(() -> AtlasPerfTracer.getPerfTracer(any(), anyString())); } @@ -572,7 +572,7 @@ public void testDeleteAtlasTypeDefs_WithPerfTracerEnabled() throws AtlasBaseExce public void testDeleteAtlasTypeDefs_WithException() throws AtlasBaseException { // Setup AtlasBaseException exception = new AtlasBaseException("Delete failed"); - doThrow(exception).when(typeDefStore).deleteTypesDef(mockTypesDef); + doThrow(exception).when(typeDefStore).deleteTypesDef(mockTypesDef, false); try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class); MockedStatic mockedAtlasTypeUtil = mockStatic(AtlasTypeUtil.class)) { @@ -581,11 +581,29 @@ public void testDeleteAtlasTypeDefs_WithException() throws AtlasBaseException { // Execute & Verify AtlasBaseException thrownException = expectThrows(AtlasBaseException.class, () -> { - typesREST.deleteAtlasTypeDefs(mockTypesDef); + typesREST.deleteAtlasTypeDefs(mockTypesDef, false); }); assertEquals(thrownException.getMessage(), "Delete failed"); - verify(typeDefStore).deleteTypesDef(mockTypesDef); + verify(typeDefStore).deleteTypesDef(mockTypesDef, false); + } + } + + @Test + public void testDeleteAtlasTypeDefs_WithForceDelete() throws AtlasBaseException { + // Setup + doNothing().when(typeDefStore).deleteTypesDef(mockTypesDef, true); + + try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class); + MockedStatic mockedAtlasTypeUtil = mockStatic(AtlasTypeUtil.class)) { + mockedPerfTracer.when(() -> AtlasPerfTracer.isPerfTraceEnabled(any())).thenReturn(false); + mockedAtlasTypeUtil.when(() -> AtlasTypeUtil.toDebugString(mockTypesDef)).thenReturn("debug_string"); + + // Execute + typesREST.deleteAtlasTypeDefs(mockTypesDef, true); + + // Verify + verify(typeDefStore).deleteTypesDef(mockTypesDef, true); } } @@ -593,16 +611,16 @@ public void testDeleteAtlasTypeDefs_WithException() throws AtlasBaseException { public void testDeleteAtlasTypeByName_Success() throws AtlasBaseException { // Setup String typeName = "test_type"; - doNothing().when(typeDefStore).deleteTypeByName(typeName); + doNothing().when(typeDefStore).deleteTypeByName(typeName, false); try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class)) { mockedPerfTracer.when(() -> AtlasPerfTracer.isPerfTraceEnabled(any())).thenReturn(false); // Execute - typesREST.deleteAtlasTypeByName(typeName); + typesREST.deleteAtlasTypeByName(typeName, false); // Verify - verify(typeDefStore).deleteTypeByName(typeName); + verify(typeDefStore).deleteTypeByName(typeName, false); } } @@ -610,17 +628,17 @@ public void testDeleteAtlasTypeByName_Success() throws AtlasBaseException { public void testDeleteAtlasTypeByName_WithPerfTracerEnabled() throws AtlasBaseException { // Setup String typeName = "test_type_perf"; - doNothing().when(typeDefStore).deleteTypeByName(typeName); + doNothing().when(typeDefStore).deleteTypeByName(typeName, false); try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class)) { mockedPerfTracer.when(() -> AtlasPerfTracer.isPerfTraceEnabled(any())).thenReturn(true); mockedPerfTracer.when(() -> AtlasPerfTracer.getPerfTracer(any(), anyString())).thenReturn(null); // Execute - typesREST.deleteAtlasTypeByName(typeName); + typesREST.deleteAtlasTypeByName(typeName, false); // Verify - verify(typeDefStore).deleteTypeByName(typeName); + verify(typeDefStore).deleteTypeByName(typeName, false); mockedPerfTracer.verify(() -> AtlasPerfTracer.isPerfTraceEnabled(any())); mockedPerfTracer.verify(() -> AtlasPerfTracer.getPerfTracer(any(), anyString())); } @@ -631,18 +649,35 @@ public void testDeleteAtlasTypeByName_WithException() throws AtlasBaseException // Setup String typeName = "test_type_error"; AtlasBaseException exception = new AtlasBaseException("Delete by name failed"); - doThrow(exception).when(typeDefStore).deleteTypeByName(typeName); + doThrow(exception).when(typeDefStore).deleteTypeByName(typeName, false); try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class)) { mockedPerfTracer.when(() -> AtlasPerfTracer.isPerfTraceEnabled(any())).thenReturn(false); // Execute & Verify AtlasBaseException thrownException = expectThrows(AtlasBaseException.class, () -> { - typesREST.deleteAtlasTypeByName(typeName); + typesREST.deleteAtlasTypeByName(typeName, false); }); assertEquals(thrownException.getMessage(), "Delete by name failed"); - verify(typeDefStore).deleteTypeByName(typeName); + verify(typeDefStore).deleteTypeByName(typeName, false); + } + } + + @Test + public void testDeleteAtlasTypeByName_WithForceDelete() throws AtlasBaseException { + // Setup + String typeName = "test_type_force"; + doNothing().when(typeDefStore).deleteTypeByName(typeName, true); + + try (MockedStatic mockedPerfTracer = mockStatic(AtlasPerfTracer.class)) { + mockedPerfTracer.when(() -> AtlasPerfTracer.isPerfTraceEnabled(any())).thenReturn(false); + + // Execute with force=true + typesREST.deleteAtlasTypeByName(typeName, true); + + // Verify + verify(typeDefStore).deleteTypeByName(typeName, true); } } From 4a6325421e0592ac9613b32c2401e2e9af333653 Mon Sep 17 00:00:00 2001 From: Prasad Pawar <49935882+pawarprasad123@users.noreply.github.com> Date: Fri, 8 May 2026 13:18:24 +0530 Subject: [PATCH 04/51] ATLAS-5285: ATLAS UI: Dashboard - Common changes that are related to refresh the page. (#614) Atlas UI dashboard changes - Base for refresh UX (cherry picked from commit 6ec5cc3669e420e799d33a018ce912c2097010fb) --- .../src/components/DialogShowMoreLess.tsx | 1 + dashboard/src/components/Modal.tsx | 110 +++++++++++++----- dashboard/src/hooks/useAsyncPending.ts | 43 +++++++ dashboard/src/redux/reducers/reducers.ts | 2 + .../src/redux/slice/dashboardRefreshSlice.ts | 39 +++++++ dashboard/src/utils/refreshDashboardHome.ts | 30 +++++ dashboard/src/views/Layout/Header.tsx | 23 +++- dashboard/src/views/SideBar/SideBarBody.tsx | 71 +++++++---- 8 files changed, 257 insertions(+), 62 deletions(-) create mode 100644 dashboard/src/hooks/useAsyncPending.ts create mode 100644 dashboard/src/redux/slice/dashboardRefreshSlice.ts create mode 100644 dashboard/src/utils/refreshDashboardHome.ts diff --git a/dashboard/src/components/DialogShowMoreLess.tsx b/dashboard/src/components/DialogShowMoreLess.tsx index d782222e85c..03492d07706 100644 --- a/dashboard/src/components/DialogShowMoreLess.tsx +++ b/dashboard/src/components/DialogShowMoreLess.tsx @@ -576,6 +576,7 @@ const DialogShowMoreLess = ({ button2Label="Remove" button2Handler={handleRemove} disableButton2={removeLoader} + button2Loading={removeLoader} isDirty={true} > {relatedTerm ? ( diff --git a/dashboard/src/components/Modal.tsx b/dashboard/src/components/Modal.tsx index 75682d27742..373e5fee264 100644 --- a/dashboard/src/components/Modal.tsx +++ b/dashboard/src/components/Modal.tsx @@ -15,7 +15,7 @@ * limitations under the License. */ -import { styled } from "@mui/material/styles"; +import { styled, type Theme } from "@mui/material/styles"; import CircularProgress from "@mui/material/CircularProgress"; import Dialog from "@mui/material/Dialog"; import DialogActions from "@mui/material/DialogActions"; @@ -54,9 +54,13 @@ interface CustomModalProps { button2Label?: string | undefined; button2Handler: any; disableButton2?: string | object | boolean; + /** Shows spinner on primary action and blocks both footer buttons while an async action runs */ + button2Loading?: boolean; maxWidth?: any; footer?: boolean; isDirty?: boolean; + /** When true, only the first footer button is rendered (e.g. import error state). */ + hideButton2?: boolean; } export const CustomModal: React.FC = ({ @@ -71,10 +75,18 @@ export const CustomModal: React.FC = ({ button2Label, button2Handler, disableButton2, + button2Loading, maxWidth, isDirty, - footer + footer, + hideButton2 }) => { + const isLoading = Boolean(button2Loading); + const primaryDisabled = + isLoading || + Boolean(disableButton2) || + (isDirty !== undefined && !isDirty); + const handleClick = (event: { stopPropagation: () => void }) => { event.stopPropagation(); }; @@ -84,6 +96,7 @@ export const CustomModal: React.FC = ({ = ({ }} onClick={(e) => { e.stopPropagation(); + if (isLoading) { + return; + } onClose(); }} + disabled={isLoading} > @@ -145,8 +162,12 @@ export const CustomModal: React.FC = ({ { e.stopPropagation(); + if (isLoading) { + return; + } button1Handler(); }} > @@ -154,37 +175,62 @@ export const CustomModal: React.FC = ({ )} - + theme.palette.primary.main, + color: (theme: Theme) => + theme.palette.primary.contrastText + } + }), + ...(primaryDisabled && + !isLoading && { + "&.Mui-disabled": { + pointerEvents: "unset", + cursor: "not-allowed" + } + }) + }} + startIcon={ + isLoading ? ( + + theme.palette.primary.contrastText + }} + /> + ) : undefined + } + onClick={(e: Event) => { + e.stopPropagation(); + if (isLoading) { + return; } - }) - }} - startIcon={ - disableButton2 && isDirty ? ( - - ) : undefined - } - onClick={(e: Event) => { - e.stopPropagation(); - button2Handler(); - }} - > - {button2Label} - + button2Handler(); + }} + > + {button2Label} + + )} )} diff --git a/dashboard/src/hooks/useAsyncPending.ts b/dashboard/src/hooks/useAsyncPending.ts new file mode 100644 index 00000000000..b058f43927e --- /dev/null +++ b/dashboard/src/hooks/useAsyncPending.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +import { useCallback, useRef, useState } from "react"; + +/** + * Single-flight async guard + pending flag for primary actions (modals, forms). + * Reuse wherever a button triggers an API call and should show loading state. + */ +export const useAsyncPending = () => { + const [pending, setPending] = useState(false); + const busyRef = useRef(false); + + const run = useCallback(async (fn: () => Promise): Promise => { + if (busyRef.current) { + return undefined; + } + busyRef.current = true; + setPending(true); + try { + return await fn(); + } finally { + busyRef.current = false; + setPending(false); + } + }, []); + + return { pending, run }; +}; diff --git a/dashboard/src/redux/reducers/reducers.ts b/dashboard/src/redux/reducers/reducers.ts index 205006341a3..425fd9f804b 100644 --- a/dashboard/src/redux/reducers/reducers.ts +++ b/dashboard/src/redux/reducers/reducers.ts @@ -32,6 +32,7 @@ import { relationshipsReducer } from "@redux/slice/typeDefSlices/typedefRelation import { metricsReducer } from "@redux/slice/metricsSlice"; import { savedSearchReducer } from "@redux/slice/savedSearchSlice"; import { drawerSliceReducer } from "@redux/slice/drawerSlice"; +import { dashboardRefreshReducer } from "@redux/slice/dashboardRefreshSlice"; const rootReducer = combineReducers({ session: sessionReducer, @@ -39,6 +40,7 @@ const rootReducer = combineReducers({ typeHeader: typeHeaderReducer, allEntityTypes: allEntityTypesReducer, metrics: metricsReducer, + dashboardRefresh: dashboardRefreshReducer, classification: classificationReducer, businessMetaData: businessMetadataReducer, glossary: glossaryReducer, diff --git a/dashboard/src/redux/slice/dashboardRefreshSlice.ts b/dashboard/src/redux/slice/dashboardRefreshSlice.ts new file mode 100644 index 00000000000..cb21a5c9dab --- /dev/null +++ b/dashboard/src/redux/slice/dashboardRefreshSlice.ts @@ -0,0 +1,39 @@ +/* + * 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. + */ + +import { createSlice } from "@reduxjs/toolkit"; + +interface DashboardRefreshState { + version: number; +} + +const initialState: DashboardRefreshState = { + version: 0, +}; + +const dashboardRefreshSlice = createSlice({ + name: "dashboardRefresh", + initialState, + reducers: { + requestDashboardRefresh: (state) => { + state.version += 1; + }, + }, +}); + +export const { requestDashboardRefresh } = dashboardRefreshSlice.actions; +export const dashboardRefreshReducer = dashboardRefreshSlice.reducer; diff --git a/dashboard/src/utils/refreshDashboardHome.ts b/dashboard/src/utils/refreshDashboardHome.ts new file mode 100644 index 00000000000..1a2a6571ccc --- /dev/null +++ b/dashboard/src/utils/refreshDashboardHome.ts @@ -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. + */ + +import type { AppDispatch } from "@redux/store/store"; +import { requestDashboardRefresh } from "@redux/slice/dashboardRefreshSlice"; +import { fetchMetricEntity } from "@redux/slice/metricsSlice"; + +/** + * Soft-refresh dashboard home: bumps subscribers (latest entities, activity, + * QuickSearch) and refetches Redux metrics — same net calls as a full reload + * for those areas, without remounting the whole app. + */ +export const refreshDashboardHomeData = (dispatch: AppDispatch): void => { + dispatch(requestDashboardRefresh()); + dispatch(fetchMetricEntity()); +}; diff --git a/dashboard/src/views/Layout/Header.tsx b/dashboard/src/views/Layout/Header.tsx index 9e00e7eeac6..80fc2dc0627 100644 --- a/dashboard/src/views/Layout/Header.tsx +++ b/dashboard/src/views/Layout/Header.tsx @@ -29,7 +29,13 @@ import BarChartOutlinedIcon from "@mui/icons-material/BarChartOutlined"; import AccountCircleRoundedIcon from "@mui/icons-material/AccountCircleRounded"; import { useLocation, useNavigate } from "react-router-dom"; import QuickSearch from "@components/GlobalSearch/QuickSearch"; -import { Logout } from "@mui/icons-material"; +import CreateDropdown from "@components/CreateDropdown"; +import { + AdminPanelSettingsOutlined, + HelpOutlineOutlined, + Logout, + SwapHorizOutlined +} from "@mui/icons-material"; import { useAppSelector } from "@hooks/reducerHook"; import { Button, @@ -174,15 +180,17 @@ const Header: React.FC

= ({ )} - {location.pathname != "/" && - location.pathname != "/search" && - location.pathname != "/!" && - (!location.pathname.includes("!") ) && ( + {location.pathname !== "/" && + location.pathname !== "/search" && (
)} -
+ {(location.pathname === "/" || location.pathname === "/search") && ( +
+ )} +
+ = ({ }} data-cy="administrator" > + Administration + Help @@ -275,6 +285,7 @@ const Header: React.FC
= ({ handleClose(); }} > + Switch to Classic { + refreshDashboardHomeData(dispatch); + navigate( + { + pathname: "/search", + }, + { replace: true } + ); + }, [dispatch, navigate]); + + const handleAtlasLogoKeyDown = useCallback( + (e: KeyboardEvent) => { + if (e.key !== "Enter" && e.key !== " ") { + return; + } + e.preventDefault(); + handleAtlasLogoClick(); + }, + [handleAtlasLogoClick] + ); useEffect(() => { const draggerElement = draggerRef.current; @@ -236,14 +260,11 @@ const SideBarBody = (props: { cursor: "pointer", boxSizing: "border-box", }} - onClick={() => { - navigate( - { - pathname: "/search", - }, - { replace: true } - ); - }} + role="button" + tabIndex={0} + aria-label="Atlas home — refresh dashboard" + onClick={handleAtlasLogoClick} + onKeyDown={handleAtlasLogoKeyDown} data-cy="apache-atlas-logo-collapsed" > - Atlas logo { - navigate( - { - pathname: "/search", - }, - { replace: true } - ); - }} - className="header-logo cursor-pointer" - data-cy="atlas-logo" - /> + + + From bec31686b107abd932f23925385b71adc66c959b Mon Sep 17 00:00:00 2001 From: Prasad Pawar <49935882+pawarprasad123@users.noreply.github.com> Date: Sun, 10 May 2026 20:31:48 +0530 Subject: [PATCH 05/51] ATLAS-5246: ATLAS UI: Dashboard Overview - React UI Dashboard Implementation (#626) * ATLAS-5286: ATLAS UI: Dashboard - Filter query and shared view helpers changes (#615) * ATLAS-5287: ATLAS UI: Dashboard- search bar with dropdown (#616) * ATLAS-5267: ATLAS UI: Create Glossary: Add Import glossary terms tab (template + upload) (#617) * ATLAS-5256: ATLAS UI: Header - Create Button and Dropdown Menu. (#618) * ATLAS-5256: ATLAS UI: Header - Create Button and Dropdown Menu * ATLAS-5256: ATLAS UI: Header - Create Button and Dropdown Menu * ATLAS-5251: ATLAS UI : Dashboard - Latest Entities List (#619) * ATLAS-5247, ATLAS-5248, ATLAS-5249, ATLAS-5250, ATLAS-5252, ATLAS-5254, ATLAS-5255: ATLAS UI: Dashboard All cards. (#620) * ATLAS-5288: ATLAS UI: Dashboard - Classification and Admin Audits (#621) * ATLAS-5246: ATLAS UI: Dashboard Overview - React UI Dashboard Implementation (cherry picked from commit 874180f5edccb7992ede23f726e1b652c46dccd7) --- .../src/api/apiMethods/searchApiMethod.ts | 62 +- .../CreateDropdown/CreateDropdown.tsx | 176 +++ .../src/components/CreateDropdown/index.ts | 18 + dashboard/src/components/FilterQuery.tsx | 197 ++- .../components/GlobalSearch/QuickSearch.tsx | 1185 ++++++++++------- dashboard/src/components/ImportDialog.tsx | 44 +- .../src/components/QueryBuilder/Filters.tsx | 123 +- .../ShowMore/DrawerBodyChipView.tsx | 1 + .../src/components/ShowMore/ShowMoreView.tsx | 3 + .../src/components/Table/TablePagination.tsx | 120 +- dashboard/src/components/TreeNodeIcons.tsx | 42 +- .../components/TypeDefAuditDetailModal.tsx | 108 ++ dashboard/src/utils/CommonViewFunction.ts | 17 +- dashboard/src/utils/Enum.ts | 9 + dashboard/src/utils/apiErrorToastMessage.ts | 43 + dashboard/src/utils/auditTypeDefUtils.ts | 90 ++ dashboard/src/utils/dashboardSearchUtils.ts | 189 +++ .../src/utils/filterUrlCriterionRemoval.ts | 81 ++ dashboard/src/utils/glossaryImportFlow.ts | 57 + dashboard/src/utils/metricsUtils.ts | 241 ++++ dashboard/src/utils/scopedQuickSearchUtils.ts | 466 +++++++ dashboard/src/utils/typeCatalogUtils.ts | 159 +++ .../Administrator/AdministratorLayout.tsx | 22 +- .../Administrator/Audits/AuditResults.tsx | 78 +- .../BusinessMetadataAtrributeForm.tsx | 1 + .../BusinessMetadata/BusinessMetadataForm.tsx | 2 + dashboard/src/views/Classification/AddTag.tsx | 1 + .../views/Classification/AddTagAttributes.tsx | 1 + .../Classification/ClassificationForm.tsx | 5 +- .../src/views/Classification/DeleteTag.tsx | 1 + dashboard/src/views/DashBoard.tsx | 83 +- .../ClassificationCoverage.tsx | 394 ++++++ .../ClassificationDistributionCard.tsx | 227 ++++ .../DashboardOverview/DashboardOverview.tsx | 149 +++ .../DashboardOverview/DashboardSkeleton.tsx | 39 + .../DashboardOverview/EntityStatusDonut.tsx | 173 +++ .../DashboardOverview/EntityTypeBarChart.tsx | 327 +++++ .../EntityTypeBarChartSkeleton.tsx | 57 + .../KafkaTopicSummaryCard.tsx | 402 ++++++ .../DashboardOverview/LatestEntitiesList.tsx | 273 ++++ .../LatestEntitiesSkeleton.tsx | 53 + .../MessageConsumptionChart.tsx | 257 ++++ .../views/DashboardOverview/OverviewCard.tsx | 114 ++ .../DashboardOverview/RecentActivity.tsx | 408 ++++++ .../RecentActivitySkeleton.tsx | 37 + .../dashboardChartPalette.ts | 42 + .../latestEntitiesList.utils.ts | 64 + .../BusinessMetadataDetailsLayout.tsx | 2 + .../EntityDetailTabs/ClassificationsTab.tsx | 6 + .../PropagationPropertyModal.tsx | 1 + .../GlossaryDetails/TermRelation.tsx | 1 + dashboard/src/views/Entity/EntityForm.tsx | 1 + .../views/Glossary/AddUpdateCategoryForm.tsx | 1 + .../views/Glossary/AddUpdateGlossaryForm.tsx | 450 +++++-- .../src/views/Glossary/AddUpdateTermForm.tsx | 1 + .../src/views/Glossary/AssignCategory.tsx | 1 + dashboard/src/views/Glossary/AssignTerm.tsx | 1 + .../src/views/Glossary/DeleteGlossary.tsx | 52 +- .../src/views/SaveFilters/SaveFilters.tsx | 1 + .../src/views/SearchResult/SearchResult.tsx | 24 +- .../views/SideBar/SideBarTree/SideBarTree.tsx | 23 +- .../src/views/Statistics/ServerStats.tsx | 7 +- dashboard/src/views/Statistics/Statistics.tsx | 45 +- 63 files changed, 6330 insertions(+), 928 deletions(-) create mode 100644 dashboard/src/components/CreateDropdown/CreateDropdown.tsx create mode 100644 dashboard/src/components/CreateDropdown/index.ts create mode 100644 dashboard/src/components/TypeDefAuditDetailModal.tsx create mode 100644 dashboard/src/utils/apiErrorToastMessage.ts create mode 100644 dashboard/src/utils/auditTypeDefUtils.ts create mode 100644 dashboard/src/utils/dashboardSearchUtils.ts create mode 100644 dashboard/src/utils/filterUrlCriterionRemoval.ts create mode 100644 dashboard/src/utils/glossaryImportFlow.ts create mode 100644 dashboard/src/utils/metricsUtils.ts create mode 100644 dashboard/src/utils/scopedQuickSearchUtils.ts create mode 100644 dashboard/src/utils/typeCatalogUtils.ts create mode 100644 dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx create mode 100644 dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx create mode 100644 dashboard/src/views/DashboardOverview/DashboardOverview.tsx create mode 100644 dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx create mode 100644 dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx create mode 100644 dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx create mode 100644 dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx create mode 100644 dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx create mode 100644 dashboard/src/views/DashboardOverview/LatestEntitiesList.tsx create mode 100644 dashboard/src/views/DashboardOverview/LatestEntitiesSkeleton.tsx create mode 100644 dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx create mode 100644 dashboard/src/views/DashboardOverview/OverviewCard.tsx create mode 100644 dashboard/src/views/DashboardOverview/RecentActivity.tsx create mode 100644 dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx create mode 100644 dashboard/src/views/DashboardOverview/dashboardChartPalette.ts create mode 100644 dashboard/src/views/DashboardOverview/latestEntitiesList.utils.ts diff --git a/dashboard/src/api/apiMethods/searchApiMethod.ts b/dashboard/src/api/apiMethods/searchApiMethod.ts index 11a061e4f7f..8cc58f041df 100644 --- a/dashboard/src/api/apiMethods/searchApiMethod.ts +++ b/dashboard/src/api/apiMethods/searchApiMethod.ts @@ -56,10 +56,62 @@ const getRelationShipV2 = (params: { params: Record }) => { return fetchApi(url, { method: "GET" }); }; +/** Atlas `SearchParameters.sortBy` / `sortOrder` (see `SortOrder` enum: DESCENDING). */ +const LATEST_ENTITIES_TIMESTAMP_SORT = "__timestamp" as const; + +type LatestEntitiesSearchOptions = { + limit: number; + includeSubClassifications: boolean; +}; + +/** + * Request `__timestamp` so sort + “Created … ago” work. Do not set + * `excludeHeaderAttributes`: for `_ALL_ENTITY_TYPES`, Atlas validates each + * `attributes` entry against `__ENTITY_ROOT` and rejects `name` / `qualifiedName` + * / `guid` (see `excludeHeaderAttributesAllEntityType` in Atlas tests). Normal + * headers then include name, guid, typeName like the main basic search. + */ +const buildLatestEntitiesBasicBody = (opts: LatestEntitiesSearchOptions) => { + return { + typeName: "_ALL_ENTITY_TYPES", + excludeDeletedEntities: true, + includeClassificationAttributes: true, + includeSubTypes: true, + includeSubClassifications: opts.includeSubClassifications, + limit: opts.limit, + offset: 0, + tagFilters: null, + entityFilters: null, + classification: null, + termName: null, + relationshipFilters: null, + attributes: ["__timestamp"], + sortBy: LATEST_ENTITIES_TIMESTAMP_SORT, + sortOrder: "DESCENDING", + }; +}; + +/** + * Dashboard card only: newest entities by `__timestamp`, no entity filters, + * sub-classifications off, full entity headers for name/guid/type. + */ +const getLatestEntities = () => { + return getBasicSearchResult( + { + data: buildLatestEntitiesBasicBody({ + limit: 7, + includeSubClassifications: false, + }), + }, + "basic" + ); +}; + export { - getBasicSearchResult, - getRelationShipResult, - getGlobalSearchResult, - getRelationShip, - getRelationShipV2 + getBasicSearchResult, + getRelationShipResult, + getGlobalSearchResult, + getRelationShip, + getRelationShipV2, + getLatestEntities }; diff --git a/dashboard/src/components/CreateDropdown/CreateDropdown.tsx b/dashboard/src/components/CreateDropdown/CreateDropdown.tsx new file mode 100644 index 00000000000..cb32d4e2a93 --- /dev/null +++ b/dashboard/src/components/CreateDropdown/CreateDropdown.tsx @@ -0,0 +1,176 @@ +/* + * 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. + */ + +import { useState, useCallback } from "react"; +import { Button, Menu, MenuItem } from "@mui/material"; +import AddIcon from "@mui/icons-material/Add"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import CategoryIcon from "@mui/icons-material/Category"; +import LocalOfferIcon from "@mui/icons-material/LocalOffer"; +import MenuBookIcon from "@mui/icons-material/MenuBook"; +import BusinessCenterIcon from "@mui/icons-material/BusinessCenter"; +import ListIcon from "@mui/icons-material/List"; +import { useNavigate } from "react-router-dom"; +import EntityForm from "@views/Entity/EntityForm"; +import ClassificationForm from "@views/Classification/ClassificationForm"; +import AddUpdateGlossaryForm from "@views/Glossary/AddUpdateGlossaryForm"; +const CreateDropdown = () => { + const [anchorEl, setAnchorEl] = useState(null); + const [entityModal, setEntityModal] = useState(false); + const [classificationModal, setClassificationModal] = useState(false); + const [glossaryModal, setGlossaryModal] = useState(false); + const navigate = useNavigate(); + + const open = Boolean(anchorEl); + + const handleClick = useCallback((event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }, []); + + const handleClose = useCallback(() => { + setAnchorEl(null); + }, []); + + const handleEntityClick = useCallback(() => { + handleClose(); + setEntityModal(true); + }, [handleClose]); + + const handleClassificationClick = useCallback(() => { + handleClose(); + setClassificationModal(true); + }, [handleClose]); + + const handleGlossaryClick = useCallback(() => { + handleClose(); + setGlossaryModal(true); + }, [handleClose]); + + const handleBusinessMetadataClick = useCallback(() => { + handleClose(); + navigate({ + pathname: "/administrator", + search: "tabActive=businessMetadata&create=true" + }); + }, [handleClose, navigate]); + + const handleEnumClick = useCallback(() => { + handleClose(); + navigate({ + pathname: "/administrator", + search: "tabActive=enum" + }); + }, [handleClose, navigate]); + + return ( + <> + + + + + Entity + + + + Classification + + + + Glossary + + + + Business Metadata + + + + Enum + + + + {entityModal && ( + setEntityModal(false)} + /> + )} + {classificationModal && ( + setClassificationModal(false)} + /> + )} + {glossaryModal && ( + setGlossaryModal(false)} + node={undefined} + /> + )} + + ); +}; + +export default CreateDropdown; diff --git a/dashboard/src/components/CreateDropdown/index.ts b/dashboard/src/components/CreateDropdown/index.ts new file mode 100644 index 00000000000..8f1e1ff80de --- /dev/null +++ b/dashboard/src/components/CreateDropdown/index.ts @@ -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. + */ + +export { default } from "./CreateDropdown"; diff --git a/dashboard/src/components/FilterQuery.tsx b/dashboard/src/components/FilterQuery.tsx index 69ef98fd29d..20351c33a6f 100644 --- a/dashboard/src/components/FilterQuery.tsx +++ b/dashboard/src/components/FilterQuery.tsx @@ -22,8 +22,12 @@ import { attributeFilter } from "@utils/CommonViewFunction"; import { queryBuilderDateRangeUIValueToAPI, systemAttributes, - filterQueryValue + filterQueryValue, + getDisplayOperator } from "@utils/Enum"; +import { removeCriterionFromFilterUrl } from "@utils/filterUrlCriterionRemoval"; +import type { ParsedApiFilter } from "@utils/filterUrlCriterionRemoval"; +import { dateTimeFormat } from "@utils/Global"; import moment from "moment"; import { useLocation, useNavigate } from "react-router-dom"; import { globalSearchFilterInitialQuery } from "@utils/Utils"; @@ -45,13 +49,18 @@ export const FilterQuery = ({ value }: any) => { ); } else { - if (obj.type === "date" || obj.id == "createTime") { + const isDateAttr = + obj.type === "date" || + obj.id === "createTime" || + obj.id === "__timestamp" || + obj.id === "__modificationTimestamp"; + if (isDateAttr) { if (queryBuilderDateRangeUIValueToAPI[obj.value]) { obj.value = queryBuilderDateRangeUIValueToAPI[obj.value]; + } else if (/^\d+$/.test(String(obj.value))) { + obj.value = `${moment(Number(obj.value)).format(dateTimeFormat)} (${moment.tz(moment.tz.guess()).zoneAbbr()})`; } else { - obj.value = `${obj.value} (${moment - .tz(moment.tz.guess()) - .zoneAbbr()})`; + obj.value = `${obj.value} (${moment.tz(moment.tz.guess()).zoneAbbr()})`; } } @@ -60,6 +69,7 @@ export const FilterQuery = ({ value }: any) => { color="primary" className="chip-items" data-type={type} + data-rule-key={key} data-id={`${obj.id}${key}`} data-cy={`${obj.id}${key}`} label={ @@ -71,7 +81,7 @@ export const FilterQuery = ({ value }: any) => { : obj.id} - {obj.operator}{" "} + {getDisplayOperator(obj.operator)}{" "} {filterQueryValue[obj.id] @@ -97,9 +107,138 @@ export const FilterQuery = ({ value }: any) => { const clearQueryAttr = (e: any) => { const searchParams = new URLSearchParams(location.search); - const currentType: any = e?.target - ?.closest("[data-type]") - ?.getAttribute("data-type"); + const chipEl = (e?.target as HTMLElement)?.closest?.( + "[data-type]" + ) as HTMLElement | null; + const currentType = chipEl?.getAttribute("data-type"); + const ruleKeyRaw = chipEl?.getAttribute("data-rule-key"); + + const navigateAfterChange = (sp: URLSearchParams) => { + const meaningfulFilterParams = [ + "type", + "tag", + "query", + "term", + "relationshipName", + "entityFilters", + "tagFilters", + "relationshipFilters", + "excludeST", + "excludeSC", + "includeDE" + ]; + const hasMeaningfulFilters = meaningfulFilterParams.some((param) => + sp.has(param) + ); + if (!hasMeaningfulFilters) { + navigate({ + pathname: "/search" + }); + } else if ([...sp]?.length <= 1) { + navigate({ + pathname: "/search" + }); + } else { + navigate({ + pathname: "/search/searchResult", + search: sp.toString() + }); + } + }; + + const syncFilterParamGlobalState = ( + paramKey: "entityFilters" | "tagFilters" | "relationshipFilters", + urlValue: string | null + ) => { + if (!urlValue) { + globalSearchFilterInitialQuery.setQuery({ [paramKey]: [] }); + return; + } + const api = attributeFilter.extractUrl({ + value: urlValue, + apiObj: true + }) as ParsedApiFilter | null; + if (!api?.criterion || !Array.isArray(api.criterion)) { + globalSearchFilterInitialQuery.setQuery({ [paramKey]: [] }); + return; + } + globalSearchFilterInitialQuery.setQuery({ + [paramKey]: { + combinator: String(api.condition || "AND").toLowerCase(), + rules: api.criterion.map((rule: any, i: number) => ({ + id: `url-rule-${i}`, + field: rule.attributeName, + operator: getDisplayOperator(rule.operator) || rule.operator, + value: rule.attributeValue, + ...(rule.type ? { type: rule.type } : {}) + })) + } + }); + }; + + const isFilterCriterionChip = + ruleKeyRaw !== null && + ruleKeyRaw !== "" && + (currentType === "entityFilters" || + currentType === "tagFilters" || + currentType === "relationshipFilters"); + + if (isFilterCriterionChip) { + const idx = Number.parseInt(ruleKeyRaw as string, 10); + if (Number.isNaN(idx)) { + return; + } + const paramKey = currentType as + | "entityFilters" + | "tagFilters" + | "relationshipFilters"; + const raw = searchParams.get(paramKey); + if (!raw) { + return; + } + const allowSimplify = paramKey === "entityFilters"; + const result = removeCriterionFromFilterUrl(raw, idx, allowSimplify); + if (!result) { + return; + } + if (result.kind === "empty") { + searchParams.delete(paramKey); + globalSearchFilterInitialQuery.setQuery({ [paramKey]: [] }); + navigateAfterChange(searchParams); + return; + } + if (result.kind === "singleTypeName") { + searchParams.set("type", result.typeName); + searchParams.delete("entityFilters"); + if (searchParams.get("includeDE") === "true") { + const delUrl = attributeFilter.generateUrl({ + value: { + condition: "AND", + criterion: [ + { + attributeName: "__state", + operator: "eq", + attributeValue: "DELETED" + } + ] + } + }); + if (delUrl) { + searchParams.set("entityFilters", delUrl); + } + } + syncFilterParamGlobalState( + "entityFilters", + searchParams.get("entityFilters") + ); + navigateAfterChange(searchParams); + return; + } + searchParams.set(paramKey, result.url); + syncFilterParamGlobalState(paramKey, result.url); + navigateAfterChange(searchParams); + return; + } if (currentType == "term") { searchParams.delete("gtype"); @@ -127,43 +266,11 @@ export const FilterQuery = ({ value }: any) => { globalSearchFilterInitialQuery.setQuery({ [currentType]: [] }); } - searchParams.delete(currentType); - - // Check if there are any meaningful filters left after removal - const meaningfulFilterParams = [ - "type", - "tag", - "query", - "term", - "relationshipName", - "entityFilters", - "tagFilters", - "relationshipFilters", - "excludeST", - "excludeSC", - "includeDE" - ]; - - const hasMeaningfulFilters = meaningfulFilterParams.some((param) => - searchParams.has(param) - ); - - // If no meaningful filters remain, navigate to clear all (like Clear button) - if (!hasMeaningfulFilters) { - navigate({ - pathname: "/search" - }); - } else if ([...searchParams]?.length <= 1) { - // Only searchType or other system params remain - navigate({ - pathname: "/search" - }); - } else { - navigate({ - pathname: "/search/searchResult", - search: searchParams.toString() - }); + if (currentType) { + searchParams.delete(currentType); } + + navigateAfterChange(searchParams); }; if (value.type) { diff --git a/dashboard/src/components/GlobalSearch/QuickSearch.tsx b/dashboard/src/components/GlobalSearch/QuickSearch.tsx index 272ee107dbf..c8eba94903c 100644 --- a/dashboard/src/components/GlobalSearch/QuickSearch.tsx +++ b/dashboard/src/components/GlobalSearch/QuickSearch.tsx @@ -16,518 +16,715 @@ */ import { - Autocomplete, - CircularProgress, - InputAdornment, - Stack, - TextField, - Typography + Autocomplete, + CircularProgress, + FormControl, + InputAdornment, + MenuItem, + Select, + Stack, + TextField, + Typography, + type SelectChangeEvent } from "@mui/material"; -import { useRef, useState } from "react"; +import { useCallback, useMemo, useRef, useState } from "react"; import { getGlobalSearchResult } from "../../api/apiMethods/searchApiMethod"; import DisplayImage from "../EntityDisplayImage"; import SearchIcon from "@mui/icons-material/Search"; import { Link, useLocation, useNavigate } from "react-router-dom"; import { entityStateReadOnly } from "../../utils/Enum"; import { - extractKeyValueFromEntity, - isEmpty, - serverError + extractKeyValueFromEntity, + isEmpty, + serverError } from "../../utils/Utils"; import parse from "autosuggest-highlight/parse"; import match from "autosuggest-highlight/match"; import ClickAwayListener from "@mui/material/ClickAwayListener"; import AdvancedSearch from "./AdvancedSearch"; import { - HandleValuesType, - QuickSearchOptionListType, - SuggestionDataType + HandleValuesType, + QuickSearchOptionListType, + SuggestionDataType } from "../../models/globalSearchType"; import { AxiosResponse } from "axios"; import { CustomButton } from "@components/muiComponents"; +import { useAppSelector } from "@hooks/reducerHook"; +import { + buildBusinessMetadataScopedOptions, + buildClassificationScopedOptions, + buildEntitiesTreeForQuickSearch, + buildGlossaryTermsTreeForQuickSearch, + entityTreeToScopedOptions, + glossaryTreeToScopedOptions, + type QuickSearchScope, + type ScopedQuickSearchOption +} from "@utils/scopedQuickSearchUtils"; +import { + navigateToBasicTextQuery, + navigateToBusinessMetadataDetailPage, + navigateToClassificationDetailPage, + navigateToGlossaryTermDetailPage, + navigateToServiceTypeEntitySearch +} from "@utils/dashboardSearchUtils"; + +interface GlobalOptionRow { + title: string; + types: string; + entityObj?: any; + scoped?: ScopedQuickSearchOption; +} + +const SCOPE_SELECT_ID = "quick-search-scope-select"; + +const SCOPE_LABELS: Record = { + default: "Select All", + entity: "Entity", + classification: "Classification", + glossary: "Glossary / Terms", + businessMetadata: "Business Metadata" +}; const QuickSearch = () => { - const navigate = useNavigate(); - const location = useLocation(); - const toastId = useRef(null); - const searchParams = new URLSearchParams(location.search); - const [options, setOptions] = useState([]); - const [open, setOpen] = useState(false); - const [openAdvanceSearch, setOpenAdvanceSearch] = useState(false); - const [loading, setLoading] = useState(false); - const [value, setValue] = useState(""); - - const getData = async (searchTerm: string) => { - let entities: QuickSearchOptionListType = []; - let suggestionNames: QuickSearchOptionListType = []; - let quickSearchResp: AxiosResponse | null = null; - let suggestionSearchResp: AxiosResponse | null = null; - try { - setLoading(true); - quickSearchResp = await getGlobalSearchResult("quick", { - params: { query: searchTerm, limit: 5, offset: 0 } - }); - setLoading(false); - } catch (error) { - setLoading(false); - console.error("Error fetching quick search results:", error); - serverError(error, toastId); - } - - try { - setLoading(true); - suggestionSearchResp = await getGlobalSearchResult("suggestions", { - params: { prefixString: searchTerm } - }); - setLoading(false); - } catch (error) { - setLoading(false); - console.error("Error fetching suggestion search results:", error); - serverError(error, toastId); - } - const { searchResults = [] } = quickSearchResp?.data || {}; - const { suggestions = [] }: SuggestionDataType = - suggestionSearchResp?.data || {}; - - entities = !isEmpty(searchResults?.entities) - ? searchResults?.entities?.map((entityDef: any) => { - const { name }: { name: string; found: boolean; key: any } = - extractKeyValueFromEntity(entityDef); - return { - title: `${name}`, - parent: entityDef.typeName, - types: "Entities", - entityObj: entityDef - }; - }) - : [{ title: "No Entities Found", types: "Entities" }]; - - suggestionNames = !isEmpty(suggestions) - ? suggestions.map((suggestion: any) => { - return { - title: `${suggestion}`, - types: "Suggestions" - }; - }) - : [{ title: "No Suggestions Found", types: "Suggestions" }]; - - setOptions([...entities, ...suggestionNames]); - }; - - const onInputChange = (_event: any, value: string) => { - // Sanitize input: remove any potential script tags and validate - const sanitizedValue = value ? value.trim() : ""; - - if (sanitizedValue) { - setOpen(true); - getData(sanitizedValue); - } else { - setOptions([]); - setValue(""); - setOpen(false); - } - }; - - const handleValues = (option: HandleValuesType | string | null) => { - // Handle case when option is a string (direct search query) - if (typeof option === "string") { - const queryValue = option.trim(); - if (queryValue) { - setOpen(false); - setOptions([]); - // URLSearchParams automatically encodes the value, preventing XSS - // Additional validation: ensure query is not empty after trim - const sanitizedQuery = queryValue || "*"; - searchParams.set("query", sanitizedQuery); - searchParams.set("searchType", "basic"); - navigate( - { - pathname: `/search/searchResult`, - search: searchParams.toString() - }, - { replace: true } - ); - } - return; - } - - // Handle case when option is null or undefined - if (!option || typeof option !== "object") { - return; - } - - const { entityObj, title, types } = option; - - // Validate that title exists and is not undefined - if (!title || title === "undefined" || typeof title !== "string") { - return; - } - - // Sanitize title: trim and validate - const sanitizedTitle = title.trim(); - if (!sanitizedTitle) { - return; - } - - setOpen(false); - setOptions([]); - // URLSearchParams automatically encodes the value, preventing XSS - searchParams.set("query", sanitizedTitle); - searchParams.set("searchType", "basic"); - - if (types === "Entities" && entityObj && entityObj.guid) { - navigate( - { - pathname: `/detailPage/${entityObj.guid}` - }, - { replace: true } - ); - } else { - navigate( - { - pathname: `/search/searchResult`, - search: searchParams.toString() - }, - { replace: true } - ); - } - }; - - const handleClickAway = () => { - setOpen(false); - }; - - const handleCloseModal = () => { - setOpenAdvanceSearch(false); - }; - - return ( - <> - - - { - const code = e.keyCode || e.which; - - switch (code) { - case 13: { // Enter key - e.preventDefault(); - const inputValue = (e.target as HTMLInputElement).value.trim(); - - // If input is empty, use "*" for wildcard search (matching classic UI behavior) - const searchQuery = inputValue === "" ? "*" : inputValue; - - // Try to find exact match in options - const activeOption = options.find( - (option: { title: any }) => - typeof option !== "string" && - option.title === searchQuery - ); - - if (activeOption) { - // If exact match found, use that option - handleValues(activeOption as HandleValuesType); - } else { - // If no match found, trigger basic search with typed value (matching classic UI behavior) - handleValues(searchQuery); - } - break; - } - case 9: // Tab key - case 27: // Escape key - setOpen(false); - break; - default: - break; - } - }} - freeSolo - id="global-search" - disablePortal - className="global-search-autocomplete" - sx={{ - "& + .MuiAutocomplete-popper .MuiAutocomplete-option": { - backgroundColor: "white" - }, - "& + .MuiAutocomplete-popper .MuiAutocomplete-option:hover": { - backgroundColor: "#c7e3ff" - } - }} - value={value} - onChange={(_event: any, newValue: any) => { - if (newValue) { - // Only update options if newValue is a valid option object - if (typeof newValue === "object" && newValue.title) { - setOptions([newValue, ...options]); - } - setValue(newValue); - // Only call handleValues if newValue is a valid option - if (typeof newValue === "object" && newValue.title && newValue.title !== "undefined") { - handleValues(newValue); - } - } else { - setValue(""); - } - }} - clearOnBlur={false} - autoComplete={true} - includeInputInList - noOptionsText={"No Entities"} - disableClearable - onInputChange={onInputChange} - getOptionLabel={(option: string | QuickSearchOptionListType) => { - if (typeof option === "string") { - return option; - } - // Safely extract title, defaulting to empty string if undefined - const title = (option as any)?.title; - return title && typeof title === "string" ? title : ""; - }} - renderOption={(props, option, { inputValue }) => { - const { entityObj, types, parent } = - typeof option !== "string" && - "entityObj" in option && - "types" in option && - "parent" in option - ? (option as { - entityObj: { status?: string; guid?: string }; - types: string; - parent: string; - }) - : { entityObj: null, types: "", parent: "" }; - typeof option !== "string" && - "entityObj" in option && - "types" in option - ? option - : { entityObj: null, types: "", parent: "" }; - const title = - typeof option !== "string" && "title" in option - ? option.title - : option; - - // Validate and sanitize title to prevent XSS - const safeTitle = typeof title === "string" ? title : ""; - - // Validate guid to prevent XSS in URL - const guid = (entityObj as { guid?: string })?.guid; - const safeGuid = guid && typeof guid === "string" ? guid : ""; - const href = safeGuid ? `/detailPage/${safeGuid}` : "#"; - - const { name }: { name: string; found: boolean; key: any } = - extractKeyValueFromEntity(entityObj); - - // Safely handle name extraction - const safeName = name && typeof name === "string" ? name : ""; - - const matches = match( - types === "Entities" ? safeName : safeTitle, - inputValue || "", - { - findAllOccurrences: true, - insideWords: true - } - ); - const parts = parse( - types === "Entities" ? safeName : safeTitle, - matches - ); - return ( - span": { - mr: 2, - flexShrink: 0 - } - }} - {...props} - onClick={() => { - if (typeof option !== "string") { - handleValues(option as unknown as HandleValuesType); - } - }} - > - {types === "Entities" && !isEmpty(entityObj) ? ( - - {" "} - {types === "Entities" && !isEmpty(entityObj) && ( - - )}{" "} - {types === "Entities" && !isEmpty(entityObj) - ? parts.map((part, index) => ( - - {entityObj?.guid !== "-1" && !part.highlight ? ( - - {part.text} - - ) : ( - part.text - )} - - )) - : parts.map((part, index) => ( - - {part.text} - - ))} - {types === "Entities" && - !isEmpty(entityObj) && - ` (${parent})`} - - ) : ( - parts.map((part, index) => ( - - {" "} - {part.text} - - )) - )} - - ); - }} - renderInput={(params) => ( - { - setOpen(true); - }} - className="text-black-default" - InputProps={{ - style: { - padding: "1px 10px", - borderRadius: "4px", - color: "white !important", - opacity: 1 - }, - ...params.InputProps, - type: "search", - endAdornment: ( - - {loading ? ( - - ) : ( - - )} - - ) - }} - /> - )} - groupBy={(option) => - typeof option !== "string" && "types" in option - ? String(option.types) - : "" - } - options={options} - filterOptions={(options) => options} - /> - - - { - setOpenAdvanceSearch(true); - }} - > - - Advanced - - - - - {openAdvanceSearch && ( - - )} - - ); + const navigate = useNavigate(); + const location = useLocation(); + const toastId = useRef(null); + const searchParams = new URLSearchParams(location.search); + const [options, setOptions] = useState([]); + const [open, setOpen] = useState(false); + const [openAdvanceSearch, setOpenAdvanceSearch] = useState(false); + const [loading, setLoading] = useState(false); + const [inputText, setInputText] = useState(""); + const [scope, setScope] = useState("default"); + + const { typeHeaderData } = useAppSelector((state: any) => state.typeHeader); + const { metricsData } = useAppSelector((state: any) => state.metrics); + const { allEntityTypesData } = useAppSelector((state: any) => state.allEntityTypes); + const { classificationData } = useAppSelector((state: any) => state.classification); + const { glossaryData } = useAppSelector((state: any) => state.glossary); + const { businessMetaData } = useAppSelector((state: any) => state.businessMetaData); + + const entityTree = useMemo( + () => + buildEntitiesTreeForQuickSearch( + typeHeaderData, + metricsData?.data?.entity, + allEntityTypesData?.category + ), + [typeHeaderData, metricsData, allEntityTypesData] + ); + + const rebuildScopedOptions = useCallback( + (term: string): GlobalOptionRow[] => { + if (scope === "entity") { + return entityTreeToScopedOptions(entityTree, term).map((o) => ({ + title: o.title, + types: o.group, + scoped: o + })); + } + if (scope === "classification") { + return buildClassificationScopedOptions( + classificationData, + metricsData?.data?.tag?.tagEntities, + term + ).map((o) => ({ + title: o.title, + types: o.group, + scoped: o + })); + } + if (scope === "glossary") { + const gTree = buildGlossaryTermsTreeForQuickSearch(glossaryData); + return glossaryTreeToScopedOptions(gTree, term).map((o) => ({ + title: o.title, + types: o.group, + scoped: o + })); + } + if (scope === "businessMetadata") { + return buildBusinessMetadataScopedOptions( + businessMetaData?.businessMetadataDefs, + term + ).map((o) => ({ + title: o.title, + types: o.group, + scoped: o + })); + } + return []; + }, + [ + scope, + entityTree, + classificationData, + metricsData, + glossaryData, + businessMetaData + ] + ); + + const getGlobalSearchData = async (searchTerm: string) => { + let entities: QuickSearchOptionListType = []; + let suggestionNames: QuickSearchOptionListType = []; + let quickSearchResp: AxiosResponse | null = null; + let suggestionSearchResp: AxiosResponse | null = null; + try { + setLoading(true); + quickSearchResp = await getGlobalSearchResult("quick", { + params: { query: searchTerm, limit: 5, offset: 0 } + }); + setLoading(false); + } catch (error) { + setLoading(false); + console.error("Error fetching quick search results:", error); + serverError(error, toastId); + } + + try { + setLoading(true); + suggestionSearchResp = await getGlobalSearchResult("suggestions", { + params: { prefixString: searchTerm } + }); + setLoading(false); + } catch (error) { + setLoading(false); + console.error("Error fetching suggestion search results:", error); + serverError(error, toastId); + } + const { searchResults = [] } = quickSearchResp?.data || {}; + const { suggestions = [] }: SuggestionDataType = + suggestionSearchResp?.data || {}; + + entities = !isEmpty(searchResults?.entities) + ? searchResults?.entities?.map((entityDef: any) => { + const { name }: { name: string; found: boolean; key: any } = + extractKeyValueFromEntity(entityDef); + return { + title: `${name}`, + parent: entityDef.typeName, + types: "Entities", + entityObj: entityDef + }; + }) + : [{ title: "No Entities Found", types: "Entities" }]; + + suggestionNames = !isEmpty(suggestions) + ? suggestions.map((suggestion: any) => { + return { + title: `${suggestion}`, + types: "Suggestions" + }; + }) + : [{ title: "No Suggestions Found", types: "Suggestions" }]; + + setOptions([...entities, ...suggestionNames] as GlobalOptionRow[]); + }; + + const onInputChange = (_event: unknown, value: string) => { + const sanitizedValue = value ? value.trim() : ""; + setInputText(value ?? ""); + if (!sanitizedValue) { + setOptions([]); + setOpen(false); + return; + } + setOpen(true); + if (scope === "default") { + void getGlobalSearchData(sanitizedValue); + } else { + setOptions(rebuildScopedOptions(sanitizedValue)); + } + }; + + const handleScopedSelection = (opt: ScopedQuickSearchOption) => { + setOpen(false); + setOptions([]); + setInputText(""); + if (opt.kind === "entity-type" && opt.entityTypeName) { + navigateToBasicTextQuery(navigate, opt.entityTypeName); + return; + } + if (opt.kind === "entity-service" && opt.serviceUnderlyingTypeNames?.length) { + navigateToServiceTypeEntitySearch( + navigate, + opt.serviceUnderlyingTypeNames, + false + ); + return; + } + if (opt.kind === "classification" && opt.classificationName) { + navigateToClassificationDetailPage(navigate, opt.classificationName); + return; + } + if ( + opt.kind === "glossary-term" && + opt.termGuid && + opt.glossaryGuid && + opt.termId && + opt.termParent + ) { + navigateToGlossaryTermDetailPage(navigate, { + termGuid: opt.termGuid, + termId: opt.termId, + glossaryGuid: opt.glossaryGuid, + parentName: opt.termParent + }); + return; + } + if (opt.kind === "business-metadata" && opt.bmGuid) { + navigateToBusinessMetadataDetailPage(navigate, opt.bmGuid); + } + }; + + const handleValues = (option: HandleValuesType | GlobalOptionRow | string | null) => { + if (typeof option === "string") { + const queryValue = option.trim(); + if (!queryValue) return; + setOpen(false); + setOptions([]); + setInputText(""); + if (scope !== "default") { + return; + } + const sanitizedQuery = queryValue || "*"; + searchParams.set("query", sanitizedQuery); + searchParams.set("searchType", "basic"); + navigate( + { + pathname: `/search/searchResult`, + search: searchParams.toString() + }, + { replace: true } + ); + return; + } + + if (!option || typeof option !== "object") return; + + const row = option as GlobalOptionRow; + if (row.scoped) { + handleScopedSelection(row.scoped); + return; + } + + const { entityObj, title, types } = row as HandleValuesType; + if (!title || title === "undefined" || typeof title !== "string") return; + + const sanitizedTitle = title.trim(); + if (!sanitizedTitle) return; + + setOpen(false); + setOptions([]); + setInputText(""); + + searchParams.set("query", sanitizedTitle); + searchParams.set("searchType", "basic"); + + if (types === "Entities" && entityObj && entityObj.guid) { + navigate( + { + pathname: `/detailPage/${entityObj.guid}` + }, + { replace: true } + ); + } else { + navigate( + { + pathname: `/search/searchResult`, + search: searchParams.toString() + }, + { replace: true } + ); + } + }; + + const handleSubmitSearch = () => { + const q = inputText.trim(); + if (scope !== "default") { + const activeOption = options.find((o) => o.title === q); + if (activeOption?.scoped) { + handleScopedSelection(activeOption.scoped); + } + return; + } + if (!q) { + handleValues("*"); + return; + } + const activeOption = options.find( + (o) => typeof o !== "string" && o.title === q + ); + if (activeOption) { + handleValues(activeOption as HandleValuesType); + } else { + handleValues(q); + } + }; + + const handleScopeChange = (e: SelectChangeEvent) => { + const v = e.target.value as QuickSearchScope; + setScope(v); + setOptions([]); + setInputText(""); + setOpen(false); + }; + + const handleClickAway = () => { + setOpen(false); + }; + + const handleCloseModal = () => { + setOpenAdvanceSearch(false); + }; + + const inputPlaceholder = + scope === "default" ? "Search Entities..." : "Contains text..."; + + return ( + <> + + + + id={SCOPE_SELECT_ID} + value={scope} + onChange={handleScopeChange} + aria-label="Search scope" + displayEmpty + renderValue={(v) => SCOPE_LABELS[v as QuickSearchScope]} + > + Select All + Entity + Classification + Glossary / Terms + Business Metadata + + + + + { + const code = e.keyCode || e.which; + switch (code) { + case 13: { + e.preventDefault(); + handleSubmitSearch(); + break; + } + case 9: + case 27: + setOpen(false); + break; + default: + break; + } + }} + freeSolo + id="global-search" + disablePortal + className="global-search-autocomplete" + sx={{ + minWidth: 280, + flex: 1, + "& + .MuiAutocomplete-popper .MuiAutocomplete-option": { + backgroundColor: "white" + }, + "& + .MuiAutocomplete-popper .MuiAutocomplete-option:hover": { + backgroundColor: "#c7e3ff" + } + }} + value={null} + onChange={(_event: unknown, newValue: unknown) => { + if (newValue && typeof newValue === "object") { + const o = newValue as GlobalOptionRow; + if (o.title) { + handleValues(o); + } + } + }} + clearOnBlur={false} + autoComplete + includeInputInList + noOptionsText={scope === "default" ? "No Entities" : "No matches"} + getOptionLabel={(option: string | GlobalOptionRow) => { + if (typeof option === "string") return option; + return option?.title && typeof option.title === "string" + ? option.title + : ""; + }} + renderOption={(props, option, { inputValue }) => { + const row = option as GlobalOptionRow; + if (row.scoped) { + const title = row.title; + const matches = match(title, inputValue || "", { + findAllOccurrences: true, + insideWords: true + }); + const parts = parse(title, matches); + return ( +
  • + + {parts.map((part, index) => ( + + {part.text} + + ))} + +
  • + ); + } + + const { entityObj, types, parent } = + typeof option !== "string" && + "entityObj" in option && + "types" in option && + "parent" in option + ? (option as { + entityObj: { status?: string; guid?: string }; + types: string; + parent: string; + }) + : { entityObj: null, types: "", parent: "" }; + const title = + typeof option !== "string" && "title" in option + ? option.title + : option; + const safeTitle = typeof title === "string" ? title : ""; + const guid = (entityObj as { guid?: string })?.guid; + const safeGuid = guid && typeof guid === "string" ? guid : ""; + const href = safeGuid ? `/detailPage/${safeGuid}` : "#"; + const { name }: { name: string; found: boolean; key: any } = + extractKeyValueFromEntity(entityObj); + const safeName = name && typeof name === "string" ? name : ""; + const matches = match( + types === "Entities" ? safeName : safeTitle, + inputValue || "", + { + findAllOccurrences: true, + insideWords: true + } + ); + const parts = parse( + types === "Entities" ? safeName : safeTitle, + matches + ); + return ( + span": { + mr: 2, + flexShrink: 0 + } + }} + {...props} + onClick={() => { + handleValues(option as GlobalOptionRow); + }} + > + {types === "Entities" && !isEmpty(entityObj) ? ( + + {types === "Entities" && !isEmpty(entityObj) && ( + + )} + {types === "Entities" && !isEmpty(entityObj) + ? parts.map((part, index) => ( + + {entityObj?.guid !== "-1" && !part.highlight ? ( + + {part.text} + + ) : ( + part.text + )} + + )) + : parts.map((part, index) => ( + + {part.text} + + ))} + {types === "Entities" && + !isEmpty(entityObj) && + ` (${parent})`} + + ) : ( + parts.map((part, index) => ( + + {part.text} + + )) + )} + + ); + }} + renderInput={(params) => ( + { + setOpen(true); + }} + className="text-black-default" + InputProps={{ + style: { + padding: "1px 10px", + borderRadius: "4px", + color: "#1a1a1a", + backgroundColor: "white" + }, + ...params.InputProps, + type: "search", + endAdornment: ( + + {loading ? ( + + ) : ( + + )} + + ) + }} + inputProps={{ + ...params.inputProps, + "aria-label": "Global search" + }} + /> + )} + groupBy={(option) => + typeof option !== "string" && "types" in option + ? String((option as GlobalOptionRow).types) + : "" + } + options={options} + filterOptions={(x) => x} + /> +
    + + + Search + + + { + setOpenAdvanceSearch(true); + }} + > + + Advanced + + +
    + + {openAdvanceSearch && ( + + )} + + ); }; export default QuickSearch; diff --git a/dashboard/src/components/ImportDialog.tsx b/dashboard/src/components/ImportDialog.tsx index a3adfbb5490..10d82aa1d08 100644 --- a/dashboard/src/components/ImportDialog.tsx +++ b/dashboard/src/components/ImportDialog.tsx @@ -37,7 +37,8 @@ import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemText from "@mui/material/ListItemText"; import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew"; -import { getGlossaryImport } from "../api/apiMethods/glossaryApiMethod"; +import { postGlossaryImportFormData } from "@utils/glossaryImportFlow"; +import { getApiErrorToastMessage } from "@utils/apiErrorToastMessage"; const BootstrapDialog = styled(Dialog)(({ theme }) => ({ "& .MuiDialogContent-root": { @@ -77,22 +78,27 @@ export const ImportDialog: React.FC = ({ const onUpload = async () => { if (fileData) { try { - let apiMethod = + const onProgress = (progressValue: number) => { + setProgress(progressValue); + }; + const importResp = title == "Import Business Metadata" - ? getBusinessMetadataImport - : getGlossaryImport; - let formData = new FormData(); - formData.append("file", fileData); - const importResp = await apiMethod(formData, { - onUploadProgress: (progressEvent: { - loaded: number; - total: number; - }) => { - let progressValue = - (progressEvent.loaded / progressEvent.total) * 100; - setProgress(progressValue); - } - }); + ? await (async () => { + const formData = new FormData(); + formData.append("file", fileData); + return getBusinessMetadataImport(formData, { + onUploadProgress: (progressEvent: { + loaded: number; + total: number; + }) => { + if (!progressEvent.total) return; + onProgress( + (progressEvent.loaded / progressEvent.total) * 100 + ); + } + }); + })() + : await postGlossaryImportFormData(fileData, onProgress); if (importResp.data.failedImportInfoList == undefined) { toast.dismiss(toastId.current); @@ -114,8 +120,12 @@ export const ImportDialog: React.FC = ({ } setImportData(importResp.data); } catch (error) { + const message = getApiErrorToastMessage(error); + if (message === null) { + return; + } toast.dismiss(toastId.current); - toastId.current = toast.error(`Invalid JSON response from server`); + toastId.current = toast.error(message); } } }; diff --git a/dashboard/src/components/QueryBuilder/Filters.tsx b/dashboard/src/components/QueryBuilder/Filters.tsx index 2b305510ec3..d162f28e6a2 100644 --- a/dashboard/src/components/QueryBuilder/Filters.tsx +++ b/dashboard/src/components/QueryBuilder/Filters.tsx @@ -25,7 +25,7 @@ import { FormControlLabel } from "@mui/material"; -import { useState } from "react"; +import { useState, useEffect, useMemo } from "react"; import { Accordion, AccordionDetails, @@ -47,6 +47,7 @@ import { useAppSelector } from "@hooks/reducerHook"; import { cloneDeep } from "@utils/Helper"; import { getObjDef } from "@views/Administrator/Audits/AuditsFilter/AuditFiltersFields"; import { attributeFilter } from "@utils/CommonViewFunction"; +import { getDisplayOperator } from "@utils/Enum"; import moment from "moment"; import RelationshipFilters from "./RelationshipFilters"; import TypeFilters from "./TypeFilters/TypeFilters"; @@ -70,28 +71,66 @@ const Filters = ({ const tagParams = searchParams.get("tag"); const relationshipParams = searchParams.get("relationshipName"); const entityFilterParams = searchParams.get("entityFilters"); - const [checkedEntities, setCheckedEntities] = useState( - !isEmpty(searchParams.get("includeDE")) - ? searchParams.get("includeDE") - : false + const [checkedEntities, setCheckedEntities] = useState( + searchParams.get("includeDE") === "true" || searchParams.get("includeDE") === true ); - const [checkedSubClassifications, setCheckedSubClassifications] = - useState( - !isEmpty(searchParams.get("excludeSC")) - ? searchParams.get("excludeSC") - : false - ); - const [checkedSubTypes, setCheckedSubTypes] = useState( - !isEmpty(searchParams.get("excludeST")) - ? searchParams.get("excludeST") - : false + const [checkedSubClassifications, setCheckedSubClassifications] = useState( + searchParams.get("excludeSC") === "true" || searchParams.get("excludeSC") === true + ); + const [checkedSubTypes, setCheckedSubTypes] = useState( + searchParams.get("excludeST") === "true" || searchParams.get("excludeST") === true ); + const parseFiltersFromUrl = (params: string | null) => { + if (isEmpty(params)) return null; + const parsed = attributeFilter.extractUrl({ + value: params, + formatDate: true + }); + if (!parsed?.rules) return null; + const rulesArr = Array.isArray(parsed.rules) + ? parsed.rules + : Object.keys(parsed.rules || {}).map((k) => parsed.rules[k]); + const mappedRules = rulesArr + .filter((r) => r && !r.condition) + .map((r, i) => ({ + field: r.id, + operator: getDisplayOperator(r.operator) || r.operator, + value: r.value, + id: `url-rule-${i}` + })); + if (mappedRules.length === 0) return null; + return { + combinator: (parsed.condition || "AND").toLowerCase(), + rules: mappedRules + }; + }; + + const entityFiltersFromUrl = parseFiltersFromUrl(entityFilterParams); + const tagFilterParams = searchParams.get("tagFilters"); + const relationshipFilterParams = searchParams.get("relationshipFilters"); + const tagFiltersFromUrl = parseFiltersFromUrl(tagFilterParams); + const relationshipFiltersFromUrl = parseFiltersFromUrl(relationshipFilterParams); + const [typeQuery, setTypeQuery] = useState( !isEmpty(globalSearchFilterInitialQuery.getQuery()?.entityFilters) && !isEmpty(entityFilterParams) ? globalSearchFilterInitialQuery.getQuery()?.entityFilters - : initialQuery + : !isEmpty(entityFiltersFromUrl) + ? entityFiltersFromUrl + : initialQuery ); + + useEffect(() => { + if ( + !isEmpty(entityFilterParams) && + isEmpty(globalSearchFilterInitialQuery.getQuery()?.entityFilters) && + !isEmpty(entityFiltersFromUrl) + ) { + globalSearchFilterInitialQuery.setQuery({ + entityFilters: entityFiltersFromUrl + }); + } + }, [entityFilterParams]); const [classificationQuery, setClassificationQuery] = useState( !isEmpty(globalSearchFilterInitialQuery.getQuery()?.tagFilters) ? globalSearchFilterInitialQuery.getQuery()?.tagFilters @@ -125,28 +164,63 @@ const Filters = ({ businessMetadata: businessMetadataDefs }; + const appliedIncludeDE = searchParams.get("includeDE") === "true" || searchParams.get("includeDE") === true; + const appliedExcludeSC = searchParams.get("excludeSC") === "true" || searchParams.get("excludeSC") === true; + const appliedExcludeST = searchParams.get("excludeST") === "true" || searchParams.get("excludeST") === true; + + const hasChanges = useMemo(() => { + const switchChanged = + !!checkedEntities !== !!appliedIncludeDE || + !!checkedSubClassifications !== !!appliedExcludeSC || + !!checkedSubTypes !== !!appliedExcludeST; + + const normalizeQuery = (q: RuleGroupType | null) => { + if (!q || !q.rules || q.rules.length === 0) return JSON.stringify({ combinator: "and", rules: [] }); + return JSON.stringify({ combinator: q.combinator || "and", rules: q.rules }); + }; + + const entityQueryChanged = + normalizeQuery(typeQuery) !== normalizeQuery(entityFiltersFromUrl || initialQuery); + const tagQueryChanged = + normalizeQuery(classificationQuery) !== normalizeQuery(tagFiltersFromUrl || initialQuery); + const relationshipQueryChanged = + normalizeQuery(relationshipQuery) !== normalizeQuery(relationshipFiltersFromUrl || initialQuery); + + return switchChanged || entityQueryChanged || tagQueryChanged || relationshipQueryChanged; + }, [ + checkedEntities, + checkedSubClassifications, + checkedSubTypes, + appliedIncludeDE, + appliedExcludeSC, + appliedExcludeST, + typeQuery, + classificationQuery, + relationshipQuery, + entityFiltersFromUrl, + tagFiltersFromUrl, + relationshipFiltersFromUrl + ]); + const handleSwitchChangeEntities = ( event: React.ChangeEvent ) => { event.stopPropagation(); - searchParams.set("includeDE", event.target.checked); - setCheckedEntities(event.target.checked); + setCheckedEntities(Boolean(event.target.checked)); }; const handleSwitchChangeSubClassification = ( event: React.ChangeEvent ) => { event.stopPropagation(); - searchParams.set("excludeSC", event.target.checked); - setCheckedSubClassifications(event.target.checked); + setCheckedSubClassifications(Boolean(event.target.checked)); }; const handleSwitchChangeSubTypes = ( event: React.ChangeEvent ) => { event.stopPropagation(); - searchParams.set("excludeST", event.target.checked); - setCheckedSubTypes(event.target.checked); + setCheckedSubTypes(Boolean(event.target.checked)); }; const paramsObject: Record = {}; @@ -187,9 +261,9 @@ const Filters = ({ let rules_widgets = null; let systemAttrArr; - if (!isEmpty(paramsObject)) { + if (!isEmpty(paramsObject?.entityFilters)) { rules_widgets = attributeFilter.extractUrl({ - value: undefined, + value: paramsObject.entityFilters, formatDate: true }); } @@ -699,6 +773,7 @@ const Filters = ({ { applyFilter(); }} diff --git a/dashboard/src/components/ShowMore/DrawerBodyChipView.tsx b/dashboard/src/components/ShowMore/DrawerBodyChipView.tsx index 5a082ef7e0e..38f702af633 100644 --- a/dashboard/src/components/ShowMore/DrawerBodyChipView.tsx +++ b/dashboard/src/components/ShowMore/DrawerBodyChipView.tsx @@ -388,6 +388,7 @@ const DrawerBodyChipView = ({ button2Label="Remove" button2Handler={handleRemove} disableButton2={removeLoader} + button2Loading={removeLoader} > Remove:{" "} diff --git a/dashboard/src/components/ShowMore/ShowMoreView.tsx b/dashboard/src/components/ShowMore/ShowMoreView.tsx index 5a0f1cfc00c..3761d0a4d1c 100644 --- a/dashboard/src/components/ShowMore/ShowMoreView.tsx +++ b/dashboard/src/components/ShowMore/ShowMoreView.tsx @@ -182,6 +182,8 @@ const ShowMoreView = ({ } } catch (error) { serverError(error, toastId); + } finally { + setRemoveLoader(false); } }; @@ -379,6 +381,7 @@ const ShowMoreView = ({ button2Label="Remove" button2Handler={handleRemove} disableButton2={removeLoader} + button2Loading={removeLoader} > Remove:{" "} diff --git a/dashboard/src/components/Table/TablePagination.tsx b/dashboard/src/components/Table/TablePagination.tsx index 7577f00076a..792d1a7115a 100644 --- a/dashboard/src/components/Table/TablePagination.tsx +++ b/dashboard/src/components/Table/TablePagination.tsx @@ -369,6 +369,18 @@ const TablePagination: React.FC = ({ ? pageTo : Math.min((pageIndex + 1) * pageSize, totalDatasetRows); + /** Last page may return fewer than `limit` rows; cap "to" at known total. */ + const displayToCapped = + isServerSide && + typeof totalCount === "number" && + totalCount >= 0 + ? Math.min(displayTo, totalCount) + : displayTo; + + const footerRangeStart = + totalDatasetRows === 0 ? 0 : Math.min(displayFrom, displayToCapped); + const footerRangeEnd = totalDatasetRows === 0 ? 0 : displayToCapped; + return ( = ({ >
    - Showing {totalDatasetRows.toLocaleString()} records From{" "} - {displayFrom} - {displayTo} + {totalDatasetRows === 0 ? ( + "No records to display" + ) : ( + <> + Showing {footerRangeStart.toLocaleString()}- + {footerRangeEnd.toLocaleString()} of{" "} + {totalDatasetRows.toLocaleString()}{" "} + {totalDatasetRows === 1 ? "record" : "records"} + + )}
    @@ -491,25 +511,27 @@ const TablePagination: React.FC = ({ value={pendingGoToPageVal} /> - { - if (!isEmpty(pendingGoToPageVal)) { - setGoToPageTrigger(pendingGoToPageVal); - handleGoToPage(); - } - }} - disabled={isEmpty(pendingGoToPageVal)} - > - Go - + + { + if (!isEmpty(pendingGoToPageVal)) { + setGoToPageTrigger(pendingGoToPageVal); + handleGoToPage(); + } + }} + disabled={isEmpty(pendingGoToPageVal)} + > + Go + +
    @@ -517,19 +539,21 @@ const TablePagination: React.FC = ({ - - {theme.direction === "rtl" ? ( - - ) : ( - - )} - + + + {theme.direction === "rtl" ? ( + + ) : ( + + )} + + @@ -539,19 +563,21 @@ const TablePagination: React.FC = ({ - - {theme.direction === "rtl" ? ( - - ) : ( - - )} - + + + {theme.direction === "rtl" ? ( + + ) : ( + + )} + + diff --git a/dashboard/src/components/TreeNodeIcons.tsx b/dashboard/src/components/TreeNodeIcons.tsx index 3e56f70e82a..5403a2a9d63 100644 --- a/dashboard/src/components/TreeNodeIcons.tsx +++ b/dashboard/src/components/TreeNodeIcons.tsx @@ -16,6 +16,7 @@ */ import { useRef, useState } from "react"; +import { useAsyncPending } from "../hooks/useAsyncPending"; import IconButton from "@mui/material/IconButton"; import Menu from "@mui/material/Menu"; import Stack from "@mui/material/Stack"; @@ -72,6 +73,9 @@ const TreeNodeIcons = (props: { const [glossaryModal, setGlossaryModal] = useState(false); const [termModal, setTermModal] = useState(false); const [categoryModal, setCategoryModal] = useState(false); + const [savedSearchDeleteLoading, setSavedSearchDeleteLoading] = + useState(false); + const { pending: renameSubmitting, run: runRenameAction } = useAsyncPending(); const openNode = Boolean(expandNode); @@ -128,6 +132,7 @@ const TreeNodeIcons = (props: { const handleRemove = async () => { try { + setSavedSearchDeleteLoading(true); await removeSavedSearch(selectedSearchData.guid); setDeleteModal(false); setExpandNode(null); @@ -142,23 +147,27 @@ const TreeNodeIcons = (props: { toastId.current = toast.success(`${node.id} was deleted successfully`); } catch (error) { serverError(error, toastId); + } finally { + setSavedSearchDeleteLoading(false); } }; - const handleEdit = async () => { - try { - let filterData = { ...selectedSearchData, name: value }; - await editSavedSearch(filterData as CustomFiltersNodeType, "PUT"); - updatedData(); - setRenameModal(false); - setExpandNode(null); - toast.dismiss(toastId.current); - toastId.current = toast.success( - `${filterData.name} was updated successfully` - ); - } catch (error) { - serverError(error, toastId); - } + const handleEdit = () => { + void runRenameAction(async () => { + try { + let filterData = { ...selectedSearchData, name: value }; + await editSavedSearch(filterData as CustomFiltersNodeType, "PUT"); + updatedData(); + setRenameModal(false); + setExpandNode(null); + toast.dismiss(toastId.current); + toastId.current = toast.success( + `${filterData.name} was updated successfully` + ); + } catch (error) { + serverError(error, toastId); + } + }); }; return ( <> @@ -483,7 +492,8 @@ const TreeNodeIcons = (props: { button1Handler={handleCloseRenameModal} button2Label="Update" button2Handler={handleEdit} - // disableButton2={value} + disableButton2={renameSubmitting} + button2Loading={renameSubmitting} > Are you sure you want to delete {node.id} ?{""} diff --git a/dashboard/src/components/TypeDefAuditDetailModal.tsx b/dashboard/src/components/TypeDefAuditDetailModal.tsx new file mode 100644 index 00000000000..1e780d6fb71 --- /dev/null +++ b/dashboard/src/components/TypeDefAuditDetailModal.tsx @@ -0,0 +1,108 @@ +/* + * 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. + */ + +import { Divider, Stack } from "@mui/material"; +import CustomModal from "@components/Modal"; +import { getValues } from "@components/commonComponents"; +import { StyledPaper } from "@utils/Muiutils"; +import { category } from "@utils/Enum"; +import { isArray, isEmpty } from "@utils/Utils"; + +export interface TypeDefAuditDetail { + category?: string; + name?: string; + [key: string]: unknown; +} + +interface TypeDefAuditDetailModalProps { + open: boolean; + onClose: () => void; + /** Full type-definition payload from audit `result` (same shape as audit tab click). */ + detailObject: TypeDefAuditDetail | Record | null; + maxWidth?: "xs" | "sm" | "md" | "lg" | "xl"; +} + +const buildTitle = (detailObject: TypeDefAuditDetailModalProps["detailObject"]): string => { + if (isEmpty(detailObject)) return "Type Details"; + const cat = detailObject?.category; + const name = detailObject?.name; + if (cat != null && name != null && category[String(cat)]) { + return `${category[String(cat)]} Type Details: ${String(name)}`; + } + if (name != null) return `Type Details: ${String(name)}`; + return "Type Details"; +}; + +export const TypeDefAuditDetailModal = ({ + open, + onClose, + detailObject, + maxWidth = "md", +}: TypeDefAuditDetailModalProps) => { + return ( + + + {!isEmpty(detailObject) + ? Object.entries(detailObject as Record) + .sort(([a], [b]) => a.localeCompare(b)) + .map(([keys, value]) => ( +
    + +
    + {`${keys} ${isArray(value) ? `(${(value as unknown[]).length})` : ""}`} +
    +
    + {getValues( + value, + undefined, + undefined, + undefined, + "properties" + )} +
    +
    + +
    + )) + : "No Record Found"} +
    +
    + ); +}; + +export default TypeDefAuditDetailModal; diff --git a/dashboard/src/utils/CommonViewFunction.ts b/dashboard/src/utils/CommonViewFunction.ts index 3760de5a538..d58357bfd42 100644 --- a/dashboard/src/utils/CommonViewFunction.ts +++ b/dashboard/src/utils/CommonViewFunction.ts @@ -193,13 +193,19 @@ export const attributeFilter = { let temp = obj.split("::") || obj.split("|" + spliter + "|"); let rule = {}; if (apiObj) { + const attrName = temp[0]; + const isDateAttr = + temp[3] === "date" || + attrName === "__timestamp" || + attrName === "__modificationTimestamp" || + attrName === "createTime"; rule = { - attributeName: temp[0], + attributeName: attrName, operator: mapUiOperatorToAPI(temp[1]), attributeValue: temp[2]?.trim() }; rule.attributeValue = - rule.type === "date" && formatDate && rule.attributeValue.length + isDateAttr && formatDate && rule.attributeValue?.length ? formatedDate({ date: parseInt(rule.attributeValue), zone: false @@ -231,9 +237,12 @@ export const attributeFilter = { rule.value; } } else if ( - (rule.type === "date" || rule.attributeName == "createTime") && + (rule.type === "date" || + rule.attributeName === "createTime" || + rule.id === "__timestamp" || + rule.id === "__modificationTimestamp") && formatDate && - rule.value.length + rule.value?.length ) { rule.value = formatedDate({ date: parseInt(rule.value), diff --git a/dashboard/src/utils/Enum.ts b/dashboard/src/utils/Enum.ts index 76ee0712d4d..50644400b87 100644 --- a/dashboard/src/utils/Enum.ts +++ b/dashboard/src/utils/Enum.ts @@ -319,6 +319,15 @@ export const queryBuilderUIOperatorToAPI = { export const queryBuilderApiOperatorToUI = invert(queryBuilderUIOperatorToAPI); +/** + * Converts API operator (eq, lte, gte, etc.) to display symbol (=, <=, >=, etc.) + * Used when rendering filter query chips above search results table + */ +export const getDisplayOperator = (operator: string): string => { + const mapped = (queryBuilderApiOperatorToUI as Map).get(operator); + return mapped ?? operator; +}; + export const queryBuilderDateRangeUIValueToAPI: Record = { Today: "TODAY", Yesterday: "YESTERDAY", diff --git a/dashboard/src/utils/apiErrorToastMessage.ts b/dashboard/src/utils/apiErrorToastMessage.ts new file mode 100644 index 00000000000..7afa98d0be2 --- /dev/null +++ b/dashboard/src/utils/apiErrorToastMessage.ts @@ -0,0 +1,43 @@ +/* + * 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. + */ + +/** + * Resolves user-visible toast text from an axios/fetchApi error. + * @returns null when the caller must not toast (403 is handled in fetchApi). + */ +export const getApiErrorToastMessage = (error: unknown): string | null => { + const er = error as { + response?: { status?: number; data?: unknown }; + }; + if (er?.response?.status === 403) { + return null; + } + const data = er?.response?.data; + if (data !== null && data !== undefined && typeof data === "object") { + const o = data as Record; + if (o.errorMessage != null && String(o.errorMessage).trim() !== "") { + return String(o.errorMessage); + } + if (o.msgDesc != null && String(o.msgDesc).trim() !== "") { + return String(o.msgDesc); + } + } + if (typeof data === "string" && data.trim() !== "") { + return data; + } + return "Invalid JSON response from server"; +}; diff --git a/dashboard/src/utils/auditTypeDefUtils.ts b/dashboard/src/utils/auditTypeDefUtils.ts new file mode 100644 index 00000000000..c2309757808 --- /dev/null +++ b/dashboard/src/utils/auditTypeDefUtils.ts @@ -0,0 +1,90 @@ +/* + * 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. + */ + +import { jsonParse } from "@utils/Utils"; + +/** TYPE_DEF_* audit params that use the same detail modal as the Administrator Audits tab */ +export const TYPE_DEF_DETAIL_MODAL_PARAMS = new Set([ + "ENUM", + "ENTITY", + "STRUCT", + "RELATIONSHIP", +]); + +export interface AuditRecordLike { + operation?: string; + params?: string; + result?: string; +} + +/** + * Pulls the full typedef object from an audit `result` JSON for ENUM / ENTITY / + * STRUCT / RELATIONSHIP rows (matches expanded audit row click payload). + */ +export const extractTypeDefDetailObject = ( + record: AuditRecordLike, + resolvedName: string, + resolvedGuid: string +): Record | null => { + const op = record.operation; + if ( + op !== "TYPE_DEF_CREATE" && + op !== "TYPE_DEF_UPDATE" && + op !== "TYPE_DEF_DELETE" + ) { + return null; + } + const paramKeys = (record.params ?? "") + .split(",") + .map((k) => k.trim()) + .filter(Boolean); + + try { + const resultObj = + typeof record.result === "string" ? jsonParse(record.result) : record.result; + if (!resultObj || typeof resultObj !== "object") return null; + + const keysToScan = + paramKeys.length > 0 ? paramKeys : Object.keys(resultObj as object); + + for (const key of keysToScan) { + if (!TYPE_DEF_DETAIL_MODAL_PARAMS.has(key)) continue; + const list = (resultObj as Record)[key]; + if (!Array.isArray(list) || list.length === 0) continue; + const match = list.find((item: { name?: string; guid?: string }) => { + if (!item || typeof item !== "object") return false; + if (resolvedName && item.name === resolvedName) return true; + if (resolvedGuid && item.guid === resolvedGuid) return true; + return false; + }); + if (match && typeof match === "object") { + return match as Record; + } + } + + const firstKey = paramKeys.find((k) => TYPE_DEF_DETAIL_MODAL_PARAMS.has(k)); + if (firstKey) { + const list = (resultObj as Record)[firstKey]; + if (Array.isArray(list) && list[0] && typeof list[0] === "object") { + return list[0] as Record; + } + } + } catch { + /* ignore */ + } + return null; +}; diff --git a/dashboard/src/utils/dashboardSearchUtils.ts b/dashboard/src/utils/dashboardSearchUtils.ts new file mode 100644 index 00000000000..15ebdf6994f --- /dev/null +++ b/dashboard/src/utils/dashboardSearchUtils.ts @@ -0,0 +1,189 @@ +/* + * 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. + */ + +import type { NavigateFunction } from "react-router-dom"; +import { attributeFilter } from "@utils/CommonViewFunction"; + +export type DashboardSearchType = + | "all_entities" + | "all_classifications" + | "entity_status" + | "entity_type"; + +export interface DashboardSearchParams { + type?: string; + tag?: string; + includeDE?: boolean; + entityFilters?: { + condition: string; + criterion: Array<{ attributeName: string; operator: string; attributeValue: string }>; + }; +} + +const buildSearchParams = ( + type: DashboardSearchType, + extra?: Partial +): URLSearchParams => { + const params = new URLSearchParams(); + params.set("searchType", "basic"); + + if (type === "all_classifications") { + params.set("tag", extra?.tag ?? "_ALL_CLASSIFICATION_TYPES"); + params.set("type", ""); + } else { + params.set("type", extra?.type ?? "_ALL_ENTITY_TYPES"); + } + if (extra?.includeDE) { + params.set("includeDE", "true"); + } + if (extra?.entityFilters) { + const urlStr = attributeFilter.generateUrl({ value: extra.entityFilters }); + if (urlStr) params.set("entityFilters", urlStr); + } + return params; +}; + +export const navigateToTaggedSearch = (navigate: NavigateFunction): void => { + navigateToSearch(navigate, "all_classifications"); +}; + +export const navigateToClassificationSearch = ( + navigate: NavigateFunction, + tagName: string +): void => { + navigateToSearch(navigate, "all_classifications", { tag: tagName }); +}; + +/** "View All" from Latest Entities card: basic all-types search, newest first. */ +export const navigateToLatestEntitiesSearch = (navigate: NavigateFunction): void => { + const params = buildSearchParams("all_entities"); + params.set("pageLimit", "25"); + params.set("pageOffset", "0"); + params.set("sortBy", "__timestamp"); + params.set("sortOrder", "DESCENDING"); + /* Same as dashboard card: request system create time in the basic-search body. */ + params.set("attributes", "__timestamp"); + navigate({ pathname: "/search/searchResult", search: params.toString() }); +}; + +export const navigateToEntityTypeSearch = ( + navigate: NavigateFunction, + typeName: string, + includeDeleted: boolean +): void => { + const extra: Partial = { + type: typeName, + includeDE: includeDeleted + }; + if (includeDeleted) { + extra.entityFilters = { + condition: "AND", + criterion: [{ attributeName: "__state", operator: "eq", attributeValue: "DELETED" }] + }; + } + navigateToSearch(navigate, "entity_type", extra); +}; + +/** Search all entity typedefs that belong to one service-type bucket (sidebar grouping). */ +export const navigateToServiceTypeEntitySearch = ( + navigate: NavigateFunction, + typeNames: string[], + includeDeleted: boolean +): void => { + const cleaned = [...new Set(typeNames.filter(Boolean))].sort((a, b) => a.localeCompare(b)); + if (cleaned.length === 0) { + navigateToSearch(navigate, "all_entities"); + return; + } + if (cleaned.length === 1) { + navigateToEntityTypeSearch(navigate, cleaned[0], includeDeleted); + return; + } + const criterion = cleaned.map((typeName) => ({ + attributeName: "__typeName", + operator: "eq", + attributeValue: typeName, + })); + navigateToSearch(navigate, "all_entities", { + type: "_ALL_ENTITY_TYPES", + includeDE: includeDeleted, + entityFilters: { condition: "OR", criterion }, + }); +}; + +export const navigateToSearch = ( + navigate: NavigateFunction, + type: DashboardSearchType, + extra?: Partial +): void => { + const search = buildSearchParams(type, extra).toString(); + navigate({ pathname: "/search/searchResult", search }); +}; + +/** Basic search using free-text `query` (e.g. entity typedef name). */ +export const navigateToBasicTextQuery = ( + navigate: NavigateFunction, + query: string +): void => { + const params = new URLSearchParams(); + params.set("searchType", "basic"); + params.set("query", query.trim()); + params.set("pageLimit", "25"); + params.set("pageOffset", "0"); + navigate({ pathname: "/search/searchResult", search: params.toString() }); +}; + +export const navigateToClassificationDetailPage = ( + navigate: NavigateFunction, + classificationName: string +): void => { + const sp = new URLSearchParams(); + sp.set("tag", classificationName); + navigate({ + pathname: `/tag/tagAttribute/${encodeURIComponent(classificationName)}`, + search: sp.toString() + }); +}; + +export const navigateToGlossaryTermDetailPage = ( + navigate: NavigateFunction, + args: { + termGuid: string; + termId: string; + glossaryGuid: string; + parentName: string; + } +): void => { + const sp = new URLSearchParams(); + sp.set("gid", args.glossaryGuid); + sp.set("term", `${args.termId}@${args.parentName}`); + sp.set("gtype", "term"); + sp.set("viewType", "term"); + sp.set("guid", args.termGuid); + sp.set("searchType", "basic"); + navigate({ + pathname: `/glossary/${args.termGuid}`, + search: sp.toString() + }); +}; + +export const navigateToBusinessMetadataDetailPage = ( + navigate: NavigateFunction, + bmGuid: string +): void => { + navigate({ pathname: `/administrator/businessMetadata/${bmGuid}` }); +}; diff --git a/dashboard/src/utils/filterUrlCriterionRemoval.ts b/dashboard/src/utils/filterUrlCriterionRemoval.ts new file mode 100644 index 00000000000..746fe7998f2 --- /dev/null +++ b/dashboard/src/utils/filterUrlCriterionRemoval.ts @@ -0,0 +1,81 @@ +/* + * 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. + */ + +import { attributeFilter } from "./CommonViewFunction"; + +export type RemoveCriterionResult = + | { kind: "empty" } + | { kind: "url"; url: string } + | { kind: "singleTypeName"; typeName: string }; + +type ApiFilterCriterionRow = { + attributeName: string; + operator: string; + attributeValue: string; + type?: string; +}; + +/** Narrowing shape for `attributeFilter.extractUrl(..., { apiObj: true })`. */ +export type ParsedApiFilter = { + condition: string; + criterion: ApiFilterCriterionRow[]; +}; + +/** + * Drops one criterion from a serialized filter URL (entity / tag / relationship). + * When allowTypeParamSimplification is true and exactly one __typeName eq remains, + * returns singleTypeName so the UI can use type= (matches sidebar search). + */ +export const removeCriterionFromFilterUrl = ( + filterUrl: string, + index: number, + allowTypeParamSimplification = false +): RemoveCriterionResult | null => { + if (!filterUrl || index < 0) { + return null; + } + const parsed = attributeFilter.extractUrl({ + value: filterUrl, + apiObj: true + }) as ParsedApiFilter | null; + if (!parsed?.criterion || !Array.isArray(parsed.criterion)) { + return null; + } + const crit = [...parsed.criterion]; + if (index >= crit.length) { + return null; + } + crit.splice(index, 1); + if (crit.length === 0) { + return { kind: "empty" }; + } + if ( + allowTypeParamSimplification && + crit.length === 1 && + crit[0].attributeName === "__typeName" && + String(crit[0].operator).toLowerCase() === "eq" + ) { + return { kind: "singleTypeName", typeName: String(crit[0].attributeValue) }; + } + const url = attributeFilter.generateUrl({ + value: { condition: parsed.condition, criterion: crit } + }); + if (!url) { + return { kind: "empty" }; + } + return { kind: "url", url }; +}; diff --git a/dashboard/src/utils/glossaryImportFlow.ts b/dashboard/src/utils/glossaryImportFlow.ts new file mode 100644 index 00000000000..a3f564050e0 --- /dev/null +++ b/dashboard/src/utils/glossaryImportFlow.ts @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import { + getGlossaryImport, + getGlossaryImportTmpl +} from '@api/apiMethods/glossaryApiMethod'; + +/** + * Same behavior as glossary branch of SideBarTree.downloadFile. + */ +export const downloadGlossaryImportTemplate = async (): Promise => { + const apiResp = await getGlossaryImportTmpl({}); + const text = + apiResp && typeof apiResp.data !== 'undefined' + ? String(apiResp.data) + : ''; + const blob = new Blob([text], { type: 'text/plain' }); + const url = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.setAttribute('download', 'template'); + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); +}; + +export const postGlossaryImportFormData = ( + file: File, + onUploadProgress?: (progressPercent: number) => void +) => { + const formData = new FormData(); + formData.append('file', file); + return getGlossaryImport(formData, { + onUploadProgress: (progressEvent: { loaded: number; total: number }) => { + if (!onUploadProgress || !progressEvent.total) return; + const progressValue = + (progressEvent.loaded / progressEvent.total) * 100; + onUploadProgress(progressValue); + } + }); +}; diff --git a/dashboard/src/utils/metricsUtils.ts b/dashboard/src/utils/metricsUtils.ts new file mode 100644 index 00000000000..2b6b6bcf220 --- /dev/null +++ b/dashboard/src/utils/metricsUtils.ts @@ -0,0 +1,241 @@ +/* + * 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. + */ + +export const sumEntityMetrics = (obj: Record | undefined): number => + Object.values(obj || {}).reduce((a, b) => a + (Number(b) || 0), 0); + +export const getEntityStatusTotals = (entity: Record | undefined) => ({ + active: sumEntityMetrics(entity?.entityActive as Record), + shell: sumEntityMetrics(entity?.entityShell as Record), + deleted: sumEntityMetrics(entity?.entityDeleted as Record) +}); + +export interface EntityTypeDistributionItem { + name: string; + count: number; + active: number; + deleted: number; + /** Entity typedef names rolled into this bar (e.g. service type buckets). */ + underlyingTypeNames?: string[]; +} + +export const getTaggedCount = (tag: Record | undefined): number => + sumEntityMetrics(tag?.tagEntities as Record); + +/** tagEntities values summed — counts tag–entity associations, not unique entities */ +export const getTagEntityAssociationTotal = (tag: Record | undefined): number => + getTaggedCount(tag); + +/** + * Number of classification types that have at least one active entity (each key in + * tagEntities with count > 0). Does not double-count the same entity across types. + */ +export const getClassificationTypesInUseCount = (tag: Record | undefined): number => { + const tagEntities = tag?.tagEntities as Record | undefined; + if (!tagEntities || typeof tagEntities !== "object") return 0; + return Object.values(tagEntities).filter((c) => (Number(c) || 0) > 0).length; +}; + +/** Classification names that have at least one entity assignment per tag metrics. */ +export const getClassificationNamesInUseFromTag = ( + tag: Record | undefined +): Set => { + const tagEntities = tag?.tagEntities as Record | undefined; + const names = new Set(); + if (!tagEntities || typeof tagEntities !== "object") return names; + for (const [name, count] of Object.entries(tagEntities)) { + if ((Number(count) || 0) > 0) { + names.add(name); + } + } + return names; +}; + +/** + * Defined classification names (from type defs) with no entity assignments in metrics. + */ +export const getUnusedClassificationNames = ( + definedNames: string[], + tag: Record | undefined +): string[] => { + const inUse = getClassificationNamesInUseFromTag(tag); + return definedNames.filter((n) => !inUse.has(n)).sort((a, b) => a.localeCompare(b)); +}; + +/** Parse stats from metrics general.stats (keys like "Notification:currentDay" -> { Notification: { currentDay } }) */ +export const parseMetricsStats = (stats: Record | undefined): Record> => { + const result: Record> = {}; + if (!stats || typeof stats !== "object") return result; + for (const key of Object.keys(stats)) { + const parts = key.split(":"); + const group = parts[0]; + const subKey = parts[1]; + if (!group || !subKey) continue; + if (!result[group]) result[group] = {}; + result[group][subKey] = stats[key]; + } + return result; +}; + +export interface MessageConsumptionItem { + period: string; + count: number; + creates: number; + updates: number; + deletes: number; + failed: number; + avgTime: number; +} + +const getNotificationValue = ( + notification: Record, + key: string, + field: "creates" | "updates" | "deletes" | "failed" | "avgTime" +): number => { + const keyMap: Record> = { + total: { creates: "totalCreates", updates: "totalUpdates", deletes: "totalDeletes", failed: "totalFailed", avgTime: "totalAvgTime" }, + currentHour: { creates: "currentHourEntityCreates", updates: "currentHourEntityUpdates", deletes: "currentHourEntityDeletes", failed: "currentHourFailed", avgTime: "currentHourAvgTime" }, + previousHour: { creates: "previousHourEntityCreates", updates: "previousHourEntityUpdates", deletes: "previousHourEntityDeletes", failed: "previousHourFailed", avgTime: "previousHourAvgTime" }, + currentDay: { creates: "currentDayEntityCreates", updates: "currentDayEntityUpdates", deletes: "currentDayEntityDeletes", failed: "currentDayFailed", avgTime: "currentDayAvgTime" }, + previousDay: { creates: "previousDayEntityCreates", updates: "previousDayEntityUpdates", deletes: "previousDayEntityDeletes", failed: "previousDayFailed", avgTime: "previousDayAvgTime" } + }; + const fullKey = keyMap[key]?.[field] ?? ""; + return Number(notification[fullKey] ?? 0); +}; + +export interface GetMessageConsumptionDataOptions { + /** When false, omits the Total period (e.g. topic rows where total is shown as Processed). */ + includeTotal?: boolean; +} + +/** Extract message consumption data for bar chart from Notification stats */ +export const getMessageConsumptionData = ( + notification: Record | undefined, + options?: GetMessageConsumptionDataOptions +): MessageConsumptionItem[] => { + if (!notification) return []; + const includeTotal = options?.includeTotal !== false; + const periods = [ + { key: "total", label: "Total" }, + { key: "currentHour", label: "Current Hour" }, + { key: "previousHour", label: "Previous Hour" }, + { key: "currentDay", label: "Current Day" }, + { key: "previousDay", label: "Previous Day" } + ]; + const selected = includeTotal ? periods : periods.filter((p) => p.key !== "total"); + return selected.map(({ key, label }) => ({ + period: label, + count: Number(notification[key] ?? 0), + creates: getNotificationValue(notification, key, "creates"), + updates: getNotificationValue(notification, key, "updates"), + deletes: getNotificationValue(notification, key, "deletes"), + failed: getNotificationValue(notification, key, "failed"), + avgTime: getNotificationValue(notification, key, "avgTime") + })); +}; + +/** + * Topic partition maps sometimes repeat `Notification:*` keys from the wire format. + * Strip the prefix so getMessageConsumptionData finds `currentHour`, `totalCreates`, etc. + */ +export const normalizeTopicMetricsRecord = ( + topicDetail: Record | undefined +): Record => { + if (!topicDetail || typeof topicDetail !== "object") return {}; + const out: Record = { ...topicDetail }; + for (const key of Object.keys(topicDetail)) { + if (!key.startsWith("Notification:")) continue; + const shortKey = key.slice("Notification:".length); + if (shortKey && out[shortKey] === undefined) { + out[shortKey] = topicDetail[key]; + } + } + return out; +}; + +/** + * True when the payload includes at least one period bucket count (hour/day series). + * `total` alone is not enough — legacy rows often only mirror processedMessageCount. + */ +export const topicRowHasPeriodMetrics = (topicDetail: Record | undefined): boolean => { + const n = normalizeTopicMetricsRecord(topicDetail); + return ( + n.currentHour !== undefined || + n.previousHour !== undefined || + n.currentDay !== undefined || + n.previousDay !== undefined + ); +}; + +const omitTopicDetailsFromNotification = ( + notification: Record | undefined +): Record => { + if (!notification || typeof notification !== "object") return {}; + const { topicDetails: _omit, ...rest } = notification; + return rest; +}; + +/** + * One entry from `Notification.topicDetails` for getMessageConsumptionData. + * When the server omits per-period fields on partitions (legacy payload), merge in + * aggregate `Notification` (excluding `topicDetails`) so the chart matches /admin/metrics. + */ +export const buildTopicNotificationRecord = ( + topicDetail: Record | undefined, + options?: { + aggregateNotification?: Record | undefined; + /** When true, fill period keys from aggregate if the topic row lacks them. */ + useAggregateFallback?: boolean; + } +): Record | undefined => { + if (!topicDetail || typeof topicDetail !== "object") { + if (options?.useAggregateFallback && options?.aggregateNotification) { + return omitTopicDetailsFromNotification(options.aggregateNotification); + } + return undefined; + } + const normalized = normalizeTopicMetricsRecord(topicDetail); + if (!options?.useAggregateFallback || !options?.aggregateNotification) { + return normalized; + } + const base = omitTopicDetailsFromNotification(options.aggregateNotification); + return { ...base, ...normalized }; +}; + +/** Chart periods without Total (Processed column shows the total). */ +export const getMessageConsumptionDataExcludingTotal = ( + notification: Record | undefined +): MessageConsumptionItem[] => + getMessageConsumptionData(notification, { includeTotal: false }); + +export interface ClassificationDistributionItem { + name: string; + count: number; +} + +/** Top classifications by entity count from tag.tagEntities */ +export const getClassificationDistribution = ( + tag: Record | undefined, + topN = 5 +): ClassificationDistributionItem[] => { + const tagEntities = tag?.tagEntities as Record | undefined; + if (!tagEntities) return []; + return Object.entries(tagEntities) + .map(([name, count]) => ({ name, count: Number(count) || 0 })) + .sort((a, b) => b.count - a.count) + .slice(0, topN); +}; diff --git a/dashboard/src/utils/scopedQuickSearchUtils.ts b/dashboard/src/utils/scopedQuickSearchUtils.ts new file mode 100644 index 00000000000..81a97c44ecb --- /dev/null +++ b/dashboard/src/utils/scopedQuickSearchUtils.ts @@ -0,0 +1,466 @@ +/* + * 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. + */ + +import type { TreeNode } from "@models/treeStructureType"; +import type { + ChildrenInterface, + ServiceTypeInterface, + TypeHeaderInterface +} from "@models/entityTreeType"; +import { addOnEntities } from "./Enum"; +import { customSortBy, customSortByObjectKeys, isEmpty } from "./Utils"; + +export type QuickSearchScope = + | "default" + | "entity" + | "classification" + | "glossary" + | "businessMetadata"; + +export type ScopedOptionKind = + | "entity-service" + | "entity-type" + | "classification" + | "glossary-term" + | "business-metadata"; + +export interface ScopedQuickSearchOption { + id: string; + title: string; + group: string; + kind: ScopedOptionKind; + entityTypeName?: string; + serviceUnderlyingTypeNames?: string[]; + classificationName?: string; + termGuid?: string; + glossaryGuid?: string; + termId?: string; + termParent?: string; + bmGuid?: string; +} + +interface MetricsEntitySnapshot { + entityActive?: Record; + entityDeleted?: Record; +} + +interface GlossaryTermCategoryRow { + parentCategoryGuid?: string; + categoryGuid?: string; + displayText?: string; + termGuid?: string; +} + +interface GlossaryApiRow { + name: string; + guid: string; + categories?: GlossaryTermCategoryRow[]; + terms?: GlossaryTermCategoryRow[]; +} + +const DEFAULT_SERVICE = "other_types"; + +const generateServiceTypeArr = ( + entityCountArr: ServiceTypeInterface[], + serviceType: string, + children: ChildrenInterface, + entityCount: number +) => { + const existing = entityCountArr.find( + (obj): obj is ServiceTypeInterface => + typeof obj === "object" && obj !== null && serviceType in obj + ); + if (existing) { + const bucket = (existing as Record)[serviceType]; + if (bucket) { + bucket.children.push(children); + bucket.totalCount += entityCount; + } + } else { + entityCountArr.push({ + [serviceType]: { + children: [children], + name: serviceType, + totalCount: entityCount + } + } as ServiceTypeInterface); + } +}; + +const pushRootEntityToTree = ( + entities: ServiceTypeInterface[], + allEntityCategory: string | undefined +) => { + const rootEntityChildren: ChildrenInterface = { + gType: "Entity", + guid: addOnEntities[0], + id: addOnEntities[0], + name: addOnEntities[0], + type: allEntityCategory, + text: addOnEntities[0] + }; + const hasOther = entities.some((obj) => obj["other_types"] !== undefined); + if (hasOther) { + const idx = entities.findIndex((obj) => "other_types" in obj); + (entities[idx] as ServiceTypeInterface)["other_types"].children.push( + rootEntityChildren + ); + } else { + entities.push({ + other_types: { + name: "other_types", + children: [rootEntityChildren], + totalCount: 0 + } + } as ServiceTypeInterface); + } + return entities; +}; + +/** + * Mirrors {@link EntitiesTree} group view (service type → entity typedefs). + */ +export const buildEntitiesTreeForQuickSearch = ( + typeHeaderData: TypeHeaderInterface[] | null | undefined, + metricsEntity: MetricsEntitySnapshot | null | undefined, + allEntityCategory: string | undefined +): TreeNode[] => { + if (!Array.isArray(typeHeaderData) || !typeHeaderData.length || !metricsEntity) { + return []; + } + const active = metricsEntity.entityActive || {}; + const deleted = metricsEntity.entityDeleted || {}; + const newArr: ServiceTypeInterface[] = []; + + typeHeaderData.forEach((entity) => { + let { serviceType = DEFAULT_SERVICE, category, name, guid } = entity; + if (category !== "ENTITY") return; + const entityCount = + Number(active[name] ?? 0) + Number(deleted[name] ?? 0); + const modelName = entityCount ? `${name} (${entityCount})` : name; + const children: ChildrenInterface = { + text: modelName, + name, + type: category, + gType: "Entity", + guid, + id: guid + }; + generateServiceTypeArr(newArr, serviceType, children, entityCount); + }); + + pushRootEntityToTree(newArr, allEntityCategory); + + const child = (childs: ChildrenInterface[]) => { + if (!childs?.length) return []; + return customSortBy( + childs.map((obj) => ({ + id: obj.name as string, + label: obj.text as string, + types: "child" + })), + ["label"] + ); + }; + + const sorted = customSortByObjectKeys(newArr); + return sorted.map((entity: ServiceTypeInterface) => { + const key = Object.keys(entity)[0]; + const entityData = entity[key]; + return { + id: entityData.name, + label: + entityData.totalCount === 0 + ? entityData.name + : `${entityData.name} (${entityData.totalCount})`, + children: child(entityData.children), + types: "parent" + }; + }); +}; + +const filterTreeNodes = (treeData: TreeNode[], searchTerm: string): TreeNode[] => { + const q = searchTerm.trim().toLowerCase(); + if (!q) return treeData; + return treeData + .filter( + (node) => + node.label?.toLowerCase().includes(q) || + node.children?.some((child) => child.label?.toLowerCase().includes(q)) + ) + .map((node) => { + const parentMatches = node.label?.toLowerCase().includes(q) ?? false; + const kids = node.children?.length + ? parentMatches + ? node.children + : node.children.filter((c) => c.label?.toLowerCase().includes(q)) + : undefined; + return { ...node, children: kids }; + }); +}; + +export const entityTreeToScopedOptions = ( + tree: TreeNode[], + searchTerm: string +): ScopedQuickSearchOption[] => { + const filtered = filterTreeNodes(tree, searchTerm); + const out: ScopedQuickSearchOption[] = []; + for (const parent of filtered) { + const underlying = + parent.children?.map((c) => c.id).filter(Boolean) ?? []; + out.push({ + id: `svc:${parent.id}`, + title: parent.label, + group: "Entity", + kind: "entity-service", + serviceUnderlyingTypeNames: underlying + }); + for (const child of parent.children ?? []) { + out.push({ + id: `type:${child.id}`, + title: child.label, + group: "Entity", + kind: "entity-type", + entityTypeName: child.id + }); + } + } + return out; +}; + +interface ClassificationDefRow { + name: string; + subTypes: string[]; + guid: string; + superTypes: string[]; +} + +/** Depth-first classification list (same traversal as sidebar tree). */ +export const buildClassificationScopedOptions = ( + classificationData: { classificationDefs: ClassificationDefRow[] } | null, + tagEntities: Record | undefined, + searchTerm: string +): ScopedQuickSearchOption[] => { + if (!classificationData?.classificationDefs?.length) return []; + const defs = classificationData.classificationDefs; + const byName = new Map(defs.map((d) => [d.name, d])); + const q = searchTerm.trim().toLowerCase(); + const out: ScopedQuickSearchOption[] = []; + const seen = new Set(); + + const visit = (typeName: string) => { + if (seen.has(typeName)) return; + seen.add(typeName); + const def = byName.get(typeName); + if (!def) return; + const count = tagEntities?.[typeName]; + const label = + count !== undefined ? `${typeName} (${count})` : typeName; + if (!q || label.toLowerCase().includes(q) || typeName.toLowerCase().includes(q)) { + out.push({ + id: `cls:${def.guid}:${typeName}`, + title: label, + group: "Classification", + kind: "classification", + classificationName: typeName + }); + } + (def.subTypes ?? []).forEach((st) => visit(st)); + }; + + defs + .filter((d) => isEmpty(d.superTypes)) + .forEach((d) => visit(d.name)); + + return customSortBy(out, ["title"]); +}; + +/** Build glossary tree for “terms” mode (see {@link GlossaryTree} glossaryType true). */ +export const buildGlossaryTermsTreeForQuickSearch = ( + glossaryData: GlossaryApiRow[] | null | undefined +): TreeNode[] => { + if (!glossaryData?.length) return []; + const glossaryType = true; + + const toServiceRows: Record[] = glossaryData.map((glossary) => { + const categoryRelation = + glossary.categories?.filter((o) => o.parentCategoryGuid !== undefined) ?? + []; + + const getChildren = (glossaries: { + children: NonNullable; + parent: string; + }) => { + if (isEmpty(glossaries.children)) return []; + return glossaries.children + .map((glossariesType) => { + const getChild = () => + categoryRelation + .map((obj) => { + if (obj.parentCategoryGuid === glossariesType.categoryGuid) { + return { + name: obj.displayText, + id: obj.displayText, + children: [] as ChildrenInterface[], + types: "child", + parent: glossaries.parent, + cGuid: glossaryType ? obj.termGuid : obj.categoryGuid, + guid: glossary.guid + }; + } + return undefined; + }) + .filter(Boolean) as ChildrenInterface[]; + if (glossariesType.parentCategoryGuid === undefined) { + return { + name: glossariesType.displayText, + id: glossariesType.displayText, + children: getChild(), + types: "child", + parent: glossaries.parent, + cGuid: glossaryType + ? glossariesType.termGuid + : glossariesType.categoryGuid, + guid: glossary.guid + } as ChildrenInterface; + } + return undefined; + }) + .filter(Boolean) as ChildrenInterface[]; + }; + + const children = getChildren({ + children: glossary?.terms ?? [], + parent: glossary.name + }); + + return { + [glossary.name]: { + name: glossary.name, + children: children || [], + id: glossary.guid, + types: "parent", + parent: glossary.name, + guid: glossary.guid + } + }; + }); + + const child = (childs: ChildrenInterface[]): TreeNode[] => { + if (!childs?.length) return []; + return customSortBy( + childs.map((obj) => ({ + id: obj?.name as string, + label: obj?.name as string, + children: + obj?.children !== undefined + ? child(obj.children.filter(Boolean) as ChildrenInterface[]) + : [], + types: obj?.types, + parent: obj?.parent, + guid: obj?.guid, + cGuid: obj?.cGuid + })), + ["label"] + ); + }; + + const sorted = customSortByObjectKeys(toServiceRows as ServiceTypeInterface[]); + return sorted.map((entity: Record) => { + const g = entity[Object.keys(entity)[0]]; + return { + id: g.name, + label: g.name, + children: child((g.children ?? []) as ChildrenInterface[]), + types: g.types, + parent: g.parent, + guid: g.guid + }; + }); +}; + +const collectGlossaryTermOptions = ( + nodes: TreeNode[], + glossaryLabel: string, + out: ScopedQuickSearchOption[] +) => { + for (const n of nodes) { + if (n.cGuid && n.types === "child" && n.id) { + out.push({ + id: `term:${n.cGuid}`, + title: `${n.label} (${glossaryLabel})`, + group: "Glossary / Terms", + kind: "glossary-term", + termGuid: n.cGuid as string, + glossaryGuid: (n.guid as string) ?? "", + termId: n.id, + termParent: (n.parent as string) ?? glossaryLabel + }); + } + if (n.children?.length) { + collectGlossaryTermOptions(n.children, glossaryLabel, out); + } + } +}; + +export const glossaryTreeToScopedOptions = ( + tree: TreeNode[], + searchTerm: string +): ScopedQuickSearchOption[] => { + const filtered = filterTreeNodes(tree, searchTerm); + const out: ScopedQuickSearchOption[] = []; + for (const parent of filtered) { + collectGlossaryTermOptions(parent.children ?? [], parent.label, out); + } + return customSortBy(out, ["title"]); +}; + +export const buildBusinessMetadataScopedOptions = ( + businessMetadataDefs: Array<{ name: string; guid: string }> | undefined, + searchTerm: string +): ScopedQuickSearchOption[] => { + if (!businessMetadataDefs?.length) return []; + const q = searchTerm.trim().toLowerCase(); + return customSortBy( + businessMetadataDefs + .filter((d) => !q || d.name.toLowerCase().includes(q)) + .map((d) => ({ + id: `bm:${d.guid}`, + title: d.name, + group: "Business Metadata", + kind: "business-metadata" as const, + bmGuid: d.guid + })), + ["title"] + ); +}; diff --git a/dashboard/src/utils/typeCatalogUtils.ts b/dashboard/src/utils/typeCatalogUtils.ts new file mode 100644 index 00000000000..078a36c797b --- /dev/null +++ b/dashboard/src/utils/typeCatalogUtils.ts @@ -0,0 +1,159 @@ +/* + * 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. + */ + +import type { EntityTypeDistributionItem } from "./metricsUtils"; + +/** Minimal typedef row from `/api/atlas/types/typedefs/headers` (see EntitiesTree). */ +export interface TypeHeaderCatalogRow { + name: string; + category: string; + serviceType?: string; + guid?: string; +} + +export interface DashboardTypeCatalog { + classificationNames: string[]; + /** Glossary-related entity typedef names (Atlas glossary model). */ + glossaryTermRelatedTypeNames: string[]; + businessMetadataNames: string[]; + /** All ENTITY typedef names (sorted). */ + entityTypeNames: string[]; +} + +const DEFAULT_SERVICE_TYPE = "other_types"; + +const countForEntityType = ( + entity: Record | undefined, + typeName: string +): { active: number; deleted: number } => { + const active = (entity?.entityActive as Record) || {}; + const deleted = (entity?.entityDeleted as Record) || {}; + return { + active: Number(active[typeName] ?? 0) || 0, + deleted: Number(deleted[typeName] ?? 0) || 0, + }; +}; + +/** + * Service-type buckets aligned with the Entities sidebar (`serviceType` on each ENTITY typedef). + * Falls back to `{typeName}_` prefix grouping when headers are missing (e.g. hive_table → hive). + */ +export const getServiceTypeDistribution = ( + entity: Record | undefined, + typeHeaders: TypeHeaderCatalogRow[] | null | undefined, + topN = 5 +): EntityTypeDistributionItem[] => { + const active = (entity?.entityActive as Record) || {}; + const deleted = (entity?.entityDeleted as Record) || {}; + const map = new Map< + string, + { active: number; deleted: number; typeNames: Set } + >(); + + const add = (serviceKey: string, typeName: string) => { + const { active: a, deleted: d } = countForEntityType(entity, typeName); + const cur = map.get(serviceKey) ?? { + active: 0, + deleted: 0, + typeNames: new Set(), + }; + cur.active += a; + cur.deleted += d; + cur.typeNames.add(typeName); + map.set(serviceKey, cur); + }; + + if (Array.isArray(typeHeaders) && typeHeaders.length > 0) { + for (const row of typeHeaders) { + if (row.category !== "ENTITY") continue; + const st = (row.serviceType?.trim() || DEFAULT_SERVICE_TYPE) as string; + add(st, row.name); + } + } else { + const allTypes = new Set([...Object.keys(active), ...Object.keys(deleted)]); + allTypes.forEach((typeName) => { + const i = typeName.indexOf("_"); + const serviceKey = i === -1 ? typeName : typeName.slice(0, i); + add(serviceKey, typeName); + }); + } + + const rows: EntityTypeDistributionItem[] = [...map.entries()].map( + ([name, { active: a, deleted: d, typeNames }]) => ({ + name, + active: a, + deleted: d, + count: a + d, + underlyingTypeNames: [...typeNames].sort(), + }) + ); + + rows.sort((x, y) => y.count - x.count || x.name.localeCompare(y.name)); + + const top = rows.slice(0, topN); + if (top.length === topN) return top; + + const used = new Set(top.map((r) => r.name)); + const pad = rows + .filter((r) => !used.has(r.name)) + .sort((a, b) => a.name.localeCompare(b.name)); + while (top.length < topN && pad.length > 0) { + const next = pad.shift(); + if (next) top.push(next); + } + return top; +}; + +/** Lists derived from type headers for search / future features. */ +export const buildDashboardTypeCatalog = ( + typeHeaders: TypeHeaderCatalogRow[] | null | undefined +): DashboardTypeCatalog => { + const empty: DashboardTypeCatalog = { + classificationNames: [], + glossaryTermRelatedTypeNames: [], + businessMetadataNames: [], + entityTypeNames: [], + }; + if (!Array.isArray(typeHeaders) || typeHeaders.length === 0) return empty; + + const classificationNames: string[] = []; + const businessMetadataNames: string[] = []; + const entityTypeNames: string[] = []; + const glossaryTermRelatedTypeNames: string[] = []; + + for (const row of typeHeaders) { + const { name, category } = row; + if (!name) continue; + if (category === "CLASSIFICATION") classificationNames.push(name); + else if (category === "BUSINESS_METADATA") businessMetadataNames.push(name); + else if (category === "ENTITY") { + entityTypeNames.push(name); + if (name.toLowerCase().includes("glossary")) { + glossaryTermRelatedTypeNames.push(name); + } + } + } + + const sortUnique = (arr: string[]) => [...new Set(arr)].sort((a, b) => a.localeCompare(b)); + + return { + classificationNames: sortUnique(classificationNames), + businessMetadataNames: sortUnique(businessMetadataNames), + entityTypeNames: sortUnique(entityTypeNames), + glossaryTermRelatedTypeNames: sortUnique(glossaryTermRelatedTypeNames), + }; +}; diff --git a/dashboard/src/views/Administrator/AdministratorLayout.tsx b/dashboard/src/views/Administrator/AdministratorLayout.tsx index 302da43132d..7e1e2abc8a7 100644 --- a/dashboard/src/views/Administrator/AdministratorLayout.tsx +++ b/dashboard/src/views/Administrator/AdministratorLayout.tsx @@ -19,7 +19,7 @@ import { LinkTab } from "@components/muiComponents"; import { Stack, Tabs } from "@mui/material"; import { Item, samePageLinkNavigation } from "@utils/Muiutils"; import { isEmpty } from "@utils/Utils"; -import { useState } from "react"; +import { useState, useEffect } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import BusinessMetadataTab from "./BusinessMetadataTab"; import Enumerations from "./Enumerations"; @@ -44,6 +44,26 @@ const AdministratorLayout = () => { !isEmpty(activeTab) ? allTabs.findIndex((val) => val === activeTab) : 0 ); + useEffect(() => { + const tabIndex = !isEmpty(activeTab) + ? allTabs.findIndex((val) => val === activeTab) + : 0; + const resolvedIndex = tabIndex >= 0 ? tabIndex : 0; + setValue(resolvedIndex); + + if (activeTab && activeTab !== "businessMetadata") { + setForm(false); + } + const createParam = searchParams.get("create"); + if (createParam === "true" && activeTab === "businessMetadata") { + setForm(true); + setBMAttribute({}); + const newParams = new URLSearchParams(location.search); + newParams.delete("create"); + navigate({ pathname: "/administrator", search: newParams.toString() }, { replace: true }); + } + }, [activeTab, location.search, navigate]); + const handleChange = (event: React.SyntheticEvent, newValue: number) => { if ( event.type !== "click" || diff --git a/dashboard/src/views/Administrator/Audits/AuditResults.tsx b/dashboard/src/views/Administrator/Audits/AuditResults.tsx index 9deef05255e..a287456f78d 100644 --- a/dashboard/src/views/Administrator/Audits/AuditResults.tsx +++ b/dashboard/src/views/Administrator/Audits/AuditResults.tsx @@ -15,22 +15,13 @@ * limitations under the License. */ -import { - Divider, - Grid, - Link, - List, - ListItem, - ListItemText, - Stack, - Typography, -} from "@mui/material"; +import { Grid, Link, List, ListItem, ListItemText, Typography } from "@mui/material"; import { auditAction, category } from "@utils/Enum"; -import { isArray, isEmpty, jsonParse } from "@utils/Utils"; +import { isEmpty, jsonParse } from "@utils/Utils"; import CustomModal from "@components/Modal"; +import TypeDefAuditDetailModal from "@components/TypeDefAuditDetailModal"; import { useState } from "react"; -import { getValues } from "@components/commonComponents"; -import { Item, StyledPaper } from "@utils/Muiutils"; +import { Item } from "@utils/Muiutils"; import AuditsTab from "@views/DetailPage/EntityDetailTabs/AuditsTab"; import ImportExportAudits from "./ImportExportAudits"; @@ -196,65 +187,12 @@ const AuditResults = ({ componentProps, row }: any) => { )} - - - {" "} - {!isEmpty(currentResultObj) - ? Object.entries(currentResultObj) - .sort() - .map(([keys, value]: [string, any]) => { - return ( - <> - -
    - {`${keys} ${ - isArray(value) ? `(${value.length})` : "" - }`} -
    -
    - {getValues( - value, - undefined, - undefined, - undefined, - "properties" - )} -
    -
    - - - ); - }) - : "No Record Found"} -
    -
    + detailObject={currentResultObj} + maxWidth="sm" + /> {(operation == "PURGE" || operation == "AUTO_PURGE") && ( { button2Label="Add" button2Handler={handleSubmit(onSubmit)} disableButton2={isSubmitting} + button2Loading={isSubmitting} >
    {/* */} diff --git a/dashboard/src/views/Classification/ClassificationForm.tsx b/dashboard/src/views/Classification/ClassificationForm.tsx index 170f9f16c6e..943cabdb68e 100644 --- a/dashboard/src/views/Classification/ClassificationForm.tsx +++ b/dashboard/src/views/Classification/ClassificationForm.tsx @@ -48,6 +48,7 @@ import { paramsType } from "@models/detailPageType"; import TagAtrributes from "./TagAttributes"; import { fetchClassificationData } from "@redux/slice/typeDefSlices/typedefClassificationSlice"; import { AntSwitch } from "@utils/Muiutils"; +import { refreshDashboardHomeData } from "@utils/refreshDashboardHome"; const ClassificationForm = ({ open, @@ -202,7 +203,8 @@ const ClassificationForm = ({ isAdd ? "created" : "updated" } successfully` ); - fetchInitialData(); + await fetchInitialData(); + refreshDashboardHomeData(dispatchApi); } catch (error) { console.error( `Error while ${isAdd ? "creating" : "updating"} classification`, @@ -223,6 +225,7 @@ const ClassificationForm = ({ button1Handler={onClose} button2Label={isAdd ? "Create" : "Save"} disableButton2={isSubmitting} + button2Loading={isSubmitting} isDirty={isDirty} maxWidth="sm" button2Handler={handleSubmit(onSubmit)} diff --git a/dashboard/src/views/Classification/DeleteTag.tsx b/dashboard/src/views/Classification/DeleteTag.tsx index 71b4448f6a7..4bc2d7a1995 100644 --- a/dashboard/src/views/Classification/DeleteTag.tsx +++ b/dashboard/src/views/Classification/DeleteTag.tsx @@ -77,6 +77,7 @@ const DeleteTag = (props: { maxWidth="sm" button2Handler={handleRemove} disableButton2={loader} + button2Loading={loader} > Are you sure you want to delete classification diff --git a/dashboard/src/views/DashBoard.tsx b/dashboard/src/views/DashBoard.tsx index 9b8dde43094..c0b5a201e80 100644 --- a/dashboard/src/views/DashBoard.tsx +++ b/dashboard/src/views/DashBoard.tsx @@ -15,65 +15,40 @@ * limitations under the License. */ +import { Stack } from "@mui/material"; import QuickSearch from "@components/GlobalSearch/QuickSearch"; -import { CustomButton } from "@components/muiComponents"; +import DashboardOverview from "./DashboardOverview/DashboardOverview"; import { useAppSelector } from "@hooks/reducerHook"; -import { Stack } from "@mui/material"; -import { useState } from "react"; -import EntityForm from "./Entity/EntityForm"; -import AddIcon from "@mui/icons-material/Add"; const DashBoard = () => { - const { sessionObj = "" }: any = useAppSelector( - (state: any) => state.session - ); - const [entityModal, setEntityModal] = useState(false); - const { data } = sessionObj || {}; - const key = "atlas.entity.create.allowed"; - const entityCreate = data?.[key] || ""; + const dashboardRefreshVersion = useAppSelector((state) => state.dashboardRefresh.version); - const handleOpenEntityModal = () => { - setEntityModal(true); - }; - const handleCloseEntityModal = () => { - setEntityModal(false); - }; - return ( - - - {entityCreate && ( - handleOpenEntityModal()} - startIcon={} - > - Create Entity - - )} - - - - - {entityModal && ( - - )} - - ); + return ( + + + + + + + + + ); }; export default DashBoard; diff --git a/dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx b/dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx new file mode 100644 index 00000000000..21fc1858865 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/ClassificationCoverage.tsx @@ -0,0 +1,394 @@ +/* + * 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. + */ + +import { memo, useCallback, useEffect, useMemo, useState } from "react"; +import { + Paper, + Stack, + Typography, + Box, + List, + ListItem, + Link, + TextField, + InputAdornment, +} from "@mui/material"; +import SearchIcon from "@mui/icons-material/Search"; +import { Link as RouterLink, useNavigate } from "react-router-dom"; +import CustomModal from "@components/Modal"; +import { numberFormatWithComma } from "@utils/Helper"; +import { + getClassificationTypesInUseCount, + getUnusedClassificationNames, +} from "@utils/metricsUtils"; +import { navigateToTaggedSearch } from "@utils/dashboardSearchUtils"; +import { useAppDispatch, useAppSelector } from "@hooks/reducerHook"; +import { fetchClassificationData } from "@redux/slice/typeDefSlices/typedefClassificationSlice"; + +interface ClassificationCoverageProps { + /** Defined classification types in the type system (from general.tagCount) */ + classificationTypeDefinitions: number; + tag: Record | undefined; + isLoading?: boolean; +} + +const ClassificationCoverage = memo( + ({ + classificationTypeDefinitions, + tag, + isLoading, + }: ClassificationCoverageProps) => { + const navigate = useNavigate(); + const dispatch = useAppDispatch(); + const { classificationData, loadingClassification } = useAppSelector( + (state: { classification?: { classificationData?: { classificationDefs?: { name: string }[] } | null; loadingClassification?: boolean } }) => + state.classification ?? {} + ); + + useEffect(() => { + if (!classificationData && !loadingClassification) { + void dispatch(fetchClassificationData()); + } + }, [classificationData, loadingClassification, dispatch]); + + const definedNames = useMemo(() => { + const defs = + classificationData?.classificationDefs as { name?: string }[] | undefined; + if (!Array.isArray(defs)) return []; + return defs.map((d) => d.name).filter((n): n is string => Boolean(n)); + }, [classificationData]); + + const typesInUse = useMemo( + () => getClassificationTypesInUseCount(tag), + [tag] + ); + const unusedNames = useMemo( + () => getUnusedClassificationNames(definedNames, tag), + [definedNames, tag] + ); + const unusedCount = unusedNames.length; + + const typeUsageProgress = + classificationTypeDefinitions > 0 + ? (typesInUse / classificationTypeDefinitions) * 100 + : 0; + const usagePercentRounded = Math.min( + 100, + Math.round(Number.isFinite(typeUsageProgress) ? typeUsageProgress : 0) + ); + + const [unusedModalOpen, setUnusedModalOpen] = useState(false); + const [unusedListSearchQuery, setUnusedListSearchQuery] = useState(""); + + const handleClassificationsClick = useCallback(() => { + navigateToTaggedSearch(navigate); + }, [navigate]); + + const handleOpenUnusedModal = useCallback(() => { + if (unusedCount > 0 && definedNames.length > 0) { + setUnusedListSearchQuery(""); + setUnusedModalOpen(true); + } + }, [unusedCount, definedNames.length]); + + const handleCloseUnusedModal = useCallback(() => { + setUnusedListSearchQuery(""); + setUnusedModalOpen(false); + }, []); + + const handleUnusedBarSegmentClick = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation(); + handleOpenUnusedModal(); + }, + [handleOpenUnusedModal] + ); + + const unusedNamesFiltered = useMemo(() => { + const q = unusedListSearchQuery.trim().toLowerCase(); + if (!q) return unusedNames; + return unusedNames.filter((name) => name.toLowerCase().includes(q)); + }, [unusedNames, unusedListSearchQuery]); + + const showUnusedListSearch = unusedNames.length > 5; + + if (isLoading) return null; + + const usedBarPct = Math.min(Math.max(typeUsageProgress, 0), 100); + const defsReady = definedNames.length > 0 || !!classificationData; + + return ( + + + + Classification Types In Use + + + + + + Classifications in use + + + {usagePercentRounded}% + + + + {usedBarPct > 0 ? ( + + ) : null} + 0 && defsReady ? "pointer" : "default", + backgroundColor: "#e9ecef", + }} + aria-label={ + unusedCount > 0 && defsReady + ? `View ${unusedCount} classification types not in use` + : "No unused classification types to show" + } + /> + + {defsReady && ( + + Not in use:{" "} + {unusedCount > 0 ? ( + + {numberFormatWithComma(unusedCount)}{" "} + {unusedCount === 1 + ? "classification type" + : "classification types"} + + ) : ( + <> + {numberFormatWithComma(unusedCount)}{" "} + {classificationTypeDefinitions > 0 + ? unusedCount === 1 + ? "classification type" + : "classification types" + : ""} + + )} + + )} + {!defsReady && loadingClassification ? ( + + Loading classification definitions… + + ) : null} + + {numberFormatWithComma(typesInUse)} of{" "} + {numberFormatWithComma(classificationTypeDefinitions)} + classification types are in use (have at least one entity). + + + + + + + These types are defined in Atlas but have no entity assignments in + the current metrics snapshot. + + {showUnusedListSearch ? ( + setUnusedListSearchQuery(e.target.value)} + inputProps={{ + "aria-label": "Filter unused classifications by name", + }} + InputProps={{ + startAdornment: ( + + + + ), + }} + /> + ) : null} + + {unusedNamesFiltered.length === 0 ? ( + + {unusedListSearchQuery.trim() + ? "No classifications match your search." + : "No unused classifications to list."} + + ) : ( + + {unusedNamesFiltered.map((name) => ( + + + {name} + + + ))} + + )} + + + + + ); + } +); + +ClassificationCoverage.displayName = "ClassificationCoverage"; + +export default ClassificationCoverage; diff --git a/dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx b/dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx new file mode 100644 index 00000000000..6da4704c780 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/ClassificationDistributionCard.tsx @@ -0,0 +1,227 @@ +/* + * 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. + */ + +import React, { memo, useCallback, useMemo } from "react"; +import { Paper, Stack, Typography, Box, Link } from "@mui/material"; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + Cell, + LabelList +} from "recharts"; +import { useNavigate } from "react-router-dom"; +import { numberFormatWithComma } from "@utils/Helper"; +import { + getClassificationDistribution, + getTagEntityAssociationTotal, +} from "@utils/metricsUtils"; +import { navigateToSearch, navigateToClassificationSearch } from "@utils/dashboardSearchUtils"; +import { + CHART_BAR_ACTIVE_BLUE, + CLASSIFICATION_DISTRIBUTION_CHART_MARGIN, +} from "./dashboardChartPalette"; + +const BAR_COLOR = CHART_BAR_ACTIVE_BLUE; + +interface ClassificationDistributionCardProps { + tag: Record | undefined; + isLoading?: boolean; +} + +const ClassificationDistributionCard = memo(({ tag, isLoading }: ClassificationDistributionCardProps) => { + const navigate = useNavigate(); + const data = getClassificationDistribution(tag, 5); + const associationTotal = useMemo(() => getTagEntityAssociationTotal(tag), [tag]); + + const handleBarClick = useCallback( + (entry: { name: string }) => { + navigateToClassificationSearch(navigate, entry.name); + }, + [navigate] + ); + + const handleViewAll = useCallback(() => { + navigateToSearch(navigate, "all_classifications"); + }, [navigate]); + + const handleLabelClick = useCallback( + (tagName: string) => { + navigateToClassificationSearch(navigate, tagName); + }, + [navigate] + ); + + const renderTooltip = useCallback((props: unknown) => { + const p = props as { active?: boolean; payload?: Array<{ payload?: { name: string; count: number } }> }; + if (!p?.active || !p?.payload?.length) return null; + const row = p.payload[0]?.payload; + if (!row) return null; + return ( + + + {row.name} + + + Entities: {numberFormatWithComma(row.count)} + + + ); + }, []); + + if (isLoading) return null; + + return ( + + + + + Classification Distribution + + + View All + + + + + Tag–entity associations (total):{" "} + {numberFormatWithComma(associationTotal)} + + + The chart shows the top 5 classifications by number of entities in use. + + {data.length === 0 ? ( + + + No classification data available + + + ) : ( + + + + + numberFormatWithComma(v)} + height={36} + label={{ + value: "Entity Count", + position: "bottom", + offset: 12, + style: { fontSize: 11, fill: "#6c757d" }, + }} + /> + ) => { + const { x = 0, y = 0, payload } = props; + const p = payload as { value?: string; name?: string } | undefined; + const value = p?.value ?? p?.name ?? (typeof payload === "string" ? payload : ""); + return ( + (value ? handleLabelClick(value) : undefined)} + style={{ cursor: value ? "pointer" : "default" }} + role={value ? "button" : undefined} + tabIndex={value ? 0 : undefined} + onKeyDown={ + value + ? (e: React.KeyboardEvent) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleLabelClick(value); + } + } + : undefined + } + > + + {value} + + + ); + }} + /> + + handleBarClick(entry)} + cursor="pointer" + > + numberFormatWithComma(v)} + style={{ + fontSize: 12, + fontWeight: 500, + fill: BAR_COLOR, + }} + /> + {data.map((_, index) => )} + + + + + )} + + ); +}); + +ClassificationDistributionCard.displayName = "ClassificationDistributionCard"; + +export default ClassificationDistributionCard; diff --git a/dashboard/src/views/DashboardOverview/DashboardOverview.tsx b/dashboard/src/views/DashboardOverview/DashboardOverview.tsx new file mode 100644 index 00000000000..c7bfbd55115 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/DashboardOverview.tsx @@ -0,0 +1,149 @@ +/* + * 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. + */ + +import { useEffect, useState, useMemo, useCallback } from "react"; +import { Grid, Stack } from "@mui/material"; +import { useAppDispatch, useAppSelector } from "@hooks/reducerHook"; +import { fetchTypeHeaderData } from "@redux/slice/typeDefSlices/typeDefHeaderSlice"; +import { getLatestEntities } from "@api/apiMethods/searchApiMethod"; +import type { TypeHeaderInterface } from "@models/entityTreeType"; +import DashboardSkeleton from "./DashboardSkeleton"; +import EntityTypeBarChartSkeleton from "./EntityTypeBarChartSkeleton"; +import LatestEntitiesSkeleton from "./LatestEntitiesSkeleton"; +import OverviewCard from "./OverviewCard"; +import EntityStatusDonut from "./EntityStatusDonut"; +import ClassificationCoverage from "./ClassificationCoverage"; +import EntityTypeBarChart from "./EntityTypeBarChart"; +import LatestEntitiesList from "./LatestEntitiesList"; +import RecentActivity from "./RecentActivity"; +import KafkaTopicSummaryCard from "./KafkaTopicSummaryCard"; +import ClassificationDistributionCard from "./ClassificationDistributionCard"; + +const DashboardOverview = () => { + const dispatch = useAppDispatch(); + const { metricsData, loading: metricsLoading } = useAppSelector((state: { metrics: { metricsData: unknown; loading: boolean } }) => state.metrics); + const typeHeaderData = useAppSelector( + (state: { typeHeader?: { typeHeaderData?: TypeHeaderInterface[] | null } }) => + state.typeHeader?.typeHeaderData ?? null + ); + const dashboardRefreshVersion = useAppSelector((state) => state.dashboardRefresh.version); + const [latestEntities, setLatestEntities] = useState([]); + const [latestLoading, setLatestLoading] = useState(true); + const [latestError, setLatestError] = useState(null); + + const metrics = metricsData as { + data?: { + general?: { entityCount?: number; tagCount?: number; stats?: Record }; + entity?: Record; + tag?: Record; + }; + } | null; + const general = metrics?.data?.general; + const entity = metrics?.data?.entity; + const tag = metrics?.data?.tag; + const stats = general?.stats; + const entityCount = general?.entityCount ?? 0; + const tagCount = general?.tagCount ?? 0; + + const isLoading = metricsLoading; + + const fetchLatestEntities = useCallback(async () => { + setLatestLoading(true); + setLatestError(null); + try { + const resp = await getLatestEntities(); + const entities = (resp as { data?: { entities?: unknown[] } })?.data?.entities ?? []; + setLatestEntities(Array.isArray(entities) ? entities : []); + } catch (err) { + setLatestError(err instanceof Error ? err.message : "Failed to load latest entities"); + setLatestEntities([]); + } finally { + setLatestLoading(false); + } + }, []); + + useEffect(() => { + fetchLatestEntities(); + }, [dashboardRefreshVersion, fetchLatestEntities]); + + useEffect(() => { + dispatch(fetchTypeHeaderData()); + }, [dispatch]); + + const latestEntitiesList = useMemo(() => { + if (!Array.isArray(latestEntities)) return []; + return latestEntities.slice(0, 7) as { guid?: string; typeName?: string; attributes?: { name?: string; qualifiedName?: string; __timestamp?: number } }[]; + }, [latestEntities]); + + return ( + + + + {isLoading ? : } + + + {isLoading ? : } + + + {isLoading ? ( + + ) : ( + + )} + + + {isLoading ? ( + + ) : ( + + )} + + + {latestLoading ? ( + + ) : ( + + )} + + + + + + {isLoading ? : } + + + {isLoading ? : } + + + + ); +}; + +export default DashboardOverview; diff --git a/dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx b/dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx new file mode 100644 index 00000000000..b37ec59d499 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/DashboardSkeleton.tsx @@ -0,0 +1,39 @@ +/* + * 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. + */ + +import { Paper, Stack } from "@mui/material"; +import SkeletonLoader from "@components/SkeletonLoader"; + +const DashboardSkeleton = () => ( + + + + + + +); + +export default DashboardSkeleton; diff --git a/dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx b/dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx new file mode 100644 index 00000000000..9eb93dc1ed5 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/EntityStatusDonut.tsx @@ -0,0 +1,173 @@ +/* + * 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. + */ + +import { memo, useCallback, useState } from "react"; +import { Paper, Stack, Typography, Box } from "@mui/material"; +import { PieChart, Pie, Cell, Tooltip, ResponsiveContainer, Sector } from "recharts"; +import { useNavigate } from "react-router-dom"; +import { numberFormatWithComma } from "@utils/Helper"; +import { getEntityStatusTotals } from "@utils/metricsUtils"; +import { navigateToSearch } from "@utils/dashboardSearchUtils"; +import { ENTITY_STATUS_DONUT_COLORS as COLORS } from "./dashboardChartPalette"; + +interface EntityStatusDonutProps { + entity: Record | undefined; + isLoading?: boolean; +} + +const EntityStatusDonut = memo(({ entity, isLoading }: EntityStatusDonutProps) => { + const [activeIndex, setActiveIndex] = useState(-1); + const navigate = useNavigate(); + const totals = getEntityStatusTotals(entity); + const total = totals.active + totals.shell + totals.deleted; + + const chartData = [ + { name: "Active", value: totals.active, color: COLORS.Active }, + { name: "Shell", value: totals.shell, color: COLORS.Shell }, + { name: "Deleted", value: totals.deleted, color: COLORS.Deleted } + ].filter((d) => d.value > 0); + + const getPercent = (val: number) => (total > 0 ? Math.round((val / total) * 100) : 0); + + const handleStatusClick = useCallback( + (status: "Active" | "Shell" | "Deleted") => { + if (status === "Active") { + navigateToSearch(navigate, "entity_status"); + } else if (status === "Deleted") { + navigateToSearch(navigate, "entity_status", { + includeDE: true, + entityFilters: { + condition: "AND", + criterion: [{ attributeName: "__state", operator: "eq", attributeValue: "DELETED" }] + } + }); + } else if (status === "Shell") { + navigateToSearch(navigate, "entity_status", { + entityFilters: { + condition: "AND", + criterion: [{ attributeName: "__isIncomplete", operator: "eq", attributeValue: "true" }] + } + }); + } + }, + [navigate] + ); + + if (isLoading) return null; + + const renderActiveShape = (props: unknown) => { + const p = props as { outerRadius?: number; innerRadius?: number; [k: string]: unknown }; + return ( + + ); + }; + + return ( + + + + Entity Status Overview + + + + + {(["Active", "Shell", "Deleted"] as const).map((status) => ( + handleStatusClick(status)} + aria-label={`View ${status} entities`} + sx={{ + display: "flex", + alignItems: "center", + gap: 1.5, + cursor: "pointer", + background: "none", + border: "none", + padding: 0, + margin: 0, + font: "inherit", + textAlign: "left", + "&:hover": { opacity: 0.85 } + }} + > + + + {status} {getPercent(totals[status.toLowerCase() as keyof typeof totals])}% + + + ))} + + + + setActiveIndex(index)} + onMouseLeave={() => setActiveIndex(-1)} + onClick={(data) => handleStatusClick(data.name as "Active" | "Shell" | "Deleted")} + > + {chartData.map((entry, index) => ( + + ))} + + numberFormatWithComma(value)} + contentStyle={{ borderRadius: 8 }} + /> + + + + + ); +}); + +EntityStatusDonut.displayName = "EntityStatusDonut"; + +export default EntityStatusDonut; diff --git a/dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx b/dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx new file mode 100644 index 00000000000..433cf228f89 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/EntityTypeBarChart.tsx @@ -0,0 +1,327 @@ +/* + * 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. + */ + +import React, { memo, useCallback, useMemo } from "react"; +import { Paper, Stack, Typography, Link, Box } from "@mui/material"; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + Cell, + LabelList, +} from "recharts"; +import { useNavigate } from "react-router-dom"; +import { numberFormatWithComma } from "@utils/Helper"; +import type { EntityTypeDistributionItem } from "@utils/metricsUtils"; +import { + getServiceTypeDistribution, + type TypeHeaderCatalogRow, +} from "@utils/typeCatalogUtils"; +import { + navigateToSearch, + navigateToServiceTypeEntitySearch, +} from "@utils/dashboardSearchUtils"; +import { + CHART_BAR_ACTIVE_BLUE, + ENTITY_STATUS_DONUT_COLORS, + HORIZONTAL_BAR_CHART_MARGIN, +} from "./dashboardChartPalette"; + +const ACTIVE_COLOR = CHART_BAR_ACTIVE_BLUE; +const DELETED_COLOR = ENTITY_STATUS_DONUT_COLORS.Deleted; + +interface EntityTypeBarChartProps { + entity: Record | undefined; + typeHeaderData?: TypeHeaderCatalogRow[] | null; + isLoading?: boolean; +} + +const payloadFromBarEvent = (item: unknown): EntityTypeDistributionItem | undefined => { + if (!item || typeof item !== "object") return undefined; + const rec = item as { payload?: EntityTypeDistributionItem }; + return rec.payload; +}; + +const EntityTypeBarChart = memo( + ({ entity, typeHeaderData, isLoading }: EntityTypeBarChartProps) => { + const navigate = useNavigate(); + const data = useMemo( + () => getServiceTypeDistribution(entity, typeHeaderData, 5), + [entity, typeHeaderData] + ); + + const navigateForRow = useCallback( + (row: EntityTypeDistributionItem, includeDeleted: boolean) => { + const targets = + row.underlyingTypeNames?.length && row.underlyingTypeNames.length > 0 + ? row.underlyingTypeNames + : [row.name]; + navigateToServiceTypeEntitySearch(navigate, targets, includeDeleted); + }, + [navigate] + ); + + const handleActiveBarClick = useCallback( + (barProps: unknown) => { + const row = payloadFromBarEvent(barProps); + if (row) navigateForRow(row, false); + }, + [navigateForRow] + ); + + const handleDeletedBarClick = useCallback( + (barProps: unknown) => { + const row = payloadFromBarEvent(barProps); + if (row) navigateForRow(row, true); + }, + [navigateForRow] + ); + + const handleViewAll = useCallback(() => { + navigateToSearch(navigate, "all_entities"); + }, [navigate]); + + const handleLabelClick = useCallback( + (serviceLabel: string) => { + const row = data.find((d) => d.name === serviceLabel); + if (row) navigateForRow(row, false); + }, + [data, navigateForRow] + ); + + const renderTooltip = useCallback((props: unknown) => { + const p = props as { + active?: boolean; + payload?: Array<{ + payload?: EntityTypeDistributionItem; + }>; + }; + if (!p?.active || !p?.payload?.length) return null; + const row = p.payload[0]?.payload; + if (!row) return null; + return ( + + + {row.name} + + + Active: {numberFormatWithComma(row.active)} + + + Deleted: {numberFormatWithComma(row.deleted)} + + + Total: {numberFormatWithComma(row.count)} + + + ); + }, []); + + if (isLoading) return null; + + return ( + + + + + Service Type Distribution + + + View All + + + + {data.length === 0 ? ( + + + No service type data available + + + ) : ( + + + + + + Active + + + + + + Deleted + + + + + + + numberFormatWithComma(v)} + height={36} + label={{ + value: "Entity Count", + position: "bottom", + offset: 12, + style: { fontSize: 11, fill: "#6c757d" }, + }} + /> + ) => { + const { x = 0, y = 0, payload } = props; + const p = payload as { value?: string; name?: string } | undefined; + const value = + p?.value ?? + p?.name ?? + (typeof payload === "string" ? payload : ""); + return ( + (value ? handleLabelClick(value) : undefined)} + style={{ cursor: value ? "pointer" : "default" }} + role={value ? "button" : undefined} + tabIndex={value ? 0 : undefined} + onKeyDown={ + value + ? (e: React.KeyboardEvent) => { + if (e.key === "Enter" || e.key === " ") { + e.preventDefault(); + handleLabelClick(value); + } + } + : undefined + } + > + + {value} + + + ); + }} + /> + + + {data.map((_, index) => ( + + ))} + + + numberFormatWithComma(v)} + style={{ + fontSize: 12, + fontWeight: 500, + fill: ACTIVE_COLOR, + }} + /> + {data.map((_, index) => ( + + ))} + + + + + )} + + ); + } +); + +EntityTypeBarChart.displayName = "EntityTypeBarChart"; + +export default EntityTypeBarChart; diff --git a/dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx b/dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx new file mode 100644 index 00000000000..3f2950b0b8a --- /dev/null +++ b/dashboard/src/views/DashboardOverview/EntityTypeBarChartSkeleton.tsx @@ -0,0 +1,57 @@ +/* + * 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. + */ + +import { Paper, Stack, Box } from "@mui/material"; +import SkeletonLoader from "@components/SkeletonLoader"; + +const EntityTypeBarChartSkeleton = () => ( + + + + + + + + + + + + + {[1, 2, 3, 4, 5].map((i) => ( + + + + + ))} + + +); + +export default EntityTypeBarChartSkeleton; diff --git a/dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx b/dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx new file mode 100644 index 00000000000..93c00f50b7a --- /dev/null +++ b/dashboard/src/views/DashboardOverview/KafkaTopicSummaryCard.tsx @@ -0,0 +1,402 @@ +/* + * 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. + */ + +import { Fragment, memo, useMemo, useState, useCallback } from "react"; +import { + Paper, + Stack, + Typography, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Box, + IconButton, + Tooltip, + Collapse, +} from "@mui/material"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import ExpandLessIcon from "@mui/icons-material/ExpandLess"; +import { numberFormatWithComma } from "@utils/Helper"; +import { formatedDate } from "@utils/Utils"; +import { + parseMetricsStats, + getMessageConsumptionData, + getMessageConsumptionDataExcludingTotal, + buildTopicNotificationRecord, + topicRowHasPeriodMetrics, + type MessageConsumptionItem, +} from "@utils/metricsUtils"; +import MessageConsumptionChart from "./MessageConsumptionChart"; +import { + CHART_BAR_ACTIVE_BLUE, + ENTITY_STATUS_DONUT_COLORS, +} from "./dashboardChartPalette"; + +const CREATES_COLOR = ENTITY_STATUS_DONUT_COLORS.Active; +const UPDATES_COLOR = CHART_BAR_ACTIVE_BLUE; +const DELETES_COLOR = ENTITY_STATUS_DONUT_COLORS.Deleted; + +interface TopicDetail { + topic: string; + processed: number; + failed: number; + lastProcessed: string | number; + /** Partition stats — same shape as aggregate Notification (per AtlasMetricsUtil). */ + topicStats: Record; +} + +interface KafkaTopicSummaryCardProps { + stats: Record | undefined; + isLoading?: boolean; +} + +const getTopicConsumptionPanelId = (topic: string): string => + `kafka-topic-msg-panel-${topic.replace(/[^a-zA-Z0-9_-]/g, "_")}`; + +const TotalProcessedTooltip = ({ + total, +}: { + total: MessageConsumptionItem | undefined; +}) => { + if (!total) { + return ( + + No breakdown available + + ); + } + return ( + + + {total.period} + + + Creates: {numberFormatWithComma(total.creates)} + + + Updates: {numberFormatWithComma(total.updates)} + + + Deletes: {numberFormatWithComma(total.deletes)} + + + Messages processed: {numberFormatWithComma(total.count)} + + + Avg time (ms): {numberFormatWithComma(total.avgTime)} + + + ); +}; + +const KafkaTopicSummaryCard = memo(({ stats, isLoading }: KafkaTopicSummaryCardProps) => { + const [sortKey, setSortKey] = useState<"topic" | "processed" | "failed">("topic"); + const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc"); + /** One expanded topic at a time to limit vertical growth. */ + const [expandedTopic, setExpandedTopic] = useState(null); + + const parsed = useMemo(() => parseMetricsStats(stats), [stats]); + const notification = parsed?.Notification as Record | undefined; + const topicDetails = notification?.topicDetails as + | Record> + | undefined; + + const rows = useMemo((): TopicDetail[] => { + if (!topicDetails || typeof topicDetails !== "object") return []; + return Object.entries(topicDetails).map(([topic, data]) => { + const lp = data?.lastMessageProcessedTime; + const lastProcessed: string | number = + lp != null && typeof lp !== "object" ? (lp as string | number) : "-"; + return { + topic, + processed: Number(data?.processedMessageCount ?? 0), + failed: Number(data?.failedMessageCount ?? 0), + lastProcessed, + topicStats: data ?? {}, + }; + }); + }, [topicDetails]); + + const sortedRows = useMemo(() => { + const list = [...rows]; + const dir = sortOrder === "asc" ? 1 : -1; + return list.sort((a, b) => { + if (sortKey === "topic") { + const av = String(a.topic).toLowerCase(); + const bv = String(b.topic).toLowerCase(); + return (av < bv ? -1 : av > bv ? 1 : 0) * dir; + } + const av = a[sortKey]; + const bv = b[sortKey]; + return ((av as number) - (bv as number)) * dir; + }); + }, [rows, sortKey, sortOrder]); + + const consumptionByTopic = useMemo(() => { + const m = new Map< + string, + { totalRow: MessageConsumptionItem | undefined; chartData: MessageConsumptionItem[] } + >(); + for (const row of rows) { + const record = buildTopicNotificationRecord(row.topicStats, { + aggregateNotification: notification, + useAggregateFallback: !topicRowHasPeriodMetrics(row.topicStats), + }); + const full = getMessageConsumptionData(record); + m.set(row.topic, { + totalRow: full.find((d) => d.period === "Total"), + chartData: getMessageConsumptionDataExcludingTotal(record), + }); + } + return m; + }, [rows, notification]); + + const handleSort = useCallback((key: "topic" | "processed" | "failed") => { + setSortKey(key); + setSortOrder((prev) => (prev === "asc" ? "desc" : "asc")); + }, []); + + const handleToggleExpand = useCallback((topic: string) => { + setExpandedTopic((prev) => (prev === topic ? null : topic)); + }, []); + + const formatLastProcessed = (val: string | number): string => { + if (val === "-" || val == null) return "-"; + if (typeof val === "number") return formatedDate({ date: val }); + return String(val); + }; + + const hasExpanded = expandedTopic !== null; + + if (isLoading) return null; + + return ( + + + + Kafka Topic Summary + + + {rows.length === 0 ? ( + + + No topic data available + + + ) : ( + + + + + handleSort("topic")} + sx={{ cursor: "pointer", fontWeight: 600 }} + aria-label="Sort by topic" + > + Topic{" "} + {sortKey === "topic" + ? sortOrder === "asc" + ? "▲" + : "▼" + : ""} + + handleSort("processed")} + sx={{ cursor: "pointer", fontWeight: 600 }} + aria-label="Sort by processed" + > + Processed{" "} + {sortKey === "processed" + ? sortOrder === "asc" + ? "▲" + : "▼" + : ""} + + handleSort("failed")} + sx={{ cursor: "pointer", fontWeight: 600 }} + aria-label="Sort by failed" + > + Failed{" "} + {sortKey === "failed" + ? sortOrder === "asc" + ? "▲" + : "▼" + : ""} + + + Last Processed + + + + + {sortedRows.map((row) => { + const isExpanded = expandedTopic === row.topic; + const panelId = getTopicConsumptionPanelId(row.topic); + const cons = consumptionByTopic.get(row.topic); + const totalForHover = cons?.totalRow; + const chartData = cons?.chartData ?? []; + return ( + + + + + { + e.stopPropagation(); + handleToggleExpand(row.topic); + }} + onKeyDown={(e) => { + if (e.key === " " || e.key === "Enter") { + e.stopPropagation(); + } + }} + > + {isExpanded ? ( + + ) : ( + + )} + + + {row.topic} + + + + + } + arrow + enterDelay={200} + placement="top" + componentsProps={{ + tooltip: { + sx: { + bgcolor: "#fff", + color: "#1a1a1a", + border: "1px solid", + borderColor: "rgba(0, 0, 0, 0.12)", + boxShadow: 2, + }, + }, + arrow: { + sx: { + color: "#fff", + }, + }, + }} + > + + {numberFormatWithComma(row.processed)} + + + + + {numberFormatWithComma(row.failed)} + + + {formatLastProcessed(row.lastProcessed)} + + + {isExpanded ? ( + + + + + + Message consumption + + + + + + + ) : null} + + ); + })} + +
    +
    + )} +
    + ); +}); + +KafkaTopicSummaryCard.displayName = "KafkaTopicSummaryCard"; + +export default KafkaTopicSummaryCard; diff --git a/dashboard/src/views/DashboardOverview/LatestEntitiesList.tsx b/dashboard/src/views/DashboardOverview/LatestEntitiesList.tsx new file mode 100644 index 00000000000..2d80a5a1fa0 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/LatestEntitiesList.tsx @@ -0,0 +1,273 @@ +/* + * 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. + */ + +import { memo, useCallback } from "react"; +import { Paper, Stack, Typography, Link, List, ListItem, Box } from "@mui/material"; +import { Link as RouterLink } from "react-router-dom"; +import moment from "moment"; +import { useNavigate } from "react-router-dom"; +import { navigateToLatestEntitiesSearch } from "@utils/dashboardSearchUtils"; +import type { LatestEntityRowModel } from "./latestEntitiesList.utils"; +import { + resolveLatestEntityDisplayName, + resolveLatestEntityGuid, + resolveLatestEntityTypeName +} from "./latestEntitiesList.utils"; + +interface EntityItem extends LatestEntityRowModel { + createTime?: number | Date | string; + attributes?: LatestEntityRowModel["attributes"] & { + __timestamp?: number | string | Record; + createTime?: number | string; + }; +} + +interface LatestEntitiesListProps { + entities: EntityItem[]; + isLoading?: boolean; + error?: string | null; +} + +const INVALID_TS_LABEL = "Created today"; + +const unwrapLongLike = (raw: unknown): unknown => { + if (raw == null || typeof raw !== "object" || Array.isArray(raw)) return raw; + const o = raw as Record; + if (typeof o.$numberLong === "string" || typeof o.$numberLong === "number") { + return o.$numberLong; + } + if (typeof o.longValue === "string" || typeof o.longValue === "number") { + return o.longValue; + } + return raw; +}; + +/** + * Milliseconds since epoch, or null only when missing / unusable. + * Rejects 0 (epoch) to avoid "56 years ago". Accepts sec or ms numbers, ISO strings. + */ +const normalizeEntityTimestampMs = (raw: unknown): number | null => { + const v = unwrapLongLike(raw); + if (v == null) return null; + if (v instanceof Date) { + const t = v.getTime(); + if (!Number.isFinite(t) || t <= 0) return null; + return moment(t).isValid() ? t : null; + } + if (typeof v === "string") { + const trimmed = v.trim(); + if (trimmed === "") return null; + const n = Number(trimmed); + if (Number.isFinite(n) && n > 0) { + const ms = n < 1e12 ? n * 1000 : n; + if (moment(ms).isValid() && ms > 0) return ms; + } + const parsed = moment(trimmed); + if (parsed.isValid()) { + const ms = parsed.valueOf(); + if (ms > 0) return ms; + } + return null; + } + if (typeof v === "number") { + if (!Number.isFinite(v) || v <= 0) return null; + const ms = v < 1e12 ? v * 1000 : v; + return moment(ms).isValid() && ms > 0 ? ms : null; + } + return null; +}; + +/** Use only `__timestamp` for relative "Created … ago" (not `createTime`, often 0 in API). */ +const getEntityTimestampRawForDisplay = (entity: EntityItem): unknown => { + const a = entity.attributes; + const top = entity as EntityItem & { __timestamp?: unknown }; + return a?.__timestamp ?? top.__timestamp; +}; + +/** Valid timestamp only: seconds / minutes / hours for last 24h, then moment relative. */ +const formatCreatedRelativeFromMs = (ms: number): string => { + const now = Date.now(); + const deltaMs = now - ms; + if (!Number.isFinite(deltaMs)) return INVALID_TS_LABEL; + if (deltaMs < 0) { + return `Created ${moment(ms).fromNow()}`; + } + const totalSec = Math.floor(deltaMs / 1000); + if (totalSec < 1) { + return "Created just now"; + } + if (totalSec < 60) { + return totalSec === 1 + ? "Created 1 second ago" + : `Created ${totalSec} seconds ago`; + } + const totalMin = Math.floor(totalSec / 60); + if (totalMin < 60) { + return totalMin === 1 + ? "Created 1 minute ago" + : `Created ${totalMin} minutes ago`; + } + const totalHr = Math.floor(totalMin / 60); + if (totalHr < 24) { + return totalHr === 1 + ? "Created 1 hour ago" + : `Created ${totalHr} hours ago`; + } + return `Created ${moment(ms).fromNow()}`; +}; + +const formatRelativeTime = (raw: unknown): string => { + const ms = normalizeEntityTimestampMs(raw); + if (ms == null) return INVALID_TS_LABEL; + return formatCreatedRelativeFromMs(ms); +}; + +const LatestEntitiesList = memo(({ entities, isLoading, error }: LatestEntitiesListProps) => { + const navigate = useNavigate(); + + const handleViewAll = useCallback(() => { + navigateToLatestEntitiesSearch(navigate); + }, [navigate]); + + if (isLoading) return null; + + return ( + + + + + Latest Entities Created + + + View All + + + + {error ? ( + + + {error} + + + ) : !entities || entities.length === 0 ? ( + + + No recent entities + + + ) : ( + + {entities.slice(0, 7).map((entity) => { + const displayName = resolveLatestEntityDisplayName(entity); + const entityGuid = resolveLatestEntityGuid(entity); + const typeName = resolveLatestEntityTypeName(entity); + const timestamp = getEntityTimestampRawForDisplay(entity); + const detailHref = entityGuid + ? `/detailPage/${entityGuid}` + : undefined; + + return ( + + + + {detailHref ? ( + + {displayName} + + ) : ( + + {displayName} + + )} + + ({typeName}) + + + + {formatRelativeTime(timestamp)} + + + + ); + })} + + )} + + ); +}); + +LatestEntitiesList.displayName = "LatestEntitiesList"; + +export default LatestEntitiesList; diff --git a/dashboard/src/views/DashboardOverview/LatestEntitiesSkeleton.tsx b/dashboard/src/views/DashboardOverview/LatestEntitiesSkeleton.tsx new file mode 100644 index 00000000000..75e4f596059 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/LatestEntitiesSkeleton.tsx @@ -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. + */ + +import { Paper, Stack, Box } from "@mui/material"; +import SkeletonLoader from "@components/SkeletonLoader"; + +const LatestEntitiesSkeleton = () => ( + + + + + + + + + {[1, 2, 3, 4, 5, 6, 7].map((i) => ( + + + + + ))} + + +); + +export default LatestEntitiesSkeleton; diff --git a/dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx b/dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx new file mode 100644 index 00000000000..f2b98f687c2 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/MessageConsumptionChart.tsx @@ -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. + */ + +import { memo, useCallback } from "react"; +import { Stack, Typography, Box } from "@mui/material"; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + Cell, + LabelList, +} from "recharts"; +import { numberFormatWithComma } from "@utils/Helper"; +import { type MessageConsumptionItem } from "@utils/metricsUtils"; +import { + CHART_BAR_ACTIVE_BLUE, + ENTITY_STATUS_DONUT_COLORS, +} from "./dashboardChartPalette"; + +const CREATES_COLOR = ENTITY_STATUS_DONUT_COLORS.Active; +const UPDATES_COLOR = CHART_BAR_ACTIVE_BLUE; +const DELETES_COLOR = ENTITY_STATUS_DONUT_COLORS.Deleted; + +interface MessageConsumptionChartProps { + /** Rows must already exclude the Total period when used from Kafka Topic Summary. */ + data: MessageConsumptionItem[]; + /** Optional accessible name for the chart region (embedded context). */ + chartAriaLabel?: string; +} + +const MessageConsumptionChart = memo( + ({ data, chartAriaLabel }: MessageConsumptionChartProps) => { + const renderTooltip = useCallback( + (props: unknown) => { + const p = props as { + active?: boolean; + label?: string | number; + payload?: Array<{ payload?: MessageConsumptionItem }>; + }; + if (!p?.active) return null; + const periodLabel = + p.label !== undefined && p.label !== null ? String(p.label) : ""; + const rowFromLabel = periodLabel + ? data.find((d) => d.period === periodLabel) + : undefined; + const row = + rowFromLabel ?? p.payload?.[0]?.payload ?? undefined; + if (!row) return null; + return ( + + + {row.period} + + + Creates: {numberFormatWithComma(row.creates)} + + + Updates: {numberFormatWithComma(row.updates)} + + + Deletes: {numberFormatWithComma(row.deletes)} + + + Messages processed: {numberFormatWithComma(row.count)} + + + Avg time (ms): {numberFormatWithComma(row.avgTime)} + + + ); + }, + [data] + ); + + if (data.length === 0) { + return ( + + + No message consumption data available + + + ); + } + + return ( + + + + + + Creates + + + + + + Updates + + + + + + Deletes + + + + + + + + numberFormatWithComma(v)} + width={48} + label={{ + value: "Count", + angle: -90, + position: "left", + offset: 6, + style: { fontSize: 11, fill: "#6c757d", textAnchor: "middle" }, + }} + /> + + + {data.map((_, index) => ( + + ))} + + + {data.map((_, index) => ( + + ))} + + + numberFormatWithComma(v)} + style={{ + fontSize: 11, + fontWeight: 600, + fill: "#374151", + }} + /> + {data.map((_, index) => ( + + ))} + + + + + ); + } +); + +MessageConsumptionChart.displayName = "MessageConsumptionChart"; + +export default MessageConsumptionChart; diff --git a/dashboard/src/views/DashboardOverview/OverviewCard.tsx b/dashboard/src/views/DashboardOverview/OverviewCard.tsx new file mode 100644 index 00000000000..41018055b11 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/OverviewCard.tsx @@ -0,0 +1,114 @@ +/* + * 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. + */ + +import { Paper, Stack, Typography, Box } from "@mui/material"; +import { numberFormatWithComma } from "@utils/Helper"; +import { useNavigate } from "react-router-dom"; +import { navigateToSearch } from "@utils/dashboardSearchUtils"; + +interface OverviewCardProps { + entityCount: number; + tagCount: number; + isLoading?: boolean; +} + +const OverviewCard = ({ entityCount, tagCount, isLoading }: OverviewCardProps) => { + const navigate = useNavigate(); + + const handleEntitiesClick = () => { + navigateToSearch(navigate, "all_entities"); + }; + + const handleClassificationsClick = () => { + navigateToSearch(navigate, "all_classifications"); + }; + + if (isLoading) return null; + + return ( + + + + Overview + + + + + + {numberFormatWithComma(entityCount)} + + + Entities + + + + + {numberFormatWithComma(tagCount)} + + + Classifications + + + + + ); +}; + +export default OverviewCard; diff --git a/dashboard/src/views/DashboardOverview/RecentActivity.tsx b/dashboard/src/views/DashboardOverview/RecentActivity.tsx new file mode 100644 index 00000000000..fdd5be1500c --- /dev/null +++ b/dashboard/src/views/DashboardOverview/RecentActivity.tsx @@ -0,0 +1,408 @@ +/* + * 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. + */ + +import { memo, useCallback, useEffect, useState } from "react"; +import { useAppSelector } from "@hooks/reducerHook"; +import { Paper, Stack, Typography, Link, Box, Chip, List, ListItem } from "@mui/material"; +import { RecentActivityListSkeleton } from "./RecentActivitySkeleton"; +import TypeDefAuditDetailModal from "@components/TypeDefAuditDetailModal"; +import { Link as RouterLink, useNavigate } from "react-router-dom"; +import { getAuditData } from "@api/apiMethods/detailpageApiMethod"; +import { category } from "@utils/Enum"; +import { extractTypeDefDetailObject } from "@utils/auditTypeDefUtils"; +import { dateFormat, isEmpty, jsonParse } from "@utils/Utils"; + +export interface AuditRecord { + guid?: string; + userName?: string; + operation?: string; + params?: string; + result?: string; + startTime?: number; + endTime?: number; +} + +const AUDIT_TABS = [ + { id: "typeCreated", label: "Created", operations: ["TYPE_DEF_CREATE"] }, + { id: "typeUpdated", label: "Updated", operations: ["TYPE_DEF_UPDATE"] }, + { id: "typeDeleted", label: "Deleted", operations: ["TYPE_DEF_DELETE"] }, + { id: "purge", label: "Purge", operations: ["PURGE", "AUTO_PURGE"] }, + { id: "import", label: "Import", operations: ["IMPORT"] }, + { id: "export", label: "Export", operations: ["EXPORT"] } +] as const; + +interface ParsedAuditResult { + typeLabel: string; + entityName: string; + entityGuid?: string; + actionPhrase: string; + user: string; + dateStr: string; +} + +const parseAuditRecord = (record: AuditRecord): ParsedAuditResult => { + const { operation, params, result, userName, endTime } = record; + const user = userName || "Unknown"; + const dateStr = endTime ? dateFormat(endTime) : ""; + let typeLabel = category[params as keyof typeof category] || params || "Type"; + let actionPhrase = ""; + let entityName = ""; + let entityGuid = ""; + + if (operation === "PURGE" || operation === "AUTO_PURGE") { + try { + const guidStr = typeof result === "string" ? result.replace("[", "").replace("]", "").split(",")[0]?.trim() : ""; + entityGuid = guidStr ?? ""; + if (entityGuid) entityName = "View entity"; + } catch { + /* ignore */ + } + actionPhrase = "operation was performed"; + return { typeLabel: operation === "AUTO_PURGE" ? "Auto purge" : "Purge", entityName, entityGuid, actionPhrase, user, dateStr }; + } + if (operation === "EXPORT") { + return { typeLabel: "Export", entityName: "", entityGuid: "", actionPhrase: "operation was performed", user, dateStr }; + } + if (operation === "IMPORT") { + return { typeLabel: "Import", entityName: "", entityGuid: "", actionPhrase: "operation was performed", user, dateStr }; + } + + if (operation === "TYPE_DEF_CREATE") { + actionPhrase = "was created"; + } else if (operation === "TYPE_DEF_UPDATE") { + actionPhrase = "was updated"; + } else if (operation === "TYPE_DEF_DELETE") { + actionPhrase = "was deleted"; + } else { + return { typeLabel: operation || "", entityName: "", entityGuid: "", actionPhrase: "", user, dateStr }; + } + + try { + const resultObj = typeof result === "string" ? jsonParse(result) : result; + if (resultObj?.name) { + entityName = resultObj.name; + entityGuid = resultObj.guid ?? ""; + } else if (resultObj && typeof resultObj === "object") { + const paramsKey = params?.split(",")[0]?.trim(); + const arr = paramsKey ? resultObj[paramsKey] : resultObj[Object.keys(resultObj)[0]]; + if (Array.isArray(arr) && arr[0]) { + entityName = arr[0].name ?? ""; + entityGuid = arr[0].guid ?? ""; + } else if (!Array.isArray(arr) && arr?.name) { + entityName = arr.name; + entityGuid = arr.guid ?? ""; + } + } + } catch { + /* ignore */ + } + + return { typeLabel, entityName, entityGuid, actionPhrase, user, dateStr }; +}; + +const getDetailUrl = ( + operation: string | undefined, + params: string, + entityName: string, + entityGuid: string +): string | null => { + if ((operation === "PURGE" || operation === "AUTO_PURGE") && entityGuid) { + return `/detailPage/${entityGuid}`; + } + if (!entityName && !entityGuid) return null; + /* Type Created/Updated/Deleted tabs - link to type details */ + const param = params?.split(",")[0]?.trim(); + if (param === "CLASSIFICATION") { + return `/tag/tagAttribute/${entityName}`; + } + if (param === "BUSINESS_METADATA" && entityGuid) { + return `/administrator/businessMetadata/${entityGuid}`; + } + if (["ENTITY", "ENUM", "RELATIONSHIP", "STRUCT"].includes(param ?? "")) { + return null; + } + return `/administrator?tabActive=typeSystem`; +}; + +const RecentActivity = memo(() => { + const dashboardRefreshVersion = useAppSelector((state) => state.dashboardRefresh.version); + const navigate = useNavigate(); + const [activeTab, setActiveTab] = useState(0); + const [tabData, setTabData] = useState>({ + typeCreated: [], + typeUpdated: [], + typeDeleted: [], + purge: [], + import: [], + export: [] + }); + const [loading, setLoading] = useState>({ + typeCreated: false, + typeUpdated: false, + typeDeleted: false, + purge: false, + import: false, + export: false + }); + + const fetchAudits = useCallback(async (tabId: string, operations: string[]) => { + setLoading((prev) => ({ ...prev, [tabId]: true })); + try { + const allResults: AuditRecord[] = []; + for (const op of operations) { + const auditFilters = { + condition: "AND" as const, + criterion: [ + { + attributeName: "operation", + operator: "eq" as const, + attributeValue: op + } + ] + }; + const resp = await getAuditData({ + auditFilters, + limit: 5, + offset: 0, + sortBy: "startTime", + sortOrder: "DESCENDING" + }); + const data = (resp as { data?: AuditRecord[] })?.data ?? []; + if (Array.isArray(data)) allResults.push(...data); + } + allResults.sort((a, b) => (b.endTime ?? 0) - (a.endTime ?? 0)); + setTabData((prev) => ({ ...prev, [tabId]: allResults.slice(0, 5) })); + } catch { + setTabData((prev) => ({ ...prev, [tabId]: [] })); + } finally { + setLoading((prev) => ({ ...prev, [tabId]: false })); + } + }, []); + + useEffect(() => { + AUDIT_TABS.forEach((tab) => { + fetchAudits(tab.id, [...tab.operations]); + }); + }, [fetchAudits, dashboardRefreshVersion]); + + const handleViewAll = useCallback(() => { + navigate("/administrator?tabActive=audit"); + }, [navigate]); + + const handleTabChange = useCallback((_: React.SyntheticEvent, newValue: number) => { + setActiveTab(newValue); + }, []); + + const currentTab = AUDIT_TABS[activeTab]; + const records = tabData[currentTab?.id] ?? []; + const isLoading = loading[currentTab?.id] ?? false; + + const [typeDetailOpen, setTypeDetailOpen] = useState(false); + const [typeDetailObject, setTypeDetailObject] = useState | null>(null); + + const handleCloseTypeDetail = useCallback(() => { + setTypeDetailOpen(false); + setTypeDetailObject(null); + }, []); + + const handleOpenTypeDetail = useCallback((obj: Record) => { + setTypeDetailObject(obj); + setTypeDetailOpen(true); + }, []); + + return ( + + + + + Recent Activity + + + View All + + + + + {AUDIT_TABS.map((tab, idx) => ( + handleTabChange(e as unknown as React.SyntheticEvent, idx)} + color={activeTab === idx ? "primary" : "default"} + variant={activeTab === idx ? "filled" : "outlined"} + sx={{ + fontSize: "0.8125rem", + height: 32, + "&.MuiChip-filled": { fontWeight: 600 } + }} + aria-pressed={activeTab === idx} + aria-label={`${tab.label} tab`} + /> + ))} + + + {isLoading ? ( + + ) : isEmpty(records) ? ( + + + No records present + + + ) : ( + + {records.map((record, idx) => { + const parsed = parseAuditRecord(record); + const { typeLabel, entityName, entityGuid, actionPhrase, user, dateStr } = parsed; + const typeDefPayload = extractTypeDefDetailObject( + record, + entityName ?? "", + entityGuid ?? "" + ); + const detailUrl = getDetailUrl( + record.operation ?? "", + record.params ?? "", + entityName ?? "", + entityGuid ?? "" + ); + + const openTypeModalIfNeeded = () => { + if (typeDefPayload) { + handleOpenTypeDetail(typeDefPayload); + } + }; + + const handleEntityNameKeyDown = ( + e: React.KeyboardEvent + ) => { + if (e.key !== "Enter" && e.key !== " ") return; + e.preventDefault(); + openTypeModalIfNeeded(); + }; + + return ( + + + {entityName ? ( + <> + {typeDefPayload ? ( + + {entityName} + + ) : detailUrl ? ( + + {entityName} + + ) : ( + entityName + )} + {" "} + {typeLabel} {actionPhrase} by{" "} + + {user} + {" "} + on{" "} + + {dateStr} + + + ) : ( + <> + {typeLabel} {actionPhrase} by{" "} + + {user} + {" "} + on{" "} + + {dateStr} + + + )} + + + ); + })} + + )} + + + + ); +}); + +RecentActivity.displayName = "RecentActivity"; + +export default RecentActivity; diff --git a/dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx b/dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx new file mode 100644 index 00000000000..8ca10811fcd --- /dev/null +++ b/dashboard/src/views/DashboardOverview/RecentActivitySkeleton.tsx @@ -0,0 +1,37 @@ +/* + * 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. + */ + +import { Stack } from "@mui/material"; +import SkeletonLoader from "@components/SkeletonLoader"; + +/** Shown inside Recent Activity while the active tab's audits are loading. */ +export const RecentActivityListSkeleton = () => ( + + {[1, 2, 3, 4, 5].map((i) => ( + + ))} + +); + +export default RecentActivityListSkeleton; diff --git a/dashboard/src/views/DashboardOverview/dashboardChartPalette.ts b/dashboard/src/views/DashboardOverview/dashboardChartPalette.ts new file mode 100644 index 00000000000..fb012a445b9 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/dashboardChartPalette.ts @@ -0,0 +1,42 @@ +/* + * 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. + */ + +/** Matches Entity Status Overview donut — single source for dashboard charts */ +export const ENTITY_STATUS_DONUT_COLORS = { + Active: "#10b981", + Shell: "#f59e0b", + Deleted: "#ef4444", +} as const; + +/** Active primary series / bar fill (aligned with Classification Distribution bars) */ +export const CHART_BAR_ACTIVE_BLUE = "#1976d2"; + +/** Horizontal bar charts: Y-axis title + ticks; keep left tight to reduce card gutter */ +export const HORIZONTAL_BAR_CHART_MARGIN = { + top: 8, + right: 72, + left: 44, + bottom: 48, +} as const; + +/** Tighter layout: short classification names — minimize dead space left of Y ticks */ +export const CLASSIFICATION_DISTRIBUTION_CHART_MARGIN = { + top: 8, + right: 72, + left: 12, + bottom: 48, +} as const; diff --git a/dashboard/src/views/DashboardOverview/latestEntitiesList.utils.ts b/dashboard/src/views/DashboardOverview/latestEntitiesList.utils.ts new file mode 100644 index 00000000000..118be6b1532 --- /dev/null +++ b/dashboard/src/views/DashboardOverview/latestEntitiesList.utils.ts @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/** Shape of basic-search entity headers used by Latest Entities card. */ +export interface LatestEntityRowModel { + guid?: string; + name?: string; + typeName?: string; + displayText?: string; + attributes?: { + name?: string; + qualifiedName?: string; + __guid?: string; + }; +} + +/** + * Match Search name column: top-level name/displayText and attributes.name / + * qualifiedName (Atlas may return any of these). + */ +export const resolveLatestEntityDisplayName = ( + entity: LatestEntityRowModel +): string => { + const n = + entity.name ?? + entity.attributes?.name ?? + entity.attributes?.qualifiedName ?? + entity.displayText ?? + entity.guid; + return typeof n === "string" && n.trim() !== "" ? n.trim() : "Unknown"; +}; + +export const resolveLatestEntityGuid = ( + entity: LatestEntityRowModel +): string | undefined => { + const g = + entity.guid ?? + (typeof entity.attributes?.__guid === "string" + ? entity.attributes.__guid + : undefined); + if (typeof g !== "string" || g.trim() === "") return undefined; + return g.trim(); +}; + +export const resolveLatestEntityTypeName = ( + entity: LatestEntityRowModel +): string => { + const t = entity.typeName; + return typeof t === "string" && t.trim() !== "" ? t.trim() : "Entity"; +}; diff --git a/dashboard/src/views/DetailPage/BusinessMetadataDetails/BusinessMetadataDetailsLayout.tsx b/dashboard/src/views/DetailPage/BusinessMetadataDetails/BusinessMetadataDetailsLayout.tsx index bb6f8f1382c..214c9faadd7 100644 --- a/dashboard/src/views/DetailPage/BusinessMetadataDetails/BusinessMetadataDetailsLayout.tsx +++ b/dashboard/src/views/DetailPage/BusinessMetadataDetails/BusinessMetadataDetailsLayout.tsx @@ -45,6 +45,7 @@ import { createEditBusinessMetadata } from "@api/apiMethods/typeDefApiMethods"; import { cloneDeep } from "@utils/Helper"; import { defaultAttrObj, defaultType } from "@utils/Enum"; import { fetchBusinessMetaData } from "@redux/slice/typeDefSlices/typedefBusinessMetadataSlice"; +import { fetchEntityData } from "@redux/slice/typeDefSlices/typedefEntitySlice"; import { getTypeName } from "@utils/CommonViewFunction"; const BusinessMetadataDetailsLayout = () => { @@ -241,6 +242,7 @@ const BusinessMetadataDetailsLayout = () => { try { await createEditBusinessMetadata("business_metadata", "PUT", data); dispatchState(fetchBusinessMetaData()); + dispatchState(fetchEntityData()); toast.success( "One or more Business Metadata attributes were updated successfully" ); diff --git a/dashboard/src/views/DetailPage/EntityDetailTabs/ClassificationsTab.tsx b/dashboard/src/views/DetailPage/EntityDetailTabs/ClassificationsTab.tsx index c898692c5c0..0fdd395f69b 100644 --- a/dashboard/src/views/DetailPage/EntityDetailTabs/ClassificationsTab.tsx +++ b/dashboard/src/views/DetailPage/EntityDetailTabs/ClassificationsTab.tsx @@ -78,6 +78,7 @@ const ClassificationsTab: React.FC = ({ ); const [openModal, setOpenModal] = useState(false); + const [removeAssignmentLoading, setRemoveAssignmentLoading] = useState(false); const [tagModal, setTagModal] = useState(false); const [updateTable, setUpdateTable] = useState(moment.now()); const [rowdata, setRowData] = useState(); @@ -129,6 +130,7 @@ const ClassificationsTab: React.FC = ({ const handleRemove = async () => { try { + setRemoveAssignmentLoading(true); await removeClassification(guid, currentValue.selectedValue); if (!isEmpty(guid)) { dispatchApi(fetchDetailPageData(guid as string)); @@ -145,6 +147,8 @@ const ClassificationsTab: React.FC = ({ setOpenModal(false); } catch (error) { serverError(error, toastId); + } finally { + setRemoveAssignmentLoading(false); } }; @@ -381,6 +385,8 @@ const ClassificationsTab: React.FC = ({ button1Handler={handleCloseModal} button2Label="Remove" button2Handler={handleRemove} + disableButton2={removeAssignmentLoading} + button2Loading={removeAssignmentLoading} > Remove: {currentValue.selectedValue} assignment from{" "} diff --git a/dashboard/src/views/DetailPage/EntityDetailTabs/PropagationPropertyModal.tsx b/dashboard/src/views/DetailPage/EntityDetailTabs/PropagationPropertyModal.tsx index 5ab64aef605..1ea05c70141 100644 --- a/dashboard/src/views/DetailPage/EntityDetailTabs/PropagationPropertyModal.tsx +++ b/dashboard/src/views/DetailPage/EntityDetailTabs/PropagationPropertyModal.tsx @@ -421,6 +421,7 @@ const PropagationPropertyModal = ({ button2Label="Update" button2Handler={() => onSubmit()} disableButton2={loading} + button2Loading={loading} > diff --git a/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx b/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx index ba1381528f0..68d069ea791 100644 --- a/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx +++ b/dashboard/src/views/DetailPage/GlossaryDetails/TermRelation.tsx @@ -219,6 +219,7 @@ const TermRelation = ({ glossaryTypeData }: any) => { button2Label={editModal ? "Update" : "Close"} button2Handler={editModal ? handleSubmit(onSubmit) : handleCloseModal} disableButton2={isSubmitting} + button2Loading={isSubmitting} maxWidth="md" > diff --git a/dashboard/src/views/Entity/EntityForm.tsx b/dashboard/src/views/Entity/EntityForm.tsx index f075b943faa..e6a66fa9981 100644 --- a/dashboard/src/views/Entity/EntityForm.tsx +++ b/dashboard/src/views/Entity/EntityForm.tsx @@ -521,6 +521,7 @@ const EntityForm = ({ button2Label={guid ? "Update" : "Create"} button2Handler={handleSubmit(onSubmit)} disableButton2={isSubmitting} + button2Loading={isSubmitting} isDirty={isDirty} maxWidth="md" > diff --git a/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx b/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx index 12a80b6de55..bd908486155 100644 --- a/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx +++ b/dashboard/src/views/Glossary/AddUpdateCategoryForm.tsx @@ -146,6 +146,7 @@ const AddUpdateCategoryForm = (props: { button1Handler={onClose} button2Label={isAdd ? "Create" : "Update"} disableButton2={isSubmitting} + button2Loading={isSubmitting} maxWidth="sm" button2Handler={handleSubmit(onSubmit)} > diff --git a/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx b/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx index 4aa2248d106..5f4a2285406 100644 --- a/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx +++ b/dashboard/src/views/Glossary/AddUpdateGlossaryForm.tsx @@ -19,108 +19,370 @@ import CustomModal from "@components/Modal"; import GlossaryForm from "./GlossaryForm"; import { useForm } from "react-hook-form"; import { - createGlossary, - editGlossary + createGlossary, + editGlossary } from "@api/apiMethods/glossaryApiMethod"; import { isEmpty, serverError } from "@utils/Utils"; +import { + downloadGlossaryImportTemplate, + postGlossaryImportFormData +} from "@utils/glossaryImportFlow"; +import { getApiErrorToastMessage } from "@utils/apiErrorToastMessage"; import { toast } from "react-toastify"; -import { useRef } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; +import type { MouseEvent } from "react"; import { useAppDispatch, useAppSelector } from "@hooks/reducerHook"; import { fetchGlossaryData } from "@redux/slice/glossarySlice"; +import { + Button, + IconButton, + List, + ListItem, + ListItemText, + Stack, + ToggleButton, + ToggleButtonGroup +} from "@mui/material"; +import FileDownloadIcon from "@mui/icons-material/FileDownload"; +import ArrowBackIosNewIcon from "@mui/icons-material/ArrowBackIosNew"; +import ImportLayout from "@views/SideBar/Import/ImportLayout"; +import { LightTooltip } from "@components/muiComponents"; + +type GlossaryCreateTab = "create" | "import"; + +const hasSelectedImportFile = (fileData: unknown): boolean => { + if (fileData == null) return false; + if (fileData instanceof File) return true; + if (typeof fileData === "object" && Object.keys(fileData as object).length > 0) + return true; + return false; +}; const AddUpdateGlossaryForm = (props: { - open: any; - onClose: any; - isAdd: any; - node: Record | undefined; + open: any; + onClose: any; + isAdd: any; + node: Record | undefined; }) => { - const { open, onClose, isAdd, node } = props; - const dispatch = useAppDispatch(); - const toastId: any = useRef(null); - const { glossaryData }: any = useAppSelector((state: any) => state.glossary); - const { id } = node || {}; - let defaultValue: Record = {}; - let glossaryObj: Record = {}; - if (!isAdd) { - glossaryObj = glossaryData.find((obj: { name: string }) => { - return obj.name == id; - }); - const { name, shortDescription, longDescription } = glossaryObj || {}; - - defaultValue["name"] = name; - defaultValue["shortDescription"] = shortDescription; - defaultValue["longDescription"] = longDescription; - } - const { - control, - handleSubmit, - setValue, - formState: { isSubmitting } - } = useForm({ - defaultValues: isAdd ? {} : defaultValue, - mode: "onChange", - shouldUnregister: true - }); - - const onSubmit = async (formValues: any) => { - let formData = { ...formValues }; - const { guid, qualifiedName } = glossaryObj; - const { - name, - shortDescription, - longDescription - }: { name: string; shortDescription: string; longDescription: string } = - formData; - let data: Record = {}; - if (!isAdd) { - data["guid"] = guid; - data["qualifiedName"] = qualifiedName; - } - data["name"] = name; - data["shortDescription"] = !isEmpty(shortDescription) - ? shortDescription - : ""; - data["longDescription"] = !isEmpty(longDescription) ? longDescription : ""; - - try { - if (isAdd) { - await createGlossary(data); - } else { - await editGlossary(guid, data); - } - - await dispatch(fetchGlossaryData()); - toast.dismiss(toastId.current); - toastId.current = toast.success( - `Glossary ${name} was ${isAdd ? "created" : "updated"} successfully` - ); - onClose(); - } catch (error) { - serverError(error, toastId); - } - }; - - return ( - <> - - - - - ); + const { open, onClose, isAdd, node } = props; + const dispatch = useAppDispatch(); + const toastId: any = useRef(null); + const { glossaryData }: any = useAppSelector((state: any) => state.glossary); + const { id } = node || {}; + let defaultValue: Record = {}; + let glossaryObj: Record = {}; + if (!isAdd) { + glossaryObj = glossaryData.find((obj: { name: string }) => { + return obj.name == id; + }); + const { name, shortDescription, longDescription } = glossaryObj || {}; + + defaultValue["name"] = name; + defaultValue["shortDescription"] = shortDescription; + defaultValue["longDescription"] = longDescription; + } + const { + control, + handleSubmit, + setValue, + formState: { isSubmitting } + } = useForm({ + defaultValues: isAdd ? {} : defaultValue, + mode: "onChange", + shouldUnregister: true + }); + + const [glossaryCreateTab, setGlossaryCreateTab] = + useState("create"); + const [importFileData, setImportFileData] = useState([]); + const [importProgress, setImportProgress] = useState(0); + const [importErrorDetails, setImportErrorDetails] = useState(false); + const [importData, setImportData] = useState(null); + const [importUploading, setImportUploading] = useState(false); + + const resetImportUi = useCallback(() => { + setGlossaryCreateTab("create"); + setImportFileData([]); + setImportProgress(0); + setImportErrorDetails(false); + setImportData(null); + setImportUploading(false); + }, []); + + const handleModalClose = useCallback(() => { + resetImportUi(); + onClose(); + }, [onClose, resetImportUi]); + + useEffect(() => { + if (!open) { + resetImportUi(); + } + }, [open, resetImportUi]); + + const handleGlossaryCreateTabChange = ( + _event: MouseEvent, + next: GlossaryCreateTab | null + ) => { + if (next == null) return; + setGlossaryCreateTab(next); + if (next === "create") { + setImportFileData([]); + setImportProgress(0); + setImportErrorDetails(false); + setImportData(null); + } + }; + + const handleDownloadTemplate = async () => { + try { + await downloadGlossaryImportTemplate(); + } catch { + toast.dismiss(toastId.current); + toastId.current = toast.error("Could not download template"); + } + }; + + const handleImportUpload = async () => { + if (!hasSelectedImportFile(importFileData)) return; + setImportUploading(true); + try { + const importResp = await postGlossaryImportFormData( + importFileData, + (pct) => setImportProgress(pct) + ); + if (importResp.data.failedImportInfoList == undefined) { + toast.dismiss(toastId.current); + toastId.current = toast.success( + `File: ${importFileData.name} imported successfully` + ); + await dispatch(fetchGlossaryData()); + handleModalClose(); + return; + } + if (importResp.data.failedImportInfoList != undefined) { + toast.dismiss(toastId.current); + toastId.current = toast.error( + importResp.data.failedImportInfoList[0].remarks + ); + setImportErrorDetails(true); + } + setImportData(importResp.data); + } catch (error) { + const message = getApiErrorToastMessage(error); + if (message === null) { + return; + } + toast.dismiss(toastId.current); + toastId.current = toast.error(message); + } finally { + setImportUploading(false); + } + }; + + const onSubmit = async (formValues: any) => { + let formData = { ...formValues }; + const { guid, qualifiedName } = glossaryObj; + const { + name, + shortDescription, + longDescription + }: { name: string; shortDescription: string; longDescription: string } = + formData; + let data: Record = {}; + if (!isAdd) { + data["guid"] = guid; + data["qualifiedName"] = qualifiedName; + } + data["name"] = name; + data["shortDescription"] = !isEmpty(shortDescription) + ? shortDescription + : ""; + data["longDescription"] = !isEmpty(longDescription) ? longDescription : ""; + + try { + if (isAdd) { + await createGlossary(data); + } else { + await editGlossary(guid, data); + } + + await dispatch(fetchGlossaryData()); + toast.dismiss(toastId.current); + toastId.current = toast.success( + `Glossary ${name} was ${isAdd ? "created" : "updated"} successfully` + ); + handleModalClose(); + } catch (error) { + serverError(error, toastId); + } + }; + + const showImportError = isAdd && glossaryCreateTab === "import" && importErrorDetails; + + const modalTitle = showImportError + ? "Error Details" + : isAdd + ? "Create Glossary" + : "Edit Glossary"; + + const titleIconNode = + showImportError ? ( + { + e.stopPropagation(); + setImportErrorDetails(false); + }} + size="small" + sx={{ color: (theme) => theme.palette.grey[500] }} + > + + + + + ) : undefined; + + const isImportMode = isAdd && glossaryCreateTab === "import" && !importErrorDetails; + + const button2Label = (() => { + if (!isAdd) return "Update"; + if (glossaryCreateTab === "create") return "Create"; + if (importErrorDetails) return ""; + return "Upload"; + })(); + + const button2Handler = (() => { + if (!isAdd || glossaryCreateTab === "create") return handleSubmit(onSubmit); + if (importErrorDetails) return () => {}; + return handleImportUpload; + })(); + + const disableButton2 = (() => { + if (!isAdd) return isSubmitting; + if (glossaryCreateTab === "create") return isSubmitting; + if (importErrorDetails) return true; + return !hasSelectedImportFile(importFileData); + })(); + + const button2Loading = + isAdd && glossaryCreateTab === "import" && !importErrorDetails + ? importUploading + : isSubmitting; + + const hideButton2 = Boolean( + isAdd && glossaryCreateTab === "import" && importErrorDetails + ); + + return ( + <> + + + {isAdd && ( + + + + Create glossary + + + Import glossary terms + + + + )} + {(!isAdd || glossaryCreateTab === "create") && ( + + )} + {isImportMode && ( + + + + + )} + {showImportError && importData?.failedImportInfoList && ( + + + {importData.failedImportInfoList.map( + ( + value: { + index: number; + remarks: string; + }, + index: number + ) => ( + + + + ) + )} + + + )} + + + + ); }; export default AddUpdateGlossaryForm; diff --git a/dashboard/src/views/Glossary/AddUpdateTermForm.tsx b/dashboard/src/views/Glossary/AddUpdateTermForm.tsx index feea620324d..f5ece0289d0 100644 --- a/dashboard/src/views/Glossary/AddUpdateTermForm.tsx +++ b/dashboard/src/views/Glossary/AddUpdateTermForm.tsx @@ -142,6 +142,7 @@ const AddUpdateTermForm = (props: { button1Handler={onClose} button2Label={isAdd ? "Create" : "Update"} disableButton2={isSubmitting} + button2Loading={isSubmitting} maxWidth="sm" button2Handler={handleSubmit(onSubmit)} > diff --git a/dashboard/src/views/Glossary/AssignCategory.tsx b/dashboard/src/views/Glossary/AssignCategory.tsx index 9e588ae3c81..5a6f8f8b95f 100644 --- a/dashboard/src/views/Glossary/AssignCategory.tsx +++ b/dashboard/src/views/Glossary/AssignCategory.tsx @@ -288,6 +288,7 @@ const AssignCategory = ({ maxWidth="sm" button2Handler={assignCatgeory} disableButton2={loading} + button2Loading={loading} > {relatedTerm ? ( diff --git a/dashboard/src/views/Glossary/DeleteGlossary.tsx b/dashboard/src/views/Glossary/DeleteGlossary.tsx index 744447494f3..c4b5dcf60ff 100644 --- a/dashboard/src/views/Glossary/DeleteGlossary.tsx +++ b/dashboard/src/views/Glossary/DeleteGlossary.tsx @@ -26,6 +26,7 @@ import { Typography } from "@mui/material"; import { fetchGlossaryData } from "@redux/slice/glossarySlice"; import { isEmpty, serverError } from "@utils/Utils"; import { useRef } from "react"; +import { useAsyncPending } from "@hooks/useAsyncPending"; import { useLocation, useNavigate, useParams } from "react-router-dom"; import { toast } from "react-toastify"; @@ -48,36 +49,39 @@ const DeleteGlossary = (props: { const navigate = useNavigate(); const dispatchApi = useAppDispatch(); const toastId: any = useRef(null); + const { pending: deleteInProgress, run: runDelete } = useAsyncPending(); const fetchCurrentData = async () => { await dispatchApi(fetchGlossaryData()); }; - const handleRemove = async () => { - try { - gtype == "term" - ? await deleteGlossaryorType(cGuid) - : await deleteGlossaryorTerm(guid); - updatedData(); - fetchCurrentData(); - toast.success( - `${ - gtype == "term" ? "Term" : "Glossary" - } ${id} was deleted successfully` - ); - if (!isEmpty(glossaryGuid) || !isEmpty(glossaryType)) { - navigate( - { - pathname: "/" - }, - { replace: true } + const handleRemove = () => { + void runDelete(async () => { + try { + gtype == "term" + ? await deleteGlossaryorType(cGuid) + : await deleteGlossaryorTerm(guid); + updatedData(); + await fetchCurrentData(); + toast.success( + `${ + gtype == "term" ? "Term" : "Glossary" + } ${id} was deleted successfully` ); + if (!isEmpty(glossaryGuid) || !isEmpty(glossaryType)) { + navigate( + { + pathname: "/" + }, + { replace: true } + ); + } + onClose(); + setExpandNode(null); + } catch (error) { + serverError(error, toastId); } - onClose(); - setExpandNode(null); - } catch (error) { - serverError(error, toastId); - } + }); }; return ( @@ -92,6 +96,8 @@ const DeleteGlossary = (props: { button2Label="Ok" maxWidth="sm" button2Handler={handleRemove} + disableButton2={deleteInProgress} + button2Loading={deleteInProgress} > Are you sure you want to delete{" "} diff --git a/dashboard/src/views/SaveFilters/SaveFilters.tsx b/dashboard/src/views/SaveFilters/SaveFilters.tsx index fed2fe27f6f..ac65237ec2b 100644 --- a/dashboard/src/views/SaveFilters/SaveFilters.tsx +++ b/dashboard/src/views/SaveFilters/SaveFilters.tsx @@ -206,6 +206,7 @@ const SaveFilters = ({ maxWidth="sm" button2Handler={handleSubmit(onSubmit)} disableButton2={isSubmitting} + button2Loading={isSubmitting} > {" "} diff --git a/dashboard/src/views/SearchResult/SearchResult.tsx b/dashboard/src/views/SearchResult/SearchResult.tsx index a026e1175df..5d850d93a8e 100644 --- a/dashboard/src/views/SearchResult/SearchResult.tsx +++ b/dashboard/src/views/SearchResult/SearchResult.tsx @@ -71,6 +71,9 @@ interface Params { classification: any; termName: string | null; relationshipFilters?: string | null; + sortBy?: string; + sortOrder?: string; + excludeHeaderAttributes?: boolean; } let defaultColumnsName: Array = [ @@ -155,6 +158,15 @@ const SearchResult = ({ classificationParams, glossaryTypeParams, hideFilters }: ? !searchParams.get("excludeST") : true, includeClassificationAttributes: true, + ...(!isEmpty(searchParams.get("sortBy")) && { + sortBy: searchParams.get("sortBy") + }), + ...(!isEmpty(searchParams.get("sortOrder")) && { + sortOrder: searchParams.get("sortOrder") + }), + ...(searchParams.get("excludeHeaderAttributes") === "true" && { + excludeHeaderAttributes: true + }), ...(isEmpty(classificationParams || glossaryTypeParams) && { entityFilters: !isEmpty(entityFilterParams) ? searchParamsAPiQuery(entityFilterParams) @@ -1000,12 +1012,20 @@ const SearchResult = ({ classificationParams, glossaryTypeParams, hideFilters }: return hideColumns; }; + const latestEntitiesSortBy = searchParams.get("sortBy"); + const latestEntitiesSortOrder = searchParams.get("sortOrder"); const getDefaultSort = useMemo(() => { if (isDslAggregate) { return [] as any[]; // no default sorting for DSL aggregates } - return [{ id: "name", asc: true }]; - }, [isDslAggregate]); + if ( + latestEntitiesSortBy === "__timestamp" && + latestEntitiesSortOrder === "DESCENDING" + ) { + return [{ id: "__timestamp", desc: true }]; + } + return [{ id: "name", desc: false }]; + }, [isDslAggregate, latestEntitiesSortBy, latestEntitiesSortOrder]); return ( diff --git a/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx b/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx index 02f5e27b6e9..bc9e444c278 100644 --- a/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx +++ b/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx @@ -64,7 +64,7 @@ import { globalSearchFilterInitialQuery, isEmpty } from "@utils/Utils"; import { attributeFilter } from "@utils/CommonViewFunction"; import { cloneDeep } from "@utils/Helper"; import LaunchOutlinedIcon from "@mui/icons-material/LaunchOutlined"; -import { getGlossaryImportTmpl } from "@api/apiMethods/glossaryApiMethod"; +import { downloadGlossaryImportTemplate } from "@utils/glossaryImportFlow"; import { toast } from "react-toastify"; import { EnumTypeDefData, TreeNode } from "@models/treeStructureType"; import ImportDialog from "@components/ImportDialog"; @@ -969,33 +969,26 @@ const BarTreeView: FC<{ const downloadFile = async () => { try { - let apiResp: any = {}; - if (treeName == "Entities") { - apiResp = await getBusinessMetadataImportTmpl({}); - } else if (treeName == "Glossary") { - apiResp = await getGlossaryImportTmpl({}); - } - let text: string = ""; - if (apiResp) { - text = apiResp.data; + if (treeName == "Glossary") { + await downloadGlossaryImportTemplate(); + return; } + const apiResp: any = await getBusinessMetadataImportTmpl({}); + const text: string = apiResp ? apiResp.data : ""; const blob = new Blob([text], { type: "text/plain" }); const url = window.URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; - if (treeName == "Entities") { - link.setAttribute("download", "template_business_metadata"); - } else if (treeName == "Glossary") { - link.setAttribute("download", "template"); - } + link.setAttribute("download", "template_business_metadata"); document.body.appendChild(link); link.click(); document.body.removeChild(link); + window.URL.revokeObjectURL(url); } catch { /* ignore download error */ } diff --git a/dashboard/src/views/Statistics/ServerStats.tsx b/dashboard/src/views/Statistics/ServerStats.tsx index 9f6974614d1..5f131c41c73 100644 --- a/dashboard/src/views/Statistics/ServerStats.tsx +++ b/dashboard/src/views/Statistics/ServerStats.tsx @@ -118,12 +118,11 @@ const ServerStats = ({ selectedValue, currentMetricsData }: any) => { let notificationTableHeader = [ "Count", - "Avg", - "Time (ms)", + "Avg time (ms)", "Creates", "Updates", - "Deletes" - // "Failed" + "Deletes", + "Failed" ]; let topciOffsetTableHeader = [ diff --git a/dashboard/src/views/Statistics/Statistics.tsx b/dashboard/src/views/Statistics/Statistics.tsx index 6204a6d081d..51bb42077d1 100644 --- a/dashboard/src/views/Statistics/Statistics.tsx +++ b/dashboard/src/views/Statistics/Statistics.tsx @@ -23,6 +23,7 @@ import ClassificationStats from "./ClassificationStats"; import { Autocomplete, Badge, + CircularProgress, IconButton, Stack, TextField @@ -72,6 +73,7 @@ const Statistics = ({ value: "Current" }); const [loading, setLoading] = useState(true); + const [refreshBusy, setRefreshBusy] = useState(false); useEffect(() => { fetchMetricsStatsDetails(); @@ -117,12 +119,20 @@ const Statistics = ({ }; const handleRefresh = async () => { - await fetchMetricsStatsDetails(); - await dispatch(fetchMetricEntity()); - if (toastId.current) { - toast.dismiss(toastId.current); + if (refreshBusy) { + return; + } + setRefreshBusy(true); + try { + await fetchMetricsStatsDetails(); + await dispatch(fetchMetricEntity()); + if (toastId.current) { + toast.dismiss(toastId.current); + } + toastId.current = toast.success("Metric data is refreshed"); + } finally { + setRefreshBusy(false); } - toastId.current = toast.success("Metric data is refreshed"); }; return ( @@ -137,14 +147,23 @@ const Statistics = ({ postTitleIcon={ - { - handleRefresh(); - }} - > - - + + { + void handleRefresh(); + }} + disabled={refreshBusy || loading} + aria-busy={refreshBusy} + aria-label="Refresh metrics data" + > + {refreshBusy ? ( + + ) : ( + + )} + + } From b7014d4e0072370687cd9a87fa4fea53665f57b1 Mon Sep 17 00:00:00 2001 From: achandel-01 Date: Tue, 19 May 2026 21:26:23 +0530 Subject: [PATCH 06/51] ATLAS-5266: Upgrading commons-configuration1 to commons-configuration2. (#592) Co-authored-by: Abhinav Chandel (cherry picked from commit 6a86ea11df3d8339e5fdb4ce43b3ed9618385e03) --- addons/falcon-bridge-shim/pom.xml | 4 ++++ addons/falcon-bridge/pom.xml | 4 ++++ .../atlas/falcon/hook/FalconHookIT.java | 2 +- addons/hbase-bridge/pom.xml | 6 +++--- .../atlas/hbase/bridge/HBaseBridge.java | 2 +- .../apache/atlas/hbase/HBaseAtlasHookIT.java | 2 +- addons/hive-bridge/pom.xml | 17 ++++++++++++--- .../hive/bridge/HiveMetaStoreBridge.java | 2 +- .../hive/bridge/HiveMetaStoreBridgeV2.java | 2 +- .../hive/hook/utils/ActiveEntityFilter.java | 2 +- .../org/apache/atlas/hive/HiveITBase.java | 2 +- .../apache/atlas/hive/hook/HiveHookIT.java | 2 +- addons/impala-bridge/pom.xml | 6 +++--- .../atlas/impala/ImpalaLineageITBase.java | 2 +- addons/kafka-bridge/pom.xml | 21 ++++++++++++++++--- .../atlas/kafka/bridge/KafkaBridge.java | 2 +- .../atlas/kafka/bridge/KafkaBridgeTest.java | 2 +- .../apache/atlas/sqoop/hook/SqoopHook.java | 2 +- .../apache/atlas/sqoop/hook/SqoopHookIT.java | 2 +- addons/storm-bridge/pom.xml | 6 +++--- .../atlas/storm/hook/StormAtlasHookIT.java | 2 +- .../atlas/trino/cli/ExtractorContext.java | 2 +- .../atlas/trino/client/AtlasClientHelper.java | 2 +- .../atlas/trino/client/TrinoClientHelper.java | 2 +- .../authorize/AtlasAuthorizerFactory.java | 2 +- client/client-v1/pom.xml | 6 ------ .../org/apache/atlas/AtlasAdminClient.java | 2 +- .../java/org/apache/atlas/AtlasClient.java | 2 +- .../apache/atlas/AtlasAdminClientTest.java | 2 +- .../org/apache/atlas/AtlasClientTest.java | 2 +- .../java/org/apache/atlas/AtlasClientV2.java | 2 +- .../org/apache/atlas/AtlasClientV2Test.java | 2 +- .../org/apache/atlas/AtlasBaseClient.java | 2 +- .../atlas/security/SecureClientUtils.java | 4 ++-- common/pom.xml | 12 ----------- .../org/apache/atlas/CommonConfiguration.java | 2 +- .../org/apache/atlas/ha/HAConfiguration.java | 2 +- .../apache/atlas/repository/Constants.java | 2 +- .../org/apache/atlas/service/Services.java | 2 +- .../org/apache/atlas/utils/KafkaUtils.java | 2 +- .../atlas/utils/OnAtlasPropertyCondition.java | 2 +- .../apache/atlas/ha/HAConfigurationTest.java | 2 +- .../apache/atlas/utils/KafkaUtilsTest.java | 4 ++-- .../apache/atlas/graph/GraphSandboxUtil.java | 2 +- .../graphdb/janus/AtlasJanusGraph.java | 2 +- .../janus/AtlasJanusGraphDatabase.java | 4 ++-- .../janus/AtlasJanusGraphIndexClient.java | 2 +- .../graphdb/janus/AtlasJanusDatabaseTest.java | 2 +- .../janus/AtlasJanusGraphIndexClientTest.java | 2 +- .../graphdb/janus/AtlasJanusGraphTest.java | 2 +- .../graphdb/janus/JanusGraphProviderTest.java | 2 +- graphdb/janusgraph-rdbms/pom.xml | 4 ++++ intg/pom.xml | 6 ------ .../apache/atlas/ApplicationProperties.java | 15 ++++++++----- .../org/apache/atlas/AtlasConfiguration.java | 2 +- .../security/InMemoryJAASConfiguration.java | 4 ++-- .../apache/atlas/security/SecurityUtil.java | 4 ++-- .../apache/atlas/type/AtlasStructType.java | 2 +- .../atlas/utils/AtlasConfigurationUtil.java | 2 +- .../atlas/utils/AuthenticationUtil.java | 2 +- .../java/org/apache/atlas/utils/SSLUtil.java | 2 +- .../atlas/ApplicationPropertiesTest.java | 4 ++-- .../utils/AtlasConfigurationUtilTest.java | 4 ++-- .../atlas/utils/AuthenticationUtilTest.java | 4 ++-- .../org/apache/atlas/utils/SSLUtilTest.java | 4 ++-- .../utils/TestAtlasAsyncImportTestUtil.java | 2 +- notification/pom.xml | 6 +++--- .../java/org/apache/atlas/hook/AtlasHook.java | 2 +- .../apache/atlas/hook/AtlasTopicCreator.java | 2 +- .../atlas/kafka/EmbeddedKafkaServer.java | 4 ++-- .../apache/atlas/kafka/KafkaNotification.java | 4 ++-- .../atlas/kafka/NotificationProvider.java | 2 +- .../notification/AbstractNotification.java | 2 +- .../notification/rest/RestNotification.java | 2 +- .../notification/spool/AtlasFileSpool.java | 2 +- .../spool/SpoolConfiguration.java | 2 +- .../atlas/hook/AtlasTopicCreatorTest.java | 2 +- .../atlas/kafka/KafkaNotificationTest.java | 2 +- .../AbstractNotificationTest.java | 2 +- .../notification/RestNotificationTest.java | 2 +- .../atlas/notification/spool/BaseTest.java | 4 ++-- pom.xml | 8 ------- .../AbstractStorageBasedAuditRepository.java | 4 ++-- .../audit/AtlasAuditReductionService.java | 2 +- .../audit/HBaseBasedAuditRepository.java | 2 +- .../rdbms/RdbmsBasedAuditRepository.java | 4 ++-- .../repository/graph/AtlasGraphProvider.java | 2 +- .../repository/graph/FullTextMapperV2.java | 2 +- .../graph/GraphBackedSearchIndexer.java | 2 +- .../graph/IndexRecoveryService.java | 2 +- .../impexp/MigrationProgressService.java | 2 +- .../migration/DataMigrationService.java | 2 +- .../repository/patches/AtlasPatchService.java | 2 +- .../patches/ConcurrentPatchProcessor.java | 2 +- .../patches/EdgePatchProcessor.java | 2 +- .../AtlasTypeDefStoreInitializer.java | 2 +- .../store/graph/v2/AtlasGraphUtilsV2.java | 2 +- .../v2/tasks/AuditReductionTaskFactory.java | 2 +- .../SearchResultDownloadTask.java | 2 +- .../SearchResultDownloadTaskFactory.java | 2 +- .../apache/atlas/services/PurgeService.java | 2 +- .../apache/atlas/tasks/TaskManagement.java | 2 +- .../util/AtlasRepositoryConfiguration.java | 2 +- .../java/org/apache/atlas/TestModules.java | 2 +- .../audit/AtlasAuditReductionServiceTest.java | 2 +- .../audit/CassandraAuditRepositoryTest.java | 4 ++-- .../migration/DataMigrationServiceTest.java | 2 +- .../MigrationProgressServiceTest.java | 2 +- .../patches/AtlasPatchServiceTest.java | 2 +- .../AtlasTypeDefStoreInitializerTest.java | 2 +- .../atlas/ha/AtlasServerIdSelector.java | 2 +- .../atlas/ha/AtlasServerIdSelectorTest.java | 2 +- test-tools/pom.xml | 6 ------ .../apache/atlas/runner/LocalSolrRunner.java | 2 +- tools/atlas-index-repair/pom.xml | 4 ++++ .../org/apache/atlas/tools/RepairIndex.java | 2 +- .../atlas/tools/BulkFetchAndUpdate.java | 2 +- tools/notification-analyzer/pom.xml | 6 +++--- webapp/pom.xml | 5 ----- .../src/main/java/org/apache/atlas/Atlas.java | 9 +++++--- .../org/apache/atlas/examples/QuickStart.java | 2 +- .../apache/atlas/examples/QuickStartV2.java | 2 +- .../EntityNotificationListenerV2.java | 2 +- .../EntityNotificationSender.java | 2 +- .../notification/ImportTaskListenerImpl.java | 2 +- .../NotificationEntityChangeListener.java | 2 +- .../NotificationHookConsumer.java | 2 +- .../org/apache/atlas/web/dao/UserDao.java | 2 +- .../filters/AtlasAuthenticationFilter.java | 4 ++-- .../filters/AtlasCSRFPreventionFilter.java | 2 +- .../AtlasKnoxSSOAuthenticationFilter.java | 2 +- .../apache/atlas/web/filters/AuditFilter.java | 2 +- .../apache/atlas/web/filters/HeadersUtil.java | 4 ++-- .../atlas/web/listeners/LoginProcessor.java | 10 ++++----- .../atlas/web/resources/AdminResource.java | 11 ++++++---- .../apache/atlas/web/rest/DiscoveryREST.java | 2 +- .../AtlasADAuthenticationProvider.java | 4 ++-- .../security/AtlasAuthenticationProvider.java | 2 +- .../AtlasKeycloakAuthenticationProvider.java | 2 +- .../AtlasLdapAuthenticationProvider.java | 4 ++-- .../AtlasPamAuthenticationProvider.java | 2 +- .../web/security/AtlasSecurityConfig.java | 2 +- .../service/ActiveInstanceElectorService.java | 2 +- .../web/service/ActiveInstanceState.java | 2 +- .../atlas/web/service/CuratorFactory.java | 2 +- .../web/service/SecureEmbeddedServer.java | 4 ++-- .../atlas/web/service/ServiceState.java | 2 +- .../apache/atlas/web/setup/SetupSteps.java | 2 +- .../test/java/org/apache/atlas/AtlasIT.java | 2 +- .../EntityNotificationListenerV2Test.java | 2 +- .../EntityNotificationSenderTest.java | 2 +- .../NotificationEntityChangeListenerTest.java | 2 +- .../NotificationHookConsumerKafkaTest.java | 2 +- .../NotificationHookConsumerTest.java | 2 +- .../java/org/apache/atlas/web/TestUtils.java | 7 +++++-- .../AtlasAuthenticationFilterTest.java | 6 +++--- ...AtlasAuthenticationKerberosFilterTest.java | 2 +- .../AtlasKnoxSSOAuthenticationFilterTest.java | 2 +- .../atlas/web/filters/AuditFilterTest.java | 2 +- .../integration/AdminJerseyResourceIT.java | 8 +++++-- .../atlas/web/integration/BaseResourceIT.java | 2 +- .../atlas/web/listeners/LoginProcessorIT.java | 6 +++--- .../web/resources/AdminResourceTest.java | 2 +- .../atlas/web/rest/DiscoveryRESTTest.java | 2 +- .../AtlasADAuthenticationProviderTest.java | 4 ++-- .../AtlasAuthenticationProviderTest.java | 2 +- ...lasKeycloakAuthenticationProviderTest.java | 2 +- .../AtlasLdapAuthenticationProviderTest.java | 4 ++-- .../AtlasPamAuthenticationProviderTest.java | 4 ++-- .../web/security/AtlasSecurityConfigTest.java | 2 +- .../atlas/web/security/BaseSecurityTest.java | 18 +++++++++------- .../web/security/FileAuthenticationTest.java | 2 +- .../security/NegativeSSLAndKerberosTest.java | 9 +++++--- .../web/security/SSLAndKerberosTest.java | 6 ++++-- .../apache/atlas/web/security/SSLTest.java | 4 ++-- .../ActiveInstanceElectorServiceTest.java | 2 +- .../web/service/ActiveInstanceStateTest.java | 2 +- .../atlas/web/service/CuratorFactoryTest.java | 2 +- .../web/service/SecureEmbeddedServerTest.java | 2 +- .../service/SecureEmbeddedServerTestBase.java | 4 ++-- .../atlas/web/service/ServiceStateTest.java | 2 +- .../atlas/web/setup/SetupStepsTest.java | 2 +- 182 files changed, 307 insertions(+), 283 deletions(-) diff --git a/addons/falcon-bridge-shim/pom.xml b/addons/falcon-bridge-shim/pom.xml index 25d45947f6e..94c7fc2a4cd 100755 --- a/addons/falcon-bridge-shim/pom.xml +++ b/addons/falcon-bridge-shim/pom.xml @@ -48,6 +48,10 @@ ${falcon.version} provided + + commons-configuration + commons-configuration + javax.servlet servlet-api diff --git a/addons/falcon-bridge/pom.xml b/addons/falcon-bridge/pom.xml index 3f54d6ebc5f..1125b2caedb 100644 --- a/addons/falcon-bridge/pom.xml +++ b/addons/falcon-bridge/pom.xml @@ -75,6 +75,10 @@ ${falcon.version} provided + + commons-configuration + commons-configuration + javax.servlet servlet-api diff --git a/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java b/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java index f1b4cb41b94..906686051d9 100644 --- a/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java +++ b/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java @@ -32,7 +32,7 @@ import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.utils.ParamChecker; import org.apache.atlas.v1.typesystem.types.utils.TypesUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.RandomStringUtils; import org.apache.falcon.entity.FeedHelper; import org.apache.falcon.entity.FileSystemStorage; diff --git a/addons/hbase-bridge/pom.xml b/addons/hbase-bridge/pom.xml index a55f8bcaf2d..7a98e42606f 100644 --- a/addons/hbase-bridge/pom.xml +++ b/addons/hbase-bridge/pom.xml @@ -577,9 +577,9 @@ ${jackson.version} - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} com.sun.jersey diff --git a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java index 81aa91b926b..137d8378f74 100644 --- a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java +++ b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java @@ -36,7 +36,7 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hbase.HBaseConfiguration; diff --git a/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java b/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java index 00d140e0e55..40cd28139a4 100644 --- a/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java +++ b/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java @@ -159,7 +159,7 @@ public void testCreateTable() throws Exception { // Methods for creating HBase private void createAtlasClient() { try { - org.apache.commons.configuration.Configuration configuration = ApplicationProperties.get(); + org.apache.commons.configuration2.Configuration configuration = ApplicationProperties.get(); String[] atlasEndPoint = configuration.getStringArray(HBaseAtlasHook.ATTR_ATLAS_ENDPOINT); configuration.setProperty("atlas.cluster.name", CLUSTER_NAME); diff --git a/addons/hive-bridge/pom.xml b/addons/hive-bridge/pom.xml index 20e8b483b67..6e199ea0b5f 100755 --- a/addons/hive-bridge/pom.xml +++ b/addons/hive-bridge/pom.xml @@ -56,6 +56,12 @@ atlas-notification + + org.apache.commons + commons-text + ${commons-text.version} + + org.apache.hadoop hadoop-annotations @@ -511,9 +517,14 @@ ${jackson.version} - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} + + + org.apache.commons + commons-text + ${commons-text.version} com.sun.jersey diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java index e4f20554f93..083a66488a4 100755 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java +++ b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java @@ -51,7 +51,7 @@ import org.apache.commons.cli.MissingArgumentException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java index 30720548d1c..fbb741b2d1f 100644 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java +++ b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java @@ -45,7 +45,7 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.RandomStringUtils; diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java index 0b0d4d6b265..8b07ac5ccbe 100644 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java +++ b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java @@ -20,7 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import org.apache.atlas.hive.hook.HiveHook; import org.apache.atlas.model.notification.HookNotification; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java index f0494dbfef0..b5ea108548c 100644 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java +++ b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java @@ -33,7 +33,7 @@ import org.apache.atlas.model.notification.HookNotification; import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.utils.ParamChecker; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.fs.Path; diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java index f88928d28e0..50a2f0a2e4e 100755 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java +++ b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java @@ -37,7 +37,7 @@ import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.type.AtlasTypeUtil; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hive.conf.HiveConf; diff --git a/addons/impala-bridge/pom.xml b/addons/impala-bridge/pom.xml index 66648b5c043..9970e386537 100644 --- a/addons/impala-bridge/pom.xml +++ b/addons/impala-bridge/pom.xml @@ -501,9 +501,9 @@ ${jackson.version} - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} com.sun.jersey diff --git a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java b/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java index 7c59f917d70..fa4291450fb 100644 --- a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java +++ b/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java @@ -28,7 +28,7 @@ import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.utils.ParamChecker; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hive.conf.HiveConf; diff --git a/addons/kafka-bridge/pom.xml b/addons/kafka-bridge/pom.xml index 10910ac33a1..511b5b0bdf6 100644 --- a/addons/kafka-bridge/pom.xml +++ b/addons/kafka-bridge/pom.xml @@ -64,6 +64,11 @@ avro ${avro.version} + + org.apache.commons + commons-text + 1.11.0 + org.apache.hadoop hadoop-auth @@ -479,6 +484,11 @@ hadoop-auth ${hadoop.version} + + org.apache.hadoop + hadoop-common + ${hadoop.version} + com.google.guava guava @@ -495,9 +505,14 @@ ${httpcomponents-httpcore.version} - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} + + + org.apache.commons + commons-text + 1.11.0 com.googlecode.json-simple diff --git a/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java b/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java index 2c39a58aa63..dc14ead0cf3 100644 --- a/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java +++ b/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java @@ -36,7 +36,7 @@ import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; import org.apache.http.impl.client.CloseableHttpClient; diff --git a/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java b/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java index aeb15be7e97..0d64d443fc5 100644 --- a/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java +++ b/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java @@ -26,7 +26,7 @@ import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.utils.KafkaUtils; import org.apache.avro.Schema; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; diff --git a/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java b/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java index 63ea2a52407..88cf44b1d22 100644 --- a/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java +++ b/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java @@ -32,7 +32,7 @@ import org.apache.atlas.sqoop.model.SqoopDataTypes; import org.apache.atlas.type.AtlasTypeUtil; import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.sqoop.SqoopJobDataPublisher; import org.apache.sqoop.util.ImportException; diff --git a/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java b/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java index f73990b23bb..3d7228c5702 100644 --- a/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java +++ b/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java @@ -26,7 +26,7 @@ import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.utils.ParamChecker; import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.sqoop.SqoopJobDataPublisher; import org.slf4j.Logger; import org.testng.annotations.BeforeClass; diff --git a/addons/storm-bridge/pom.xml b/addons/storm-bridge/pom.xml index c7fcb303fcc..cbbff06f1d0 100644 --- a/addons/storm-bridge/pom.xml +++ b/addons/storm-bridge/pom.xml @@ -461,9 +461,9 @@ ${aopalliance.version} - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} org.apache.commons diff --git a/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java b/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java index 36c19c7a739..4879ffe1dff 100644 --- a/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java +++ b/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java @@ -25,7 +25,7 @@ import org.apache.atlas.storm.model.StormDataTypes; import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.storm.ILocalCluster; import org.apache.storm.generated.StormTopology; import org.slf4j.Logger; diff --git a/addons/trino-extractor/src/main/java/org/apache/atlas/trino/cli/ExtractorContext.java b/addons/trino-extractor/src/main/java/org/apache/atlas/trino/cli/ExtractorContext.java index 2857a6ff40e..049e93e0e96 100644 --- a/addons/trino-extractor/src/main/java/org/apache/atlas/trino/cli/ExtractorContext.java +++ b/addons/trino-extractor/src/main/java/org/apache/atlas/trino/cli/ExtractorContext.java @@ -22,7 +22,7 @@ import org.apache.atlas.trino.client.AtlasClientHelper; import org.apache.atlas.trino.client.TrinoClientHelper; import org.apache.commons.cli.CommandLine; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import java.io.IOException; diff --git a/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/AtlasClientHelper.java b/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/AtlasClientHelper.java index a446fc980f3..e71cc0776e2 100644 --- a/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/AtlasClientHelper.java +++ b/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/AtlasClientHelper.java @@ -31,7 +31,7 @@ import org.apache.atlas.utils.AuthenticationUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import org.apache.hadoop.security.UserGroupInformation; import org.slf4j.Logger; diff --git a/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/TrinoClientHelper.java b/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/TrinoClientHelper.java index 28a7df650bf..33a75cd2176 100644 --- a/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/TrinoClientHelper.java +++ b/addons/trino-extractor/src/main/java/org/apache/atlas/trino/client/TrinoClientHelper.java @@ -17,7 +17,7 @@ */ package org.apache.atlas.trino.client; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import java.sql.Connection; diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java index 0b24ef68d41..dab3ea0a10c 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java @@ -21,7 +21,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.authorize.simple.AtlasSimpleAuthorizer; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/client/client-v1/pom.xml b/client/client-v1/pom.xml index a07a94e8720..31d22dbd91c 100644 --- a/client/client-v1/pom.xml +++ b/client/client-v1/pom.xml @@ -42,12 +42,6 @@ org.apache.atlas atlas-common ${project.version} - - - org.apache.commons - commons-text - - diff --git a/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java b/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java index 323aabddd09..d1932f0a896 100644 --- a/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java +++ b/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java @@ -28,7 +28,7 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import java.util.Arrays; diff --git a/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java b/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java index ab678929518..8dfb6d2c9d0 100644 --- a/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java +++ b/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java @@ -33,7 +33,7 @@ import org.apache.atlas.v1.model.typedef.TraitTypeDefinition; import org.apache.atlas.v1.model.typedef.TypesDef; import org.apache.atlas.v1.typesystem.types.utils.TypesUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; import org.slf4j.Logger; diff --git a/client/client-v1/src/test/java/org/apache/atlas/AtlasAdminClientTest.java b/client/client-v1/src/test/java/org/apache/atlas/AtlasAdminClientTest.java index 0c3773b59c5..cb1395b0d98 100644 --- a/client/client-v1/src/test/java/org/apache/atlas/AtlasAdminClientTest.java +++ b/client/client-v1/src/test/java/org/apache/atlas/AtlasAdminClientTest.java @@ -21,7 +21,7 @@ import org.apache.atlas.utils.AuthenticationUtil; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java b/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java index afa7b9a85a2..a86d8e3af5a 100644 --- a/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java +++ b/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.model.legacy.EntityResult; import org.apache.atlas.type.AtlasType; import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.mockito.Matchers; import org.mockito.Mock; diff --git a/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java b/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java index 04e4376d629..a46a6724a6a 100644 --- a/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java +++ b/client/client-v2/src/main/java/org/apache/atlas/AtlasClientV2.java @@ -74,7 +74,7 @@ import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.type.AtlasType; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; diff --git a/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java b/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java index f4942d7f59c..f0799ee8475 100644 --- a/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java +++ b/client/client-v2/src/test/java/org/apache/atlas/AtlasClientV2Test.java @@ -52,7 +52,7 @@ import org.apache.atlas.model.typedef.AtlasRelationshipDef; import org.apache.atlas.model.typedef.AtlasStructDef; import org.apache.atlas.model.typedef.AtlasTypesDef; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.mockito.Mock; import org.mockito.MockitoAnnotations; diff --git a/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java b/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java index 3e4ecad7880..2faa7c5e11b 100644 --- a/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java +++ b/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java @@ -46,7 +46,7 @@ import org.apache.atlas.type.AtlasType; import org.apache.atlas.utils.AtlasJson; import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; diff --git a/client/common/src/main/java/org/apache/atlas/security/SecureClientUtils.java b/client/common/src/main/java/org/apache/atlas/security/SecureClientUtils.java index 477ce56dc38..e6fb86e5358 100644 --- a/client/common/src/main/java/org/apache/atlas/security/SecureClientUtils.java +++ b/client/common/src/main/java/org/apache/atlas/security/SecureClientUtils.java @@ -66,7 +66,7 @@ public class SecureClientUtils { private SSLFactory factory; - public static void persistSSLClientConfiguration(org.apache.commons.configuration.Configuration clientConfig, String confLocation) throws AtlasException, IOException { + public static void persistSSLClientConfiguration(org.apache.commons.configuration2.Configuration clientConfig, String confLocation) throws AtlasException, IOException { //trust settings Configuration configuration = new Configuration(false); File sslClientFile = getSSLClientFile(confLocation); @@ -94,7 +94,7 @@ public static void persistSSLClientConfiguration(org.apache.commons.configuratio } } - public URLConnectionClientHandler getClientConnectionHandler(DefaultClientConfig config, org.apache.commons.configuration.Configuration clientConfig, String doAsUser, final UserGroupInformation ugi) { + public URLConnectionClientHandler getClientConnectionHandler(DefaultClientConfig config, org.apache.commons.configuration2.Configuration clientConfig, String doAsUser, final UserGroupInformation ugi) { config.getProperties().put(URLConnectionClientHandler.PROPERTY_HTTP_URL_CONNECTION_SET_METHOD_WORKAROUND, true); Configuration conf = new Configuration(); diff --git a/common/pom.xml b/common/pom.xml index e3d1e6dbd17..2f9072d3569 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -42,12 +42,6 @@ commons-collections commons-collections - - - commons-configuration - commons-configuration - - javax.annotation javax.annotation-api @@ -68,12 +62,6 @@ org.apache.commons commons-configuration2 ${commons-conf2.version} - - - org.apache.commons - commons-text - - diff --git a/common/src/main/java/org/apache/atlas/CommonConfiguration.java b/common/src/main/java/org/apache/atlas/CommonConfiguration.java index edea42ba8b9..09bb4ec9a6c 100644 --- a/common/src/main/java/org/apache/atlas/CommonConfiguration.java +++ b/common/src/main/java/org/apache/atlas/CommonConfiguration.java @@ -29,7 +29,7 @@ public class CommonConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(CommonConfiguration.class); @Bean - public org.apache.commons.configuration.Configuration getAtlasConfig() throws AtlasException { + public org.apache.commons.configuration2.Configuration getAtlasConfig() throws AtlasException { try { return ApplicationProperties.get(); } catch (AtlasException e) { diff --git a/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java b/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java index 896aa373281..57b95c507f7 100644 --- a/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java +++ b/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java @@ -19,7 +19,7 @@ package org.apache.atlas.ha; import org.apache.atlas.security.SecurityProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; diff --git a/common/src/main/java/org/apache/atlas/repository/Constants.java b/common/src/main/java/org/apache/atlas/repository/Constants.java index dcc3f123e97..13f36c4b479 100644 --- a/common/src/main/java/org/apache/atlas/repository/Constants.java +++ b/common/src/main/java/org/apache/atlas/repository/Constants.java @@ -20,7 +20,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.encodePropertyKey; diff --git a/common/src/main/java/org/apache/atlas/service/Services.java b/common/src/main/java/org/apache/atlas/service/Services.java index 7287268d236..c815d99e5a2 100644 --- a/common/src/main/java/org/apache/atlas/service/Services.java +++ b/common/src/main/java/org/apache/atlas/service/Services.java @@ -18,7 +18,7 @@ package org.apache.atlas.service; import org.apache.atlas.annotation.AtlasService; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/common/src/main/java/org/apache/atlas/utils/KafkaUtils.java b/common/src/main/java/org/apache/atlas/utils/KafkaUtils.java index 83b165c0014..7ee13b7dfa0 100644 --- a/common/src/main/java/org/apache/atlas/utils/KafkaUtils.java +++ b/common/src/main/java/org/apache/atlas/utils/KafkaUtils.java @@ -20,7 +20,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.security.SecurityUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; import org.apache.kafka.clients.admin.AdminClient; diff --git a/common/src/main/java/org/apache/atlas/utils/OnAtlasPropertyCondition.java b/common/src/main/java/org/apache/atlas/utils/OnAtlasPropertyCondition.java index 03e5493f683..92ff402282a 100644 --- a/common/src/main/java/org/apache/atlas/utils/OnAtlasPropertyCondition.java +++ b/common/src/main/java/org/apache/atlas/utils/OnAtlasPropertyCondition.java @@ -20,7 +20,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.annotation.ConditionalOnAtlasProperty; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/common/src/test/java/org/apache/atlas/ha/HAConfigurationTest.java b/common/src/test/java/org/apache/atlas/ha/HAConfigurationTest.java index 86d0a50d663..868d4390a38 100644 --- a/common/src/test/java/org/apache/atlas/ha/HAConfigurationTest.java +++ b/common/src/test/java/org/apache/atlas/ha/HAConfigurationTest.java @@ -20,7 +20,7 @@ import org.apache.atlas.AtlasConstants; import org.apache.atlas.security.SecurityProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; diff --git a/common/src/test/java/org/apache/atlas/utils/KafkaUtilsTest.java b/common/src/test/java/org/apache/atlas/utils/KafkaUtilsTest.java index dc6dc482550..3ed53d456e8 100644 --- a/common/src/test/java/org/apache/atlas/utils/KafkaUtilsTest.java +++ b/common/src/test/java/org/apache/atlas/utils/KafkaUtilsTest.java @@ -18,8 +18,8 @@ package org.apache.atlas.utils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.security.alias.CredentialProvider; import org.apache.hadoop.security.alias.CredentialProviderFactory; diff --git a/graphdb/common/src/test/java/org/apache/atlas/graph/GraphSandboxUtil.java b/graphdb/common/src/test/java/org/apache/atlas/graph/GraphSandboxUtil.java index 2d0e9f4a3aa..17d0e2f61b7 100644 --- a/graphdb/common/src/test/java/org/apache/atlas/graph/GraphSandboxUtil.java +++ b/graphdb/common/src/test/java/org/apache/atlas/graph/GraphSandboxUtil.java @@ -19,7 +19,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.testng.SkipException; diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java index e0d4857a1ca..2286231fab0 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraph.java @@ -45,7 +45,7 @@ import org.apache.atlas.repository.graphdb.janus.query.AtlasJanusGraphQuery; import org.apache.atlas.repository.graphdb.utils.IteratorToIterableAdapter; import org.apache.atlas.type.AtlasType; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.hadoop.util.StringUtils; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer; diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java index 8648fb6c137..186b817d4fa 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphDatabase.java @@ -29,8 +29,8 @@ import org.apache.atlas.repository.graphdb.janus.serializer.BigIntegerSerializer; import org.apache.atlas.repository.graphdb.janus.serializer.TypeCategorySerializer; import org.apache.atlas.typesystem.types.DataTypes.TypeCategory; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.JanusGraphException; diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java index 0c73fa5b2af..8b81d54ef5b 100644 --- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java +++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClient.java @@ -27,7 +27,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrQuery; diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java index 5ee4203f95e..c1d20567bef 100644 --- a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java +++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java @@ -32,7 +32,7 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.typesystem.types.DataTypes.TypeCategory; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.testng.annotations.AfterClass; import org.testng.annotations.Test; diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClientTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClientTest.java index 8f126f03971..6a3662fd5a4 100644 --- a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClientTest.java +++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphIndexClientTest.java @@ -22,7 +22,7 @@ import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.graphdb.AggregationContext; import org.apache.atlas.type.AtlasStructType.AtlasAttribute; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrResponse; diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTest.java index 7e0cdef4114..6d41759a278 100644 --- a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTest.java +++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphTest.java @@ -30,7 +30,7 @@ import org.apache.atlas.repository.graphdb.GremlinVersion; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.type.AtlasType; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java index 4d2deda52ba..877d8481a4c 100644 --- a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java +++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java @@ -22,7 +22,7 @@ import org.apache.atlas.graph.GraphSandboxUtil; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.runner.LocalSolrRunner; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; diff --git a/graphdb/janusgraph-rdbms/pom.xml b/graphdb/janusgraph-rdbms/pom.xml index d60a240cf3e..bf2f51a9b33 100644 --- a/graphdb/janusgraph-rdbms/pom.xml +++ b/graphdb/janusgraph-rdbms/pom.xml @@ -63,6 +63,10 @@ com.rabbitmq amqp-client + + commons-configuration + commons-configuration + org.noggit noggit diff --git a/intg/pom.xml b/intg/pom.xml index ae850e5601f..1efa271c01e 100644 --- a/intg/pom.xml +++ b/intg/pom.xml @@ -60,12 +60,6 @@ commons-collections - - commons-configuration - commons-configuration - ${commons-conf.version} - - commons-validator commons-validator diff --git a/intg/src/main/java/org/apache/atlas/ApplicationProperties.java b/intg/src/main/java/org/apache/atlas/ApplicationProperties.java index 40a6de05ae3..c14374081fe 100644 --- a/intg/src/main/java/org/apache/atlas/ApplicationProperties.java +++ b/intg/src/main/java/org/apache/atlas/ApplicationProperties.java @@ -18,10 +18,12 @@ package org.apache.atlas; import org.apache.atlas.security.SecurityUtil; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.convert.DefaultListDelimiterHandler; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,7 +86,10 @@ public final class ApplicationProperties extends PropertiesConfiguration { private static volatile Configuration instance; private ApplicationProperties(URL url) throws ConfigurationException { - super(url); + super(); + setListDelimiterHandler(new DefaultListDelimiterHandler(',')); + FileHandler fileHandler = new FileHandler(this); + fileHandler.load(url); } public static void forceReload() { diff --git a/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java b/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java index 51b8963c366..994945a6743 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java +++ b/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java @@ -18,7 +18,7 @@ package org.apache.atlas; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; /** diff --git a/intg/src/main/java/org/apache/atlas/security/InMemoryJAASConfiguration.java b/intg/src/main/java/org/apache/atlas/security/InMemoryJAASConfiguration.java index 196e0970f5d..bd9735fa7ba 100644 --- a/intg/src/main/java/org/apache/atlas/security/InMemoryJAASConfiguration.java +++ b/intg/src/main/java/org/apache/atlas/security/InMemoryJAASConfiguration.java @@ -20,7 +20,7 @@ import org.apache.atlas.AtlasException; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.ConfigurationConverter; import org.apache.commons.lang3.ArrayUtils; import org.apache.hadoop.security.SecurityUtil; import org.slf4j.Logger; @@ -180,7 +180,7 @@ public static void init(String propFile) throws AtlasException { LOG.debug("<== InMemoryJAASConfiguration.init({})", propFile); } - public static void init(org.apache.commons.configuration.Configuration atlasConfiguration) throws AtlasException { + public static void init(org.apache.commons.configuration2.Configuration atlasConfiguration) throws AtlasException { LOG.debug("==> InMemoryJAASConfiguration.init()"); if (atlasConfiguration != null && !atlasConfiguration.isEmpty()) { diff --git a/intg/src/main/java/org/apache/atlas/security/SecurityUtil.java b/intg/src/main/java/org/apache/atlas/security/SecurityUtil.java index 730595e7961..7db2ab703ce 100644 --- a/intg/src/main/java/org/apache/atlas/security/SecurityUtil.java +++ b/intg/src/main/java/org/apache/atlas/security/SecurityUtil.java @@ -42,7 +42,7 @@ private SecurityUtil() { * @return the password. * @throws IOException */ - public static String getPassword(org.apache.commons.configuration.Configuration config, String key) throws IOException { + public static String getPassword(org.apache.commons.configuration2.Configuration config, String key) throws IOException { return getPassword(config, key, CERT_STORES_CREDENTIAL_PROVIDER_PATH); } @@ -56,7 +56,7 @@ public static String getPassword(org.apache.commons.configuration.Configuration * @return the password. * @throws IOException */ - public static String getPassword(org.apache.commons.configuration.Configuration config, String key, String pathPropertyName) throws IOException { + public static String getPassword(org.apache.commons.configuration2.Configuration config, String key, String pathPropertyName) throws IOException { String password; String provider = config.getString(pathPropertyName); diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java index 6197df3724f..b8a5ffe356e 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java @@ -29,7 +29,7 @@ import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/intg/src/main/java/org/apache/atlas/utils/AtlasConfigurationUtil.java b/intg/src/main/java/org/apache/atlas/utils/AtlasConfigurationUtil.java index 3b69b755dd6..681284224dc 100644 --- a/intg/src/main/java/org/apache/atlas/utils/AtlasConfigurationUtil.java +++ b/intg/src/main/java/org/apache/atlas/utils/AtlasConfigurationUtil.java @@ -17,7 +17,7 @@ */ package org.apache.atlas.utils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; public class AtlasConfigurationUtil { private AtlasConfigurationUtil() { diff --git a/intg/src/main/java/org/apache/atlas/utils/AuthenticationUtil.java b/intg/src/main/java/org/apache/atlas/utils/AuthenticationUtil.java index 932de5a1ea9..d98de2812f9 100644 --- a/intg/src/main/java/org/apache/atlas/utils/AuthenticationUtil.java +++ b/intg/src/main/java/org/apache/atlas/utils/AuthenticationUtil.java @@ -19,7 +19,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/intg/src/main/java/org/apache/atlas/utils/SSLUtil.java b/intg/src/main/java/org/apache/atlas/utils/SSLUtil.java index 33a38508964..5168ec72b77 100644 --- a/intg/src/main/java/org/apache/atlas/utils/SSLUtil.java +++ b/intg/src/main/java/org/apache/atlas/utils/SSLUtil.java @@ -21,7 +21,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.security.SecurityProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/intg/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java b/intg/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java index 38b66f3be4d..8060f5e00b2 100644 --- a/intg/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java +++ b/intg/src/test/java/org/apache/atlas/ApplicationPropertiesTest.java @@ -18,8 +18,8 @@ package org.apache.atlas; import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.testng.annotations.Test; import java.io.InputStream; diff --git a/intg/src/test/java/org/apache/atlas/utils/AtlasConfigurationUtilTest.java b/intg/src/test/java/org/apache/atlas/utils/AtlasConfigurationUtilTest.java index a8cd153c091..58c585b864d 100644 --- a/intg/src/test/java/org/apache/atlas/utils/AtlasConfigurationUtilTest.java +++ b/intg/src/test/java/org/apache/atlas/utils/AtlasConfigurationUtilTest.java @@ -17,8 +17,8 @@ */ package org.apache.atlas.utils; -import org.apache.commons.configuration.BaseConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.BaseConfiguration; +import org.apache.commons.configuration2.Configuration; import org.testng.annotations.Test; import java.lang.reflect.Constructor; diff --git a/intg/src/test/java/org/apache/atlas/utils/AuthenticationUtilTest.java b/intg/src/test/java/org/apache/atlas/utils/AuthenticationUtilTest.java index b70db4d060b..a0e7457dac4 100644 --- a/intg/src/test/java/org/apache/atlas/utils/AuthenticationUtilTest.java +++ b/intg/src/test/java/org/apache/atlas/utils/AuthenticationUtilTest.java @@ -17,8 +17,8 @@ */ package org.apache.atlas.utils; -import org.apache.commons.configuration.BaseConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.BaseConfiguration; +import org.apache.commons.configuration2.Configuration; import org.apache.hadoop.security.UserGroupInformation; import org.testng.annotations.Test; diff --git a/intg/src/test/java/org/apache/atlas/utils/SSLUtilTest.java b/intg/src/test/java/org/apache/atlas/utils/SSLUtilTest.java index 4770f8908eb..22cae97c4e0 100644 --- a/intg/src/test/java/org/apache/atlas/utils/SSLUtilTest.java +++ b/intg/src/test/java/org/apache/atlas/utils/SSLUtilTest.java @@ -18,8 +18,8 @@ package org.apache.atlas.utils; import org.apache.atlas.security.SecurityProperties; -import org.apache.commons.configuration.BaseConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.BaseConfiguration; +import org.apache.commons.configuration2.Configuration; import org.testng.annotations.Test; import java.io.IOException; diff --git a/intg/src/test/java/org/apache/atlas/utils/TestAtlasAsyncImportTestUtil.java b/intg/src/test/java/org/apache/atlas/utils/TestAtlasAsyncImportTestUtil.java index 21904be789f..c453a832891 100644 --- a/intg/src/test/java/org/apache/atlas/utils/TestAtlasAsyncImportTestUtil.java +++ b/intg/src/test/java/org/apache/atlas/utils/TestAtlasAsyncImportTestUtil.java @@ -22,7 +22,7 @@ import org.apache.atlas.model.impexp.AtlasAsyncImportRequest; import org.apache.atlas.model.impexp.AtlasImportRequest; import org.apache.atlas.model.impexp.AtlasImportResult; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; diff --git a/notification/pom.xml b/notification/pom.xml index f2f6cd8a992..3ce97ba85eb 100644 --- a/notification/pom.xml +++ b/notification/pom.xml @@ -129,9 +129,9 @@ ${commons-logging.version} - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} commons-collections diff --git a/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java b/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java index 74e536b2a85..ed4ad538706 100644 --- a/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java +++ b/notification/src/main/java/org/apache/atlas/hook/AtlasHook.java @@ -32,7 +32,7 @@ import org.apache.atlas.notification.NotificationInterface; import org.apache.atlas.utils.AtlasConfigurationUtil; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.ShutdownHookManager; diff --git a/notification/src/main/java/org/apache/atlas/hook/AtlasTopicCreator.java b/notification/src/main/java/org/apache/atlas/hook/AtlasTopicCreator.java index 33da4f8048a..6ae5b27e34d 100644 --- a/notification/src/main/java/org/apache/atlas/hook/AtlasTopicCreator.java +++ b/notification/src/main/java/org/apache/atlas/hook/AtlasTopicCreator.java @@ -23,7 +23,7 @@ import org.apache.atlas.AtlasException; import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.utils.KafkaUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; diff --git a/notification/src/main/java/org/apache/atlas/kafka/EmbeddedKafkaServer.java b/notification/src/main/java/org/apache/atlas/kafka/EmbeddedKafkaServer.java index ee87763528b..23158f521b7 100644 --- a/notification/src/main/java/org/apache/atlas/kafka/EmbeddedKafkaServer.java +++ b/notification/src/main/java/org/apache/atlas/kafka/EmbeddedKafkaServer.java @@ -24,8 +24,8 @@ import org.apache.atlas.AtlasException; import org.apache.atlas.service.Service; import org.apache.atlas.util.CommandHandlerUtility; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.common.KafkaException; import org.apache.kafka.common.utils.Time; diff --git a/notification/src/main/java/org/apache/atlas/kafka/KafkaNotification.java b/notification/src/main/java/org/apache/atlas/kafka/KafkaNotification.java index 630fe6250c4..a72645f8c5f 100644 --- a/notification/src/main/java/org/apache/atlas/kafka/KafkaNotification.java +++ b/notification/src/main/java/org/apache/atlas/kafka/KafkaNotification.java @@ -28,8 +28,8 @@ import org.apache.atlas.notification.NotificationException; import org.apache.atlas.service.Service; import org.apache.atlas.utils.KafkaUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.apache.commons.lang3.StringUtils; import org.apache.kafka.clients.admin.AdminClient; import org.apache.kafka.clients.consumer.ConsumerConfig; diff --git a/notification/src/main/java/org/apache/atlas/kafka/NotificationProvider.java b/notification/src/main/java/org/apache/atlas/kafka/NotificationProvider.java index b356977dc7d..eed7532a15b 100644 --- a/notification/src/main/java/org/apache/atlas/kafka/NotificationProvider.java +++ b/notification/src/main/java/org/apache/atlas/kafka/NotificationProvider.java @@ -25,7 +25,7 @@ import org.apache.atlas.notification.NotificationInterface; import org.apache.atlas.notification.rest.RestNotification; import org.apache.atlas.notification.spool.AtlasFileSpool; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/notification/src/main/java/org/apache/atlas/notification/AbstractNotification.java b/notification/src/main/java/org/apache/atlas/notification/AbstractNotification.java index 8a6b3a3f331..8e9eca9d6e6 100644 --- a/notification/src/main/java/org/apache/atlas/notification/AbstractNotification.java +++ b/notification/src/main/java/org/apache/atlas/notification/AbstractNotification.java @@ -26,7 +26,7 @@ import org.apache.atlas.model.notification.MessageSource; import org.apache.atlas.model.notification.MessageVersion; import org.apache.atlas.type.AtlasType; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java b/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java index cfbae5f26b2..e5bab47f8f7 100644 --- a/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java +++ b/notification/src/main/java/org/apache/atlas/notification/rest/RestNotification.java @@ -28,7 +28,7 @@ import org.apache.atlas.notification.NotificationConsumer; import org.apache.atlas.notification.NotificationException; import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.NotImplementedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/notification/src/main/java/org/apache/atlas/notification/spool/AtlasFileSpool.java b/notification/src/main/java/org/apache/atlas/notification/spool/AtlasFileSpool.java index 8f102e180a7..ff622cd4684 100644 --- a/notification/src/main/java/org/apache/atlas/notification/spool/AtlasFileSpool.java +++ b/notification/src/main/java/org/apache/atlas/notification/spool/AtlasFileSpool.java @@ -24,7 +24,7 @@ import org.apache.atlas.notification.NotificationConsumer; import org.apache.atlas.notification.NotificationException; import org.apache.atlas.notification.NotificationInterface; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/notification/src/main/java/org/apache/atlas/notification/spool/SpoolConfiguration.java b/notification/src/main/java/org/apache/atlas/notification/spool/SpoolConfiguration.java index b1bd4e68928..af1fc746f78 100644 --- a/notification/src/main/java/org/apache/atlas/notification/spool/SpoolConfiguration.java +++ b/notification/src/main/java/org/apache/atlas/notification/spool/SpoolConfiguration.java @@ -17,7 +17,7 @@ */ package org.apache.atlas.notification.spool; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import java.io.File; diff --git a/notification/src/test/java/org/apache/atlas/hook/AtlasTopicCreatorTest.java b/notification/src/test/java/org/apache/atlas/hook/AtlasTopicCreatorTest.java index b6acf9b3829..233bf9be851 100644 --- a/notification/src/test/java/org/apache/atlas/hook/AtlasTopicCreatorTest.java +++ b/notification/src/test/java/org/apache/atlas/hook/AtlasTopicCreatorTest.java @@ -20,7 +20,7 @@ import org.apache.atlas.AtlasConfiguration; import org.apache.atlas.utils.KafkaUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mockito; import org.testng.annotations.Test; diff --git a/notification/src/test/java/org/apache/atlas/kafka/KafkaNotificationTest.java b/notification/src/test/java/org/apache/atlas/kafka/KafkaNotificationTest.java index 34c6733c0d6..2442b7c83b1 100644 --- a/notification/src/test/java/org/apache/atlas/kafka/KafkaNotificationTest.java +++ b/notification/src/test/java/org/apache/atlas/kafka/KafkaNotificationTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.notification.NotificationInterface; import org.apache.atlas.v1.model.instance.Referenceable; import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityCreateRequest; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.RandomStringUtils; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; diff --git a/notification/src/test/java/org/apache/atlas/notification/AbstractNotificationTest.java b/notification/src/test/java/org/apache/atlas/notification/AbstractNotificationTest.java index 93e86256d9f..f284110ad77 100644 --- a/notification/src/test/java/org/apache/atlas/notification/AbstractNotificationTest.java +++ b/notification/src/test/java/org/apache/atlas/notification/AbstractNotificationTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.model.notification.MessageSource; import org.apache.atlas.notification.NotificationInterface.NotificationType; import org.apache.atlas.type.AtlasType; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import java.util.ArrayList; import java.util.Arrays; diff --git a/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java b/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java index 43d32a9f161..e35e23c7890 100644 --- a/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java +++ b/notification/src/test/java/org/apache/atlas/notification/RestNotificationTest.java @@ -27,7 +27,7 @@ import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.kafka.NotificationProvider; import org.apache.atlas.notification.rest.RestNotification; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; diff --git a/notification/src/test/java/org/apache/atlas/notification/spool/BaseTest.java b/notification/src/test/java/org/apache/atlas/notification/spool/BaseTest.java index 2dff8ccf18c..7c64dcb6717 100644 --- a/notification/src/test/java/org/apache/atlas/notification/spool/BaseTest.java +++ b/notification/src/test/java/org/apache/atlas/notification/spool/BaseTest.java @@ -17,8 +17,8 @@ */ package org.apache.atlas.notification.spool; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.io.FileUtils; import java.io.File; diff --git a/pom.xml b/pom.xml index af23e06eae4..a48b50536cc 100644 --- a/pom.xml +++ b/pom.xml @@ -98,7 +98,6 @@ 1.14 3.2.2 4.4 - 1.10 2.10.1 1.0 2.17.0 @@ -348,13 +347,6 @@ ${commons-collections.version} - - - commons-configuration - commons-configuration - ${commons-conf.version} - - commons-el commons-el diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/AbstractStorageBasedAuditRepository.java b/repository/src/main/java/org/apache/atlas/repository/audit/AbstractStorageBasedAuditRepository.java index 06bc461e5e3..b7f7cd29f8e 100644 --- a/repository/src/main/java/org/apache/atlas/repository/audit/AbstractStorageBasedAuditRepository.java +++ b/repository/src/main/java/org/apache/atlas/repository/audit/AbstractStorageBasedAuditRepository.java @@ -26,8 +26,8 @@ import org.apache.atlas.model.audit.EntityAuditEventV2; import org.apache.atlas.service.Service; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hbase.util.Bytes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/AtlasAuditReductionService.java b/repository/src/main/java/org/apache/atlas/repository/audit/AtlasAuditReductionService.java index 3781c8cd84b..45e0a5d97be 100644 --- a/repository/src/main/java/org/apache/atlas/repository/audit/AtlasAuditReductionService.java +++ b/repository/src/main/java/org/apache/atlas/repository/audit/AtlasAuditReductionService.java @@ -28,7 +28,7 @@ import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.slf4j.Logger; diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/HBaseBasedAuditRepository.java b/repository/src/main/java/org/apache/atlas/repository/audit/HBaseBasedAuditRepository.java index 544bb5ce15d..c9a2a1ca314 100644 --- a/repository/src/main/java/org/apache/atlas/repository/audit/HBaseBasedAuditRepository.java +++ b/repository/src/main/java/org/apache/atlas/repository/audit/HBaseBasedAuditRepository.java @@ -32,7 +32,7 @@ import org.apache.atlas.repository.Constants.AtlasAuditAgingType; import org.apache.atlas.utils.AtlasPerfMetrics; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.HColumnDescriptor; diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java b/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java index 523da3d618d..206e22be9ef 100644 --- a/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java +++ b/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java @@ -31,8 +31,8 @@ import org.apache.atlas.repository.audit.rdbms.entity.DbEntityAudit; import org.apache.atlas.utils.AtlasPerfMetrics; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/AtlasGraphProvider.java b/repository/src/main/java/org/apache/atlas/repository/graph/AtlasGraphProvider.java index 2df405b9f72..51ae8b3c8a3 100755 --- a/repository/src/main/java/org/apache/atlas/repository/graph/AtlasGraphProvider.java +++ b/repository/src/main/java/org/apache/atlas/repository/graph/AtlasGraphProvider.java @@ -44,7 +44,7 @@ public class AtlasGraphProvider implements IAtlasGraphProvider { private static final Long RETRY_SLEEP_TIME_MS = getRetrySleepTime(); private static volatile GraphDatabase graphDb; - private static org.apache.commons.configuration.Configuration applicationProperties; + private static org.apache.commons.configuration2.Configuration applicationProperties; public static AtlasGraph getGraphInstance() { GraphDatabase db = getGraphDatabase(); diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/FullTextMapperV2.java b/repository/src/main/java/org/apache/atlas/repository/graph/FullTextMapperV2.java index 6d2d25c3889..7b03a5270a4 100644 --- a/repository/src/main/java/org/apache/atlas/repository/graph/FullTextMapperV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/graph/FullTextMapperV2.java @@ -37,7 +37,7 @@ import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java index 721548d8d98..addeb3d0c8d 100755 --- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java +++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java @@ -58,7 +58,7 @@ import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeUtil; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/IndexRecoveryService.java b/repository/src/main/java/org/apache/atlas/repository/graph/IndexRecoveryService.java index 654af40dfdd..68e8101b3b6 100644 --- a/repository/src/main/java/org/apache/atlas/repository/graph/IndexRecoveryService.java +++ b/repository/src/main/java/org/apache/atlas/repository/graph/IndexRecoveryService.java @@ -28,7 +28,7 @@ import org.apache.atlas.repository.graphdb.AtlasGraphQuery; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.service.Service; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/MigrationProgressService.java b/repository/src/main/java/org/apache/atlas/repository/impexp/MigrationProgressService.java index 41fbf910f69..2e79c69f170 100644 --- a/repository/src/main/java/org/apache/atlas/repository/impexp/MigrationProgressService.java +++ b/repository/src/main/java/org/apache/atlas/repository/impexp/MigrationProgressService.java @@ -26,7 +26,7 @@ import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.repository.graphdb.GraphDBMigrator; import org.apache.atlas.repository.migration.DataMigrationStatusService; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/migration/DataMigrationService.java b/repository/src/main/java/org/apache/atlas/repository/migration/DataMigrationService.java index 69218275d92..3b81390ff67 100644 --- a/repository/src/main/java/org/apache/atlas/repository/migration/DataMigrationService.java +++ b/repository/src/main/java/org/apache/atlas/repository/migration/DataMigrationService.java @@ -30,7 +30,7 @@ import org.apache.atlas.service.Service; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/repository/src/main/java/org/apache/atlas/repository/patches/AtlasPatchService.java b/repository/src/main/java/org/apache/atlas/repository/patches/AtlasPatchService.java index 5be9166940d..7888e0e47c1 100644 --- a/repository/src/main/java/org/apache/atlas/repository/patches/AtlasPatchService.java +++ b/repository/src/main/java/org/apache/atlas/repository/patches/AtlasPatchService.java @@ -22,7 +22,7 @@ import org.apache.atlas.ha.HAConfiguration; import org.apache.atlas.listener.ActiveStateChangeHandler; import org.apache.atlas.service.Service; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; diff --git a/repository/src/main/java/org/apache/atlas/repository/patches/ConcurrentPatchProcessor.java b/repository/src/main/java/org/apache/atlas/repository/patches/ConcurrentPatchProcessor.java index 2a85e5898fa..efa1f937d18 100644 --- a/repository/src/main/java/org/apache/atlas/repository/patches/ConcurrentPatchProcessor.java +++ b/repository/src/main/java/org/apache/atlas/repository/patches/ConcurrentPatchProcessor.java @@ -29,7 +29,7 @@ import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/patches/EdgePatchProcessor.java b/repository/src/main/java/org/apache/atlas/repository/patches/EdgePatchProcessor.java index b09917a5f11..514189c77f4 100644 --- a/repository/src/main/java/org/apache/atlas/repository/patches/EdgePatchProcessor.java +++ b/repository/src/main/java/org/apache/atlas/repository/patches/EdgePatchProcessor.java @@ -27,7 +27,7 @@ import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.type.AtlasRelationshipType; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializer.java b/repository/src/main/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializer.java index a7c78b1356b..ff10d8e7102 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializer.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializer.java @@ -57,7 +57,7 @@ import org.apache.atlas.type.AtlasTypeUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java index 36881cecfc7..fe953486bef 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasGraphUtilsV2.java @@ -48,7 +48,7 @@ import org.apache.atlas.utils.AtlasPerfMetrics.MetricRecorder; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/AuditReductionTaskFactory.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/AuditReductionTaskFactory.java index b70e4eedfb8..c1c99b06195 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/AuditReductionTaskFactory.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/AuditReductionTaskFactory.java @@ -26,7 +26,7 @@ import org.apache.atlas.tasks.AbstractTask; import org.apache.atlas.tasks.TaskFactory; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTask.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTask.java index 0d60f36a5e5..63bbf895d25 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTask.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTask.java @@ -34,7 +34,7 @@ import org.apache.atlas.utils.AtlasJson; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTaskFactory.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTaskFactory.java index 358b7e41c61..fdf47ee1e22 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTaskFactory.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/tasks/searchdownload/SearchResultDownloadTaskFactory.java @@ -23,7 +23,7 @@ import org.apache.atlas.tasks.AbstractTask; import org.apache.atlas.tasks.TaskFactory; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/main/java/org/apache/atlas/services/PurgeService.java b/repository/src/main/java/org/apache/atlas/services/PurgeService.java index 8f5de1f7252..bc89aad8bfd 100644 --- a/repository/src/main/java/org/apache/atlas/services/PurgeService.java +++ b/repository/src/main/java/org/apache/atlas/services/PurgeService.java @@ -40,7 +40,7 @@ import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.utils.AtlasPerfTracer; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; diff --git a/repository/src/main/java/org/apache/atlas/tasks/TaskManagement.java b/repository/src/main/java/org/apache/atlas/tasks/TaskManagement.java index 113f2b1b234..47bf49541a8 100644 --- a/repository/src/main/java/org/apache/atlas/tasks/TaskManagement.java +++ b/repository/src/main/java/org/apache/atlas/tasks/TaskManagement.java @@ -25,7 +25,7 @@ import org.apache.atlas.listener.ActiveStateChangeHandler; import org.apache.atlas.model.tasks.AtlasTask; import org.apache.atlas.service.Service; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; diff --git a/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java b/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java index 0f940620032..cf8fef41be3 100644 --- a/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java +++ b/repository/src/main/java/org/apache/atlas/util/AtlasRepositoryConfiguration.java @@ -24,7 +24,7 @@ import org.apache.atlas.repository.graphdb.GraphDatabase; import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/test/java/org/apache/atlas/TestModules.java b/repository/src/test/java/org/apache/atlas/TestModules.java index 60273bc33e1..ee3e8d68d99 100644 --- a/repository/src/test/java/org/apache/atlas/TestModules.java +++ b/repository/src/test/java/org/apache/atlas/TestModules.java @@ -76,7 +76,7 @@ import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.util.AtlasRepositoryConfiguration; import org.apache.atlas.util.SearchTracker; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/repository/src/test/java/org/apache/atlas/repository/audit/AtlasAuditReductionServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/audit/AtlasAuditReductionServiceTest.java index a4f061dd070..db16c41678d 100644 --- a/repository/src/test/java/org/apache/atlas/repository/audit/AtlasAuditReductionServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/audit/AtlasAuditReductionServiceTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.repository.Constants.AtlasAuditAgingType; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; diff --git a/repository/src/test/java/org/apache/atlas/repository/audit/CassandraAuditRepositoryTest.java b/repository/src/test/java/org/apache/atlas/repository/audit/CassandraAuditRepositoryTest.java index 75fc9254138..ea55779600f 100644 --- a/repository/src/test/java/org/apache/atlas/repository/audit/CassandraAuditRepositoryTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/audit/CassandraAuditRepositoryTest.java @@ -20,8 +20,8 @@ import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.MapConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.MapConfiguration; import org.cassandraunit.utils.EmbeddedCassandraServerHelper; import org.testng.SkipException; import org.testng.annotations.BeforeClass; diff --git a/repository/src/test/java/org/apache/atlas/repository/migration/DataMigrationServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/migration/DataMigrationServiceTest.java index f23a96527ec..0c276ebf942 100644 --- a/repository/src/test/java/org/apache/atlas/repository/migration/DataMigrationServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/migration/DataMigrationServiceTest.java @@ -27,7 +27,7 @@ import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.mockito.ArgumentMatchers; import org.mockito.Mock; diff --git a/repository/src/test/java/org/apache/atlas/repository/migration/MigrationProgressServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/migration/MigrationProgressServiceTest.java index 5263e8db504..4cea5180c28 100644 --- a/repository/src/test/java/org/apache/atlas/repository/migration/MigrationProgressServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/migration/MigrationProgressServiceTest.java @@ -21,7 +21,7 @@ import org.apache.atlas.repository.graphdb.GraphDBMigrator; import org.apache.atlas.repository.graphdb.janus.migration.ReaderStatusManager; import org.apache.atlas.repository.impexp.MigrationProgressService; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; import org.testng.annotations.Test; diff --git a/repository/src/test/java/org/apache/atlas/repository/patches/AtlasPatchServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/patches/AtlasPatchServiceTest.java index 215fbc968fa..e916ebba00f 100644 --- a/repository/src/test/java/org/apache/atlas/repository/patches/AtlasPatchServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/patches/AtlasPatchServiceTest.java @@ -21,7 +21,7 @@ import org.apache.atlas.AtlasException; import org.apache.atlas.ha.HAConfiguration; import org.apache.atlas.listener.ActiveStateChangeHandler; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/repository/src/test/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializerTest.java b/repository/src/test/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializerTest.java index 99cab83ab56..c7ceacacb67 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializerTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/bootstrap/AtlasTypeDefStoreInitializerTest.java @@ -47,7 +47,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute; import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasTypeRegistry; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/server-api/src/main/java/org/apache/atlas/ha/AtlasServerIdSelector.java b/server-api/src/main/java/org/apache/atlas/ha/AtlasServerIdSelector.java index a30228e939c..2a664156732 100644 --- a/server-api/src/main/java/org/apache/atlas/ha/AtlasServerIdSelector.java +++ b/server-api/src/main/java/org/apache/atlas/ha/AtlasServerIdSelector.java @@ -20,7 +20,7 @@ import org.apache.atlas.AtlasConstants; import org.apache.atlas.AtlasException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.net.NetUtils; import org.slf4j.Logger; diff --git a/server-api/src/test/java/org/apache/atlas/ha/AtlasServerIdSelectorTest.java b/server-api/src/test/java/org/apache/atlas/ha/AtlasServerIdSelectorTest.java index c99e0eeb361..0ccbdad98d6 100644 --- a/server-api/src/test/java/org/apache/atlas/ha/AtlasServerIdSelectorTest.java +++ b/server-api/src/test/java/org/apache/atlas/ha/AtlasServerIdSelectorTest.java @@ -20,7 +20,7 @@ import org.apache.atlas.AtlasConstants; import org.apache.atlas.AtlasException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; diff --git a/test-tools/pom.xml b/test-tools/pom.xml index c06194b6370..cffd391c666 100644 --- a/test-tools/pom.xml +++ b/test-tools/pom.xml @@ -36,12 +36,6 @@ - - - commons-configuration - commons-configuration - - commons-fileupload commons-fileupload diff --git a/test-tools/src/main/java/org/apache/atlas/runner/LocalSolrRunner.java b/test-tools/src/main/java/org/apache/atlas/runner/LocalSolrRunner.java index b98a3429355..828b9e74303 100644 --- a/test-tools/src/main/java/org/apache/atlas/runner/LocalSolrRunner.java +++ b/test-tools/src/main/java/org/apache/atlas/runner/LocalSolrRunner.java @@ -19,7 +19,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ArrayUtils; diff --git a/tools/atlas-index-repair/pom.xml b/tools/atlas-index-repair/pom.xml index e99eda9ffe0..fcddaa7a468 100644 --- a/tools/atlas-index-repair/pom.xml +++ b/tools/atlas-index-repair/pom.xml @@ -58,6 +58,10 @@ com.rabbitmq amqp-client + + commons-configuration + commons-configuration + org.noggit noggit diff --git a/tools/atlas-index-repair/src/main/java/org/apache/atlas/tools/RepairIndex.java b/tools/atlas-index-repair/src/main/java/org/apache/atlas/tools/RepairIndex.java index f3992ebff3f..ea2ab330db8 100644 --- a/tools/atlas-index-repair/src/main/java/org/apache/atlas/tools/RepairIndex.java +++ b/tools/atlas-index-repair/src/main/java/org/apache/atlas/tools/RepairIndex.java @@ -32,7 +32,7 @@ import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.janusgraph.core.JanusGraph; import org.janusgraph.core.schema.JanusGraphIndex; import org.janusgraph.core.schema.SchemaAction; diff --git a/tools/classification-updater/src/main/java/org/apache/atlas/tools/BulkFetchAndUpdate.java b/tools/classification-updater/src/main/java/org/apache/atlas/tools/BulkFetchAndUpdate.java index e554f541444..a4eb06fd90c 100644 --- a/tools/classification-updater/src/main/java/org/apache/atlas/tools/BulkFetchAndUpdate.java +++ b/tools/classification-updater/src/main/java/org/apache/atlas/tools/BulkFetchAndUpdate.java @@ -38,7 +38,7 @@ import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.UserGroupInformation; import org.slf4j.Logger; diff --git a/tools/notification-analyzer/pom.xml b/tools/notification-analyzer/pom.xml index 70f54196585..bb0ec85b955 100644 --- a/tools/notification-analyzer/pom.xml +++ b/tools/notification-analyzer/pom.xml @@ -125,9 +125,9 @@ 1.26.2 - commons-configuration - commons-configuration - ${commons-conf.version} + org.apache.commons + commons-configuration2 + ${commons-conf2.version} commons-logging diff --git a/webapp/pom.xml b/webapp/pom.xml index 07c4186a90a..d0ce93d4dba 100755 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -116,11 +116,6 @@ commons-cli - - commons-configuration - commons-configuration - - commons-io commons-io diff --git a/webapp/src/main/java/org/apache/atlas/Atlas.java b/webapp/src/main/java/org/apache/atlas/Atlas.java index 07f4c30fab1..4f73d368b67 100755 --- a/webapp/src/main/java/org/apache/atlas/Atlas.java +++ b/webapp/src/main/java/org/apache/atlas/Atlas.java @@ -25,8 +25,9 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.util.ShutdownHookManager; import org.slf4j.Logger; @@ -64,7 +65,9 @@ private Atlas() { public static void main(String[] args) throws Exception { CommandLine cmd = parseArgs(args); - PropertiesConfiguration buildConfiguration = new PropertiesConfiguration("atlas-buildinfo.properties"); + PropertiesConfiguration buildConfiguration = new PropertiesConfiguration(); + FileHandler fileHandler = new FileHandler(buildConfiguration); + fileHandler.load("atlas-buildinfo.properties"); String appPath = "webapp/target/atlas-webapp-" + getProjectVersion(buildConfiguration); if (cmd.hasOption(APP_PATH)) { diff --git a/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java b/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java index ad6d54d4436..fdb96a4a1fd 100755 --- a/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java +++ b/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java @@ -37,7 +37,7 @@ import org.apache.atlas.v1.model.typedef.TraitTypeDefinition; import org.apache.atlas.v1.model.typedef.TypesDef; import org.apache.atlas.v1.typesystem.types.utils.TypesUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import java.util.Arrays; import java.util.Collections; diff --git a/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java b/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java index c1cef5a6744..a43cfc6390d 100755 --- a/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java +++ b/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java @@ -48,7 +48,7 @@ import org.apache.atlas.type.AtlasTypeUtil; import org.apache.atlas.utils.AuthenticationUtil; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ArrayUtils; import javax.ws.rs.core.MultivaluedMap; diff --git a/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java b/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java index 3906c9e5695..fbb7d7880cd 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java +++ b/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java @@ -37,7 +37,7 @@ import org.apache.atlas.utils.AtlasPerfMetrics.MetricRecorder; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.springframework.stereotype.Component; import javax.inject.Inject; diff --git a/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationSender.java b/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationSender.java index 3aba146101d..50ea50289a6 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationSender.java +++ b/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationSender.java @@ -19,7 +19,7 @@ import org.apache.atlas.GraphTransactionInterceptor; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java b/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java index cce6c20124b..1c04b432a28 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java +++ b/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java @@ -30,7 +30,7 @@ import org.apache.atlas.repository.impexp.AsyncImportService; import org.apache.atlas.repository.store.graph.v2.asyncimport.ImportTaskListener; import org.apache.atlas.service.Service; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/main/java/org/apache/atlas/notification/NotificationEntityChangeListener.java b/webapp/src/main/java/org/apache/atlas/notification/NotificationEntityChangeListener.java index fcdf42aab86..85e603dfc80 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/NotificationEntityChangeListener.java +++ b/webapp/src/main/java/org/apache/atlas/notification/NotificationEntityChangeListener.java @@ -32,7 +32,7 @@ import org.apache.atlas.v1.model.notification.EntityNotificationV1.OperationType; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.springframework.stereotype.Component; import javax.inject.Inject; diff --git a/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java b/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java index 32bf3016673..c30b652da96 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java +++ b/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java @@ -78,7 +78,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.collections4.map.PassiveExpiringMap; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.kafka.common.TopicPartition; import org.slf4j.Logger; diff --git a/webapp/src/main/java/org/apache/atlas/web/dao/UserDao.java b/webapp/src/main/java/org/apache/atlas/web/dao/UserDao.java index 89c768800ae..67faea6ff95 100644 --- a/webapp/src/main/java/org/apache/atlas/web/dao/UserDao.java +++ b/webapp/src/main/java/org/apache/atlas/web/dao/UserDao.java @@ -22,7 +22,7 @@ import org.apache.atlas.AtlasException; import org.apache.atlas.web.model.User; import org.apache.atlas.web.security.AtlasAuthenticationException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.AuthenticationException; diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java index 652af3a86ec..bc477f76242 100644 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasAuthenticationFilter.java @@ -25,8 +25,8 @@ import org.apache.atlas.web.security.AtlasAuthenticationProvider; import org.apache.atlas.web.util.Servlets; import org.apache.commons.collections.iterators.IteratorEnumeration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasCSRFPreventionFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasCSRFPreventionFilter.java index 7dc12acc37e..44e9b55b01c 100644 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasCSRFPreventionFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasCSRFPreventionFilter.java @@ -20,7 +20,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.json.simple.JSONObject; import org.slf4j.Logger; diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilter.java index a5dca7aaeea..c41f9d4686f 100644 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilter.java @@ -27,7 +27,7 @@ import com.nimbusds.jwt.SignedJWT; import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.security.AtlasAuthenticationProvider; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.utils.URIBuilder; import org.json.simple.JSONObject; diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java index 12d34353ba9..207879c7a67 100755 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java @@ -26,7 +26,7 @@ import org.apache.atlas.util.AtlasRepositoryConfiguration; import org.apache.atlas.web.util.DateTimeHelper; import org.apache.atlas.web.util.Servlets; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/HeadersUtil.java b/webapp/src/main/java/org/apache/atlas/web/filters/HeadersUtil.java index dbec3cdbfab..421250c38de 100644 --- a/webapp/src/main/java/org/apache/atlas/web/filters/HeadersUtil.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/HeadersUtil.java @@ -20,8 +20,8 @@ import com.google.common.annotations.VisibleForTesting; import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/main/java/org/apache/atlas/web/listeners/LoginProcessor.java b/webapp/src/main/java/org/apache/atlas/web/listeners/LoginProcessor.java index e8a198e3399..e7c926716af 100644 --- a/webapp/src/main/java/org/apache/atlas/web/listeners/LoginProcessor.java +++ b/webapp/src/main/java/org/apache/atlas/web/listeners/LoginProcessor.java @@ -49,7 +49,7 @@ public void login() { // first, let's see if we're running in a hadoop cluster and have the env configured boolean isHadoopCluster = isHadoopCluster(); Configuration hadoopConfig = isHadoopCluster ? getHadoopConfiguration() : new Configuration(false); - org.apache.commons.configuration.Configuration configuration = getApplicationConfiguration(); + org.apache.commons.configuration2.Configuration configuration = getApplicationConfiguration(); if (!isHadoopCluster) { // need to read the configured authentication choice and create the UGI configuration @@ -59,7 +59,7 @@ public void login() { doServiceLogin(hadoopConfig, configuration); } - protected void doServiceLogin(Configuration hadoopConfig, org.apache.commons.configuration.Configuration configuration) { + protected void doServiceLogin(Configuration hadoopConfig, org.apache.commons.configuration2.Configuration configuration) { UserGroupInformation.setConfiguration(hadoopConfig); UserGroupInformation.AuthenticationMethod authenticationMethod = SecurityUtil.getAuthenticationMethod(hadoopConfig); @@ -78,7 +78,7 @@ protected void doServiceLogin(Configuration hadoopConfig, org.apache.commons.con } } - protected void setupHadoopConfiguration(Configuration hadoopConfig, org.apache.commons.configuration.Configuration configuration) { + protected void setupHadoopConfiguration(Configuration hadoopConfig, org.apache.commons.configuration2.Configuration configuration) { String authMethod = ""; String kerberosAuthNEnabled = configuration != null ? configuration.getString(AUTHENTICATION_KERBEROS_METHOD) : null; @@ -108,7 +108,7 @@ protected Configuration getHadoopConfiguration() { * * @return the metadata configuration. */ - protected org.apache.commons.configuration.Configuration getApplicationConfiguration() { + protected org.apache.commons.configuration2.Configuration getApplicationConfiguration() { try { return ApplicationProperties.get(); } catch (AtlasException e) { @@ -135,7 +135,7 @@ protected boolean isHadoopCluster() { return isHadoopCluster; } - private String getHostname(org.apache.commons.configuration.Configuration configuration) { + private String getHostname(org.apache.commons.configuration2.Configuration configuration) { String bindAddress = configuration.getString(SecurityProperties.BIND_ADDRESS); if (bindAddress == null) { diff --git a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java index b092d480684..da9967a1ce3 100755 --- a/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java +++ b/webapp/src/main/java/org/apache/atlas/web/resources/AdminResource.java @@ -82,9 +82,10 @@ import org.apache.atlas.web.service.ServiceState; import org.apache.atlas.web.util.Servlets; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -307,7 +308,9 @@ public Response getVersion() { if (version == null) { try { - PropertiesConfiguration configProperties = new PropertiesConfiguration("atlas-buildinfo.properties"); + PropertiesConfiguration configProperties = new PropertiesConfiguration(); + FileHandler fileHandler = new FileHandler(configProperties); + fileHandler.load("atlas-buildinfo.properties"); Map response = new HashMap<>(); diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java index 6f404a656ff..e318a53b52c 100644 --- a/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java +++ b/webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java @@ -45,7 +45,7 @@ import org.apache.atlas.utils.AtlasPerfTracer; import org.apache.atlas.web.util.Servlets; import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.springframework.stereotype.Service; diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasADAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasADAuthenticationProvider.java index 59329a0643d..089791fd973 100644 --- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasADAuthenticationProvider.java +++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasADAuthenticationProvider.java @@ -20,8 +20,8 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.model.User; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ldap.core.support.LdapContextSource; diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java index 3cff9fb8eeb..9d7ca89939f 100644 --- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java +++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasAuthenticationProvider.java @@ -18,7 +18,7 @@ package org.apache.atlas.web.security; import org.apache.atlas.ApplicationProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java index 9839a219515..376a22d18b4 100644 --- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java +++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProvider.java @@ -17,7 +17,7 @@ package org.apache.atlas.web.security; import org.apache.atlas.ApplicationProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.springframework.security.core.Authentication; diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProvider.java index c401576006d..105adffecd2 100644 --- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProvider.java +++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProvider.java @@ -20,8 +20,8 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.model.User; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasPamAuthenticationProvider.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasPamAuthenticationProvider.java index 49970129c3c..ca8b028e973 100644 --- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasPamAuthenticationProvider.java +++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasPamAuthenticationProvider.java @@ -21,7 +21,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.model.User; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.ConfigurationConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; diff --git a/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java b/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java index 5058ebdf53d..0f7ad76b41d 100644 --- a/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java +++ b/webapp/src/main/java/org/apache/atlas/web/security/AtlasSecurityConfig.java @@ -25,7 +25,7 @@ import org.apache.atlas.web.filters.AtlasKnoxSSOAuthenticationFilter; import org.apache.atlas.web.filters.HeadersUtil; import org.apache.atlas.web.filters.StaleTransactionCleanupFilter; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.KeycloakConfigResolver; diff --git a/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceElectorService.java b/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceElectorService.java index ac9ecd5c9c4..31830405cda 100644 --- a/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceElectorService.java +++ b/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceElectorService.java @@ -24,7 +24,7 @@ import org.apache.atlas.listener.ActiveStateChangeHandler; import org.apache.atlas.service.Service; import org.apache.atlas.util.AtlasMetricsUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.curator.framework.recipes.leader.LeaderLatch; import org.apache.curator.framework.recipes.leader.LeaderLatchListener; import org.slf4j.Logger; diff --git a/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceState.java b/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceState.java index 8e79dbe6488..e743814bafe 100644 --- a/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceState.java +++ b/webapp/src/main/java/org/apache/atlas/web/service/ActiveInstanceState.java @@ -23,7 +23,7 @@ import org.apache.atlas.AtlasException; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.ha.HAConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.locks.InterProcessReadWriteLock; diff --git a/webapp/src/main/java/org/apache/atlas/web/service/CuratorFactory.java b/webapp/src/main/java/org/apache/atlas/web/service/CuratorFactory.java index 7a390f4985f..33cdf3d1cff 100644 --- a/webapp/src/main/java/org/apache/atlas/web/service/CuratorFactory.java +++ b/webapp/src/main/java/org/apache/atlas/web/service/CuratorFactory.java @@ -23,7 +23,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.ha.HAConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.curator.framework.AuthInfo; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; diff --git a/webapp/src/main/java/org/apache/atlas/web/service/SecureEmbeddedServer.java b/webapp/src/main/java/org/apache/atlas/web/service/SecureEmbeddedServer.java index c898861d57a..25645535dbd 100755 --- a/webapp/src/main/java/org/apache/atlas/web/service/SecureEmbeddedServer.java +++ b/webapp/src/main/java/org/apache/atlas/web/service/SecureEmbeddedServer.java @@ -90,7 +90,7 @@ public SecureEmbeddedServer(String host, int port, String path) throws IOExcepti @Override protected Connector getConnector(String host, int port) throws IOException { - org.apache.commons.configuration.Configuration config = getConfiguration(); + org.apache.commons.configuration2.Configuration config = getConfiguration(); SSLContext sslContext = getSSLContext(); @@ -164,7 +164,7 @@ protected Connector getConnector(String host, int port) throws IOException { * Returns the application configuration. * @return */ - protected org.apache.commons.configuration.Configuration getConfiguration() { + protected org.apache.commons.configuration2.Configuration getConfiguration() { try { return ApplicationProperties.get(); } catch (AtlasException e) { diff --git a/webapp/src/main/java/org/apache/atlas/web/service/ServiceState.java b/webapp/src/main/java/org/apache/atlas/web/service/ServiceState.java index b2e7dd705a1..8c66813136d 100644 --- a/webapp/src/main/java/org/apache/atlas/web/service/ServiceState.java +++ b/webapp/src/main/java/org/apache/atlas/web/service/ServiceState.java @@ -25,7 +25,7 @@ import org.apache.atlas.ha.HAConfiguration; import org.apache.atlas.model.audit.AtlasAuditEntry; import org.apache.atlas.repository.audit.AtlasAuditService; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/main/java/org/apache/atlas/web/setup/SetupSteps.java b/webapp/src/main/java/org/apache/atlas/web/setup/SetupSteps.java index b7f5ec4a396..73738a8090d 100644 --- a/webapp/src/main/java/org/apache/atlas/web/setup/SetupSteps.java +++ b/webapp/src/main/java/org/apache/atlas/web/setup/SetupSteps.java @@ -28,7 +28,7 @@ import org.apache.atlas.setup.SetupStep; import org.apache.atlas.web.service.AtlasZookeeperSecurityProperties; import org.apache.atlas.web.service.CuratorFactory; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.locks.InterProcessMutex; import org.apache.zookeeper.ZooDefs; diff --git a/webapp/src/test/java/org/apache/atlas/AtlasIT.java b/webapp/src/test/java/org/apache/atlas/AtlasIT.java index 98139e78bd8..70bbbb9f816 100644 --- a/webapp/src/test/java/org/apache/atlas/AtlasIT.java +++ b/webapp/src/test/java/org/apache/atlas/AtlasIT.java @@ -17,7 +17,7 @@ package org.apache.atlas; import org.apache.commons.cli.CommandLine; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; diff --git a/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationListenerV2Test.java b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationListenerV2Test.java index 0b3d60ab27d..a0b2eca0ef9 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationListenerV2Test.java +++ b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationListenerV2Test.java @@ -36,7 +36,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.utils.AtlasPerfMetrics.MetricRecorder; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationSenderTest.java b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationSenderTest.java index da9c4008c20..a7c48661d6c 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationSenderTest.java +++ b/webapp/src/test/java/org/apache/atlas/notification/EntityNotificationSenderTest.java @@ -19,7 +19,7 @@ package org.apache.atlas.notification; import org.apache.atlas.GraphTransactionInterceptor; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/webapp/src/test/java/org/apache/atlas/notification/NotificationEntityChangeListenerTest.java b/webapp/src/test/java/org/apache/atlas/notification/NotificationEntityChangeListenerTest.java index 59a2ac156c1..02558747ed7 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/NotificationEntityChangeListenerTest.java +++ b/webapp/src/test/java/org/apache/atlas/notification/NotificationEntityChangeListenerTest.java @@ -29,7 +29,7 @@ import org.apache.atlas.v1.model.instance.Referenceable; import org.apache.atlas.v1.model.instance.Struct; import org.apache.atlas.v1.model.notification.EntityNotificationV1; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerKafkaTest.java b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerKafkaTest.java index 529d894ffaa..3f2a83eef2e 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerKafkaTest.java +++ b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerKafkaTest.java @@ -41,7 +41,7 @@ import org.apache.atlas.v1.model.instance.Referenceable; import org.apache.atlas.v1.model.notification.HookNotificationV1; import org.apache.atlas.web.service.ServiceState; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.RandomStringUtils; import org.apache.kafka.clients.consumer.KafkaConsumer; import org.apache.kafka.common.KafkaException; diff --git a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java index 28693f767c8..b3653aa9f66 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java +++ b/webapp/src/test/java/org/apache/atlas/notification/NotificationHookConsumerTest.java @@ -58,7 +58,7 @@ import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityDeleteRequest; import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityUpdateRequest; import org.apache.atlas.web.service.ServiceState; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.kafka.common.TopicPartition; import org.mockito.Mock; import org.mockito.MockedStatic; diff --git a/webapp/src/test/java/org/apache/atlas/web/TestUtils.java b/webapp/src/test/java/org/apache/atlas/web/TestUtils.java index 7c53cdd733d..fbcbb622550 100644 --- a/webapp/src/test/java/org/apache/atlas/web/TestUtils.java +++ b/webapp/src/test/java/org/apache/atlas/web/TestUtils.java @@ -17,7 +17,8 @@ package org.apache.atlas.web; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +48,9 @@ public static void writeConfiguration(PropertiesConfiguration configuration, Str } file.createNewFile(); - configuration.save(new FileWriter(file)); + + FileHandler fileHandler = new FileHandler(configuration); + fileHandler.save(new FileWriter(file)); } public static String getTempDirectory() { diff --git a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationFilterTest.java b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationFilterTest.java index 9057ae57986..4645f800a9a 100644 --- a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationFilterTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationFilterTest.java @@ -25,9 +25,9 @@ import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.web.security.AtlasAbstractAuthenticationProvider; import org.apache.atlas.web.util.Servlets; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.MapConfiguration; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.MapConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.authentication.client.AuthenticatedURL; diff --git a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationKerberosFilterTest.java b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationKerberosFilterTest.java index c8571b4f6fe..87c4056d4e6 100644 --- a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationKerberosFilterTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasAuthenticationKerberosFilterTest.java @@ -19,7 +19,7 @@ import org.apache.atlas.RequestContext; import org.apache.atlas.web.security.BaseSecurityTest; import org.apache.atlas.web.service.EmbeddedServer; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.io.FileUtils; import org.apache.hadoop.hdfs.web.URLConnectionFactory; import org.eclipse.jetty.server.Server; diff --git a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilterTest.java b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilterTest.java index f5eec9f4d86..bbe1c700171 100644 --- a/webapp/src/test/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilterTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/filters/AtlasKnoxSSOAuthenticationFilterTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.web.security.AtlasAuthenticationProvider; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/web/filters/AuditFilterTest.java b/webapp/src/test/java/org/apache/atlas/web/filters/AuditFilterTest.java index 582e3d94609..857d3920220 100644 --- a/webapp/src/test/java/org/apache/atlas/web/filters/AuditFilterTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/filters/AuditFilterTest.java @@ -20,7 +20,7 @@ import org.apache.atlas.DeleteType; import org.apache.atlas.RequestContext; import org.apache.atlas.util.AtlasRepositoryConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/AdminJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/AdminJerseyResourceIT.java index 0dc57b748e5..8bce76e43e0 100755 --- a/webapp/src/test/java/org/apache/atlas/web/integration/AdminJerseyResourceIT.java +++ b/webapp/src/test/java/org/apache/atlas/web/integration/AdminJerseyResourceIT.java @@ -20,7 +20,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.atlas.AtlasClient; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.io.FileHandler; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -42,7 +43,10 @@ public void testGetVersion() throws Exception { assertNotNull(response); - PropertiesConfiguration buildConfiguration = new PropertiesConfiguration("atlas-buildinfo.properties"); + PropertiesConfiguration buildConfiguration = new PropertiesConfiguration(); + + FileHandler fileHandler = new FileHandler(buildConfiguration); + fileHandler.load("atlas-buildinfo.properties"); assertEquals(response.get("Version").asText(), buildConfiguration.getString("build.version")); assertEquals(response.get("Name").asText(), buildConfiguration.getString("project.name")); diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java index 53466ddecfe..a0e930f1afa 100755 --- a/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java +++ b/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java @@ -62,7 +62,7 @@ import org.apache.atlas.v1.model.typedef.TraitTypeDefinition; import org.apache.atlas.v1.model.typedef.TypesDef; import org.apache.atlas.v1.typesystem.types.utils.TypesUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.RandomStringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/webapp/src/test/java/org/apache/atlas/web/listeners/LoginProcessorIT.java b/webapp/src/test/java/org/apache/atlas/web/listeners/LoginProcessorIT.java index 37a64628e64..1ccd14da0f6 100644 --- a/webapp/src/test/java/org/apache/atlas/web/listeners/LoginProcessorIT.java +++ b/webapp/src/test/java/org/apache/atlas/web/listeners/LoginProcessorIT.java @@ -17,7 +17,7 @@ package org.apache.atlas.web.listeners; import org.apache.atlas.web.security.BaseSecurityTest; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.security.UserGroupInformation; @@ -39,7 +39,7 @@ public class LoginProcessorIT extends BaseSecurityTest { public void testDefaultSimpleLogin() throws Exception { LoginProcessor processor = new LoginProcessor() { @Override - protected org.apache.commons.configuration.Configuration getApplicationConfiguration() { + protected org.apache.commons.configuration2.Configuration getApplicationConfiguration() { return new PropertiesConfiguration(); } }; @@ -68,7 +68,7 @@ protected Configuration getHadoopConfiguration() { } @Override - protected org.apache.commons.configuration.Configuration getApplicationConfiguration() { + protected org.apache.commons.configuration2.Configuration getApplicationConfiguration() { PropertiesConfiguration config = new PropertiesConfiguration(); config.setProperty("atlas.authentication.method", "kerberos"); diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java index ef1c7fce1dc..83d7ba21ae1 100644 --- a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java @@ -69,7 +69,7 @@ import org.apache.atlas.web.service.AtlasDebugMetricsSink; import org.apache.atlas.web.service.ServiceState; import org.apache.atlas.web.util.Servlets; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/web/rest/DiscoveryRESTTest.java b/webapp/src/test/java/org/apache/atlas/web/rest/DiscoveryRESTTest.java index b4bd5abcf1b..c688f31107d 100644 --- a/webapp/src/test/java/org/apache/atlas/web/rest/DiscoveryRESTTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/rest/DiscoveryRESTTest.java @@ -32,7 +32,7 @@ import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.utils.AtlasJson; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/AtlasADAuthenticationProviderTest.java b/webapp/src/test/java/org/apache/atlas/web/security/AtlasADAuthenticationProviderTest.java index 4cc36d5dd2e..e48b2b5cd00 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/AtlasADAuthenticationProviderTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/AtlasADAuthenticationProviderTest.java @@ -20,8 +20,8 @@ package org.apache.atlas.web.security; import org.apache.atlas.ApplicationProperties; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/AtlasAuthenticationProviderTest.java b/webapp/src/test/java/org/apache/atlas/web/security/AtlasAuthenticationProviderTest.java index d06b34e06cd..425472e12f2 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/AtlasAuthenticationProviderTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/AtlasAuthenticationProviderTest.java @@ -20,7 +20,7 @@ package org.apache.atlas.web.security; import org.apache.atlas.ApplicationProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockedStatic; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProviderTest.java b/webapp/src/test/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProviderTest.java index 97fceba1f57..1b904ea3d05 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProviderTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/AtlasKeycloakAuthenticationProviderTest.java @@ -20,7 +20,7 @@ package org.apache.atlas.web.security; import org.apache.atlas.ApplicationProperties; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.OidcKeycloakAccount; import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProviderTest.java b/webapp/src/test/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProviderTest.java index 18e962ba048..8785286e36b 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProviderTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/AtlasLdapAuthenticationProviderTest.java @@ -21,8 +21,8 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.model.User; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.mockito.Mock; import org.mockito.MockedConstruction; import org.mockito.MockedStatic; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/AtlasPamAuthenticationProviderTest.java b/webapp/src/test/java/org/apache/atlas/web/security/AtlasPamAuthenticationProviderTest.java index c63d61e89a9..2295947002d 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/AtlasPamAuthenticationProviderTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/AtlasPamAuthenticationProviderTest.java @@ -21,8 +21,8 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.model.User; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationConverter; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ConfigurationConverter; import org.mockito.Mock; import org.mockito.MockedConstruction; import org.mockito.MockedStatic; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/AtlasSecurityConfigTest.java b/webapp/src/test/java/org/apache/atlas/web/security/AtlasSecurityConfigTest.java index 46c5e2111c3..a0d14f293d4 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/AtlasSecurityConfigTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/AtlasSecurityConfigTest.java @@ -26,7 +26,7 @@ import org.apache.atlas.web.filters.AtlasDelegatingAuthenticationEntryPoint; import org.apache.atlas.web.filters.AtlasKnoxSSOAuthenticationFilter; import org.apache.atlas.web.filters.StaleTransactionCleanupFilter; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.keycloak.adapters.AdapterDeploymentContext; import org.keycloak.adapters.KeycloakConfigResolver; import org.keycloak.adapters.KeycloakDeployment; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/BaseSecurityTest.java b/webapp/src/test/java/org/apache/atlas/web/security/BaseSecurityTest.java index 721d773f52e..0c0bceddf40 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/BaseSecurityTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/BaseSecurityTest.java @@ -19,8 +19,9 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.web.TestUtils; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.minikdc.MiniKdc; @@ -64,7 +65,8 @@ public static String writeConfiguration(final PropertiesConfiguration configurat url = new File(confLocation, ApplicationProperties.APPLICATION_PROPERTIES).toURI().toURL(); } PropertiesConfiguration configuredProperties = new PropertiesConfiguration(); - configuredProperties.load(url); + FileHandler fileHandler = new FileHandler(configuredProperties); + fileHandler.load(url); configuredProperties.copy(configuration); @@ -101,7 +103,7 @@ public static void setUpPolicyStore(String tmpDir) throws Exception { FileUtils.write(policyFile, policyStr); } - public static void persistSSLClientConfiguration(org.apache.commons.configuration.Configuration clientConfig) + public static void persistSSLClientConfiguration(org.apache.commons.configuration2.Configuration clientConfig) throws AtlasException, IOException { //trust settings Configuration configuration = new Configuration(false); @@ -134,16 +136,16 @@ public String createJAASEntry(String context, String principal, File keytab) { } protected void generateTestProperties(Properties props) throws ConfigurationException, IOException { - PropertiesConfiguration config = - new PropertiesConfiguration(System.getProperty("user.dir") + - "/../src/conf/" + ApplicationProperties.APPLICATION_PROPERTIES); + PropertiesConfiguration config = new PropertiesConfiguration(); + FileHandler fileHandler = new FileHandler(config); + fileHandler.load(System.getProperty("user.dir") + "/../src/conf/" + ApplicationProperties.APPLICATION_PROPERTIES); for (String propName : props.stringPropertyNames()) { config.setProperty(propName, props.getProperty(propName)); } File file = new File(System.getProperty("user.dir"), ApplicationProperties.APPLICATION_PROPERTIES); file.deleteOnExit(); Writer fileWriter = new FileWriter(file); - config.save(fileWriter); + fileHandler.save(fileWriter); } protected void startEmbeddedServer(Server server) throws Exception { diff --git a/webapp/src/test/java/org/apache/atlas/web/security/FileAuthenticationTest.java b/webapp/src/test/java/org/apache/atlas/web/security/FileAuthenticationTest.java index b753bebedd3..3bb64cbda2e 100644 --- a/webapp/src/test/java/org/apache/atlas/web/security/FileAuthenticationTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/FileAuthenticationTest.java @@ -20,7 +20,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.TestUtils; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.commons.io.FileUtils; import org.mockito.Mock; import org.mockito.MockitoAnnotations; diff --git a/webapp/src/test/java/org/apache/atlas/web/security/NegativeSSLAndKerberosTest.java b/webapp/src/test/java/org/apache/atlas/web/security/NegativeSSLAndKerberosTest.java index e37158e9ad8..c9589be6018 100755 --- a/webapp/src/test/java/org/apache/atlas/web/security/NegativeSSLAndKerberosTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/NegativeSSLAndKerberosTest.java @@ -21,8 +21,9 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasClient; import org.apache.atlas.web.TestUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.hadoop.fs.Path; import org.apache.hadoop.security.alias.JavaKeyStoreProvider; import org.testng.annotations.Test; @@ -70,7 +71,9 @@ public void setUp() throws Exception { } else { url = new File(confLocation, ApplicationProperties.APPLICATION_PROPERTIES).toURI().toURL(); } - configuration.load(url); + + FileHandler fileHandler = new FileHandler(configuration); + fileHandler.load(url); configuration.setProperty(TLS_ENABLED, true); configuration.setProperty("atlas.authentication.method.kerberos", "true"); diff --git a/webapp/src/test/java/org/apache/atlas/web/security/SSLAndKerberosTest.java b/webapp/src/test/java/org/apache/atlas/web/security/SSLAndKerberosTest.java index 3f934ce5502..40b3fbfee57 100755 --- a/webapp/src/test/java/org/apache/atlas/web/security/SSLAndKerberosTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/SSLAndKerberosTest.java @@ -21,7 +21,8 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasClient; import org.apache.atlas.web.TestUtils; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; +import org.apache.commons.configuration2.io.FileHandler; import org.apache.hadoop.fs.Path; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.alias.JavaKeyStoreProvider; @@ -79,7 +80,8 @@ public void setUp() throws Exception { url = new File(confLocation, ApplicationProperties.APPLICATION_PROPERTIES).toURI().toURL(); } - configuration.load(url); + FileHandler fileHandler = new FileHandler(configuration); + fileHandler.load(url); configuration.setProperty(TLS_ENABLED, true); configuration.setProperty("atlas.authentication.method.kerberos", "true"); configuration.setProperty("atlas.authentication.keytab", userKeytabFile.getAbsolutePath()); diff --git a/webapp/src/test/java/org/apache/atlas/web/security/SSLTest.java b/webapp/src/test/java/org/apache/atlas/web/security/SSLTest.java index 5ac970a345d..eb8065a6a77 100755 --- a/webapp/src/test/java/org/apache/atlas/web/security/SSLTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/security/SSLTest.java @@ -21,7 +21,7 @@ import org.apache.atlas.AtlasClient; import org.apache.atlas.web.TestUtils; import org.apache.atlas.web.service.SecureEmbeddedServer; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.security.alias.CredentialProvider; @@ -66,7 +66,7 @@ public void setUp() throws Exception { secureEmbeddedServer = new TestSecureEmbeddedServer(21443, getWarPath()) { @Override - public org.apache.commons.configuration.Configuration getConfiguration() { + public org.apache.commons.configuration2.Configuration getConfiguration() { return configuration; } }; diff --git a/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceElectorServiceTest.java b/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceElectorServiceTest.java index 9efbc63f2cc..24454597662 100644 --- a/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceElectorServiceTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceElectorServiceTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.ha.HAConfiguration; import org.apache.atlas.listener.ActiveStateChangeHandler; import org.apache.atlas.util.AtlasMetricsUtil; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.curator.framework.recipes.leader.LeaderLatch; import org.mockito.InOrder; import org.mockito.Mock; diff --git a/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceStateTest.java b/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceStateTest.java index 68f7ee75598..3e1d141be69 100644 --- a/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceStateTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/ActiveInstanceStateTest.java @@ -19,7 +19,7 @@ package org.apache.atlas.web.service; import org.apache.atlas.ha.HAConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.api.CreateBuilder; import org.apache.curator.framework.api.ExistsBuilder; diff --git a/webapp/src/test/java/org/apache/atlas/web/service/CuratorFactoryTest.java b/webapp/src/test/java/org/apache/atlas/web/service/CuratorFactoryTest.java index 58aef3e0c3b..89092db0e91 100644 --- a/webapp/src/test/java/org/apache/atlas/web/service/CuratorFactoryTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/CuratorFactoryTest.java @@ -21,7 +21,7 @@ import com.google.common.base.Charsets; import org.apache.atlas.AtlasException; import org.apache.atlas.ha.HAConfiguration; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.api.ACLProvider; diff --git a/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTest.java b/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTest.java index 57ab4cbec1c..7b305dcc590 100644 --- a/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTest.java @@ -21,7 +21,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.web.TestUtils; import org.apache.atlas.web.security.BaseSecurityTest; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.eclipse.jetty.webapp.WebAppContext; import org.testng.annotations.Test; diff --git a/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTestBase.java b/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTestBase.java index 5c209fa3f50..bb77e5fabc0 100755 --- a/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTestBase.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/SecureEmbeddedServerTestBase.java @@ -26,7 +26,7 @@ import org.apache.atlas.web.integration.AdminJerseyResourceIT; import org.apache.atlas.web.integration.EntityJerseyResourceIT; import org.apache.atlas.web.integration.TypesJerseyResourceIT; -import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.configuration2.PropertiesConfiguration; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.security.alias.CredentialProvider; @@ -64,7 +64,7 @@ public class SecureEmbeddedServerTestBase { @BeforeClass public void setupSecurePort() throws AtlasException { - org.apache.commons.configuration.Configuration configuration = ApplicationProperties.get(); + org.apache.commons.configuration2.Configuration configuration = ApplicationProperties.get(); securePort = configuration.getInt(Atlas.ATLAS_SERVER_HTTPS_PORT, ATLAS_DEFAULT_HTTPS_PORT); } diff --git a/webapp/src/test/java/org/apache/atlas/web/service/ServiceStateTest.java b/webapp/src/test/java/org/apache/atlas/web/service/ServiceStateTest.java index fa532a5c37d..8415144cb44 100644 --- a/webapp/src/test/java/org/apache/atlas/web/service/ServiceStateTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/service/ServiceStateTest.java @@ -23,7 +23,7 @@ import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.ha.HAConfiguration; import org.apache.atlas.repository.audit.AtlasAuditService; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; diff --git a/webapp/src/test/java/org/apache/atlas/web/setup/SetupStepsTest.java b/webapp/src/test/java/org/apache/atlas/web/setup/SetupStepsTest.java index ba8f0255091..5360f0fb3e9 100644 --- a/webapp/src/test/java/org/apache/atlas/web/setup/SetupStepsTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/setup/SetupStepsTest.java @@ -24,7 +24,7 @@ import org.apache.atlas.setup.SetupException; import org.apache.atlas.setup.SetupStep; import org.apache.atlas.web.service.CuratorFactory; -import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration2.Configuration; import org.apache.commons.lang3.tuple.Pair; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.api.CreateBuilder; From 47e1065fe0796ef2f3c67a5c307b11a4f147566b Mon Sep 17 00:00:00 2001 From: Brijesh Bhalala <32086209+Brijesh619@users.noreply.github.com> Date: Fri, 22 May 2026 17:34:20 +0530 Subject: [PATCH 07/51] ATLAS-5297: Atlas React UI: Topbar alignment and spacing issue in header section (#643) (cherry picked from commit c3be3cb2bf7a06dc0bdcc6b49477781f328f4b42) --- dashboard/src/components/GlobalSearch/QuickSearch.tsx | 5 +++-- dashboard/src/views/Layout/Header.tsx | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dashboard/src/components/GlobalSearch/QuickSearch.tsx b/dashboard/src/components/GlobalSearch/QuickSearch.tsx index c8eba94903c..58452964b0f 100644 --- a/dashboard/src/components/GlobalSearch/QuickSearch.tsx +++ b/dashboard/src/components/GlobalSearch/QuickSearch.tsx @@ -388,6 +388,7 @@ const QuickSearch = () => { className="global-search-stack" alignItems="center" gap="0.5rem" + sx={{ minWidth: 0, flexShrink: 1 }} > { disablePortal className="global-search-autocomplete" sx={{ - minWidth: 280, - flex: 1, + minWidth: 150, + flex: "1 1 280px", "& + .MuiAutocomplete-popper .MuiAutocomplete-option": { backgroundColor: "white" }, diff --git a/dashboard/src/views/Layout/Header.tsx b/dashboard/src/views/Layout/Header.tsx index 80fc2dc0627..31556391d11 100644 --- a/dashboard/src/views/Layout/Header.tsx +++ b/dashboard/src/views/Layout/Header.tsx @@ -182,14 +182,14 @@ const Header: React.FC
    = ({ )} {location.pathname !== "/" && location.pathname !== "/search" && ( -
    +
    )} {(location.pathname === "/" || location.pathname === "/search") && (
    )} -
    +
    Date: Tue, 26 May 2026 18:40:12 -0500 Subject: [PATCH 08/51] ATLAS-5239: Optimize Atlas Async Replication (#567) (cherry picked from commit 4f437010faf7456eea9dbc359e7330faa4358b85) --- .../atlas/model/impexp/AtlasImportResult.java | 12 +- .../model/impexp/TestAtlasImportResult.java | 18 +- .../repository/impexp/AsyncImportService.java | 54 +++- .../repository/impexp/ImportCacheManager.java | 132 ++++++++++ .../repository/impexp/ImportService.java | 50 ++-- .../graph/v2/AsyncImportTaskExecutor.java | 25 +- .../impexp/AsyncImportServiceTest.java | 4 +- .../repository/impexp/ImportServiceTest.java | 230 +----------------- .../impexp/ImportTransformsShaperTest.java | 4 +- .../impexp/ZipFileResourceTestUtils.java | 2 +- .../graph/v2/AsyncImportTaskExecutorTest.java | 31 ++- .../v2/bulkimport/RegularImportTest.java | 2 +- .../notification/ImportTaskListenerImpl.java | 44 ++-- .../NotificationHookConsumer.java | 10 +- .../ImportTaskListenerImplTest.java | 6 +- .../web/resources/AdminResourceTest.java | 2 +- 16 files changed, 302 insertions(+), 324 deletions(-) create mode 100644 repository/src/main/java/org/apache/atlas/repository/impexp/ImportCacheManager.java diff --git a/intg/src/main/java/org/apache/atlas/model/impexp/AtlasImportResult.java b/intg/src/main/java/org/apache/atlas/model/impexp/AtlasImportResult.java index ca689aad290..1ab1e47a69c 100644 --- a/intg/src/main/java/org/apache/atlas/model/impexp/AtlasImportResult.java +++ b/intg/src/main/java/org/apache/atlas/model/impexp/AtlasImportResult.java @@ -28,10 +28,10 @@ import javax.xml.bind.annotation.XmlRootElement; import java.io.Serializable; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; @@ -50,7 +50,7 @@ public class AtlasImportResult implements Serializable { private String hostName; private long timeStamp; private Map metrics; - private List processedEntities; + private Set processedEntities; private OperationStatus operationStatus; private AtlasExportResult exportResultWithoutData; @@ -66,7 +66,7 @@ public AtlasImportResult(AtlasImportRequest request, String userName, String cli this.timeStamp = timeStamp; this.metrics = new HashMap<>(); this.operationStatus = OperationStatus.FAIL; - this.processedEntities = new ArrayList<>(); + this.processedEntities = new HashSet<>(); } public AtlasImportRequest getRequest() { @@ -135,11 +135,11 @@ public void incrementMeticsCounter(String key, int incrementBy) { metrics.put(key, currentValue + incrementBy); } - public List getProcessedEntities() { + public Set getProcessedEntities() { return this.processedEntities; } - public void setProcessedEntities(List processedEntities) { + public void setProcessedEntities(Set processedEntities) { this.processedEntities = processedEntities; } diff --git a/intg/src/test/java/org/apache/atlas/model/impexp/TestAtlasImportResult.java b/intg/src/test/java/org/apache/atlas/model/impexp/TestAtlasImportResult.java index 4f9fd19db2e..31cb21044a9 100644 --- a/intg/src/test/java/org/apache/atlas/model/impexp/TestAtlasImportResult.java +++ b/intg/src/test/java/org/apache/atlas/model/impexp/TestAtlasImportResult.java @@ -22,10 +22,10 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; @@ -177,7 +177,7 @@ public void testOperationStatusSetterGetter() { @Test public void testProcessedEntitiesSetterGetter() { - List processedEntities = new ArrayList<>(); + Set processedEntities = new HashSet<>(); processedEntities.add("entity1"); processedEntities.add("entity2"); @@ -280,7 +280,7 @@ public void testToString() { importResult.setTimeStamp(1640995200000L); importResult.setOperationStatus(OperationStatus.SUCCESS); - List processedEntities = new ArrayList<>(); + Set processedEntities = new HashSet<>(); processedEntities.add("entity1"); importResult.setProcessedEntities(processedEntities); @@ -346,7 +346,7 @@ public void testBoundaryValues() { assertEquals(importResult.getTimeStamp(), Long.MIN_VALUE); // Test with empty collections - importResult.setProcessedEntities(new ArrayList<>()); + importResult.setProcessedEntities(new HashSet<>()); assertTrue(importResult.getProcessedEntities().isEmpty()); importResult.setMetrics(new HashMap<>()); @@ -370,14 +370,14 @@ public void testSpecialCharactersInStrings() { @Test public void testLargeCollections() { - List largeList = new ArrayList<>(); + Set largeList = new HashSet<>(); for (int i = 0; i < 10000; i++) { largeList.add("entity" + i); } importResult.setProcessedEntities(largeList); assertEquals(importResult.getProcessedEntities().size(), 10000); - assertEquals(importResult.getProcessedEntities().get(5000), "entity5000"); + assertEquals(importResult.getProcessedEntities().toArray()[5000], "entity2675"); // Test with large metrics map Map largeMetrics = new HashMap<>(); @@ -392,7 +392,7 @@ public void testLargeCollections() { @Test public void testProcessedEntitiesWithSpecialCharacters() { - List entities = new ArrayList<>(); + Set entities = new HashSet<>(); entities.add("entity-with-dash"); entities.add("entity_with_underscore"); entities.add("entity.with.dots"); @@ -457,7 +457,7 @@ public void testComplexWorkflow() { request.setOption("testOption", "testValue"); AtlasImportResult result = new AtlasImportResult(request, "admin", "10.0.0.1", "server1", System.currentTimeMillis()); - List entities = new ArrayList<>(); + Set entities = new HashSet<>(); entities.add("database1"); entities.add("table1"); entities.add("column1"); diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/AsyncImportService.java b/repository/src/main/java/org/apache/atlas/repository/impexp/AsyncImportService.java index ef747755e43..f2b3cef8c5c 100644 --- a/repository/src/main/java/org/apache/atlas/repository/impexp/AsyncImportService.java +++ b/repository/src/main/java/org/apache/atlas/repository/impexp/AsyncImportService.java @@ -29,6 +29,7 @@ import org.apache.atlas.repository.ogm.DataAccess; import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -49,20 +50,40 @@ public class AsyncImportService { private static final Logger LOG = LoggerFactory.getLogger(AsyncImportService.class); - private final DataAccess dataAccess; + private final DataAccess dataAccess; + private final ImportCacheManager importCache; @Inject public AsyncImportService(DataAccess dataAccess) { - this.dataAccess = dataAccess; + this.dataAccess = dataAccess; + this.importCache = new ImportCacheManager<>(); + } + + public void populateCache(AtlasAsyncImportRequest importRequest) { + if (importRequest != null && StringUtils.isNotEmpty(importRequest.getGuid()) && importRequest.getGuid().charAt(0) != '-') { + importCache.put(importRequest.getImportId(), importRequest); + } } public AtlasAsyncImportRequest fetchImportRequestByImportId(String importId) { try { + AtlasAsyncImportRequest cachedRequest = importCache.get(importId); + + if (cachedRequest != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Cache hit for importId: {}", importId); + } + return cachedRequest; + } AtlasAsyncImportRequest request = new AtlasAsyncImportRequest(); request.setImportId(importId); - return dataAccess.load(request); + request = dataAccess.load(request); + + populateCache(request); + + return request; } catch (Exception e) { LOG.error("Error fetching request with importId: {}", importId, e); @@ -70,9 +91,21 @@ public AtlasAsyncImportRequest fetchImportRequestByImportId(String importId) { } } + public void saveImport(String importId) { + try { + AtlasAsyncImportRequest importRequest = importCache.get(importId); + if (importRequest != null) { + saveImportRequest(importRequest); + importCache.invalidate(importId); + } + } catch (AtlasBaseException e) { + LOG.error("Error saving import request from cache for importId: {}", importId, e); + } + } + public void saveImportRequest(AtlasAsyncImportRequest importRequest) throws AtlasBaseException { try { - dataAccess.save(importRequest); + dataAccess.saveNoLoad(importRequest); LOG.debug("Save request ID: {} request: {}", importRequest.getImportId(), importRequest); } catch (AtlasBaseException e) { @@ -105,11 +138,24 @@ public List fetchQueuedImportRequests() { public void deleteRequests() { try { dataAccess.delete(AtlasGraphUtilsV2.findEntityGUIDsByType(ASYNC_IMPORT_TYPE_NAME, SortOrder.ASCENDING)); + + importCache.clear(); } catch (Exception e) { LOG.error("Error deleting import requests", e); } } + public void deleteRequest(AtlasAsyncImportRequest importRequest) { + try { + if (importRequest != null) { + dataAccess.delete(importRequest.getGuid()); + importCache.invalidate(importRequest.getImportId()); + } + } catch (Exception e) { + LOG.warn("Error deleting import request with importId: {}", importRequest.getImportId(), e); + } + } + public AtlasAsyncImportRequest abortImport(String importId) throws AtlasBaseException { AtlasAsyncImportRequest importRequestToKill = fetchImportRequestByImportId(importId); diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/ImportCacheManager.java b/repository/src/main/java/org/apache/atlas/repository/impexp/ImportCacheManager.java new file mode 100644 index 00000000000..698b7629245 --- /dev/null +++ b/repository/src/main/java/org/apache/atlas/repository/impexp/ImportCacheManager.java @@ -0,0 +1,132 @@ +/** + * 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.atlas.repository.impexp; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +/** + * Lightweight in-memory cache for import operations. + * + *

    Keeps at most 10 entries alive for up to 30 minutes. + * Ideal for caching import-related objects such as entity DTOs, + * vertex lookups, or ImportID→Entity mappings during a single import cycle.

    + */ +public class ImportCacheManager { + private static final int MAX_SIZE = 10; // Max 10 entries + private static final long TTL_MINUTES = 30; // Expire after 30 minutes + private static final long TTL_MILLIS = TimeUnit.MINUTES.toMillis(TTL_MINUTES); + + private final ConcurrentHashMap> cache = new ConcurrentHashMap<>(); + + public ImportCacheManager() { + startCleanupThread(); + } + + private static class CacheEntry { + final V value; + final long timestamp; + + CacheEntry(V value) { + this.value = value; + this.timestamp = System.currentTimeMillis(); + } + + boolean isExpired(long ttlMillis) { + return System.currentTimeMillis() - timestamp > ttlMillis; + } + } + + /** Store or update a value in the cache */ + public void put(K key, V value) { + if (key == null || value == null) { + return; + } + + // Evict oldest if max size exceeded + if (cache.size() >= MAX_SIZE) { + evictOldest(); + } + + cache.put(key, new CacheEntry<>(value)); + } + + /** Retrieve a value if still valid */ + public V get(K key) { + CacheEntry entry = cache.get(key); + if (entry == null) { + return null; + } + + if (entry.isExpired(TTL_MILLIS)) { + cache.remove(key); + return null; + } + + return entry.value; + } + + /** Manually remove one entry */ + public void invalidate(K key) { + cache.remove(key); + } + + /** Clear entire cache */ + public void clear() { + cache.clear(); + } + + /** Returns current cache size */ + public int size() { + return cache.size(); + } + + /** Evicts the oldest entry based on timestamp */ + private void evictOldest() { + K oldestKey = null; + long oldestTime = Long.MAX_VALUE; + + for (Map.Entry> e : cache.entrySet()) { + if (e.getValue().timestamp < oldestTime) { + oldestKey = e.getKey(); + oldestTime = e.getValue().timestamp; + } + } + + if (oldestKey != null) { + cache.remove(oldestKey); + } + } + + /** Periodic cleanup for expired entries */ + private void startCleanupThread() { + Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = new Thread(r, "ImportCache-Cleanup"); + t.setDaemon(true); + return t; + }).scheduleAtFixedRate(this::cleanup, 1, 1, TimeUnit.MINUTES); + } + + private void cleanup() { + long now = System.currentTimeMillis(); + cache.entrySet().removeIf(e -> (now - e.getValue().timestamp) > TTL_MILLIS); + } +} diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java b/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java index 0b502515c50..b6a66522cb3 100644 --- a/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java +++ b/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java @@ -60,9 +60,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -164,22 +162,22 @@ public AtlasAsyncImportRequest run(AtlasImportRequest request, InputStream input try { LOG.info("==> asyncImport(user={}, from={}, request={})", userName, requestingIP, request); - EntityImportStream source = createZipSource(inputStream, AtlasConfiguration.IMPORT_TEMP_DIRECTORY.getString()); - String transforms = MapUtils.isNotEmpty(request.getOptions()) ? request.getOptions().get(TRANSFORMS_KEY) : null; + EntityImportStream source = createZipSource(inputStream, AtlasConfiguration.IMPORT_TEMP_DIRECTORY.getString()); + String transforms = MapUtils.isNotEmpty(request.getOptions()) ? request.getOptions().get(TRANSFORMS_KEY) : null; setImportTransform(source, transforms); - String transformers = MapUtils.isNotEmpty(request.getOptions()) ? request.getOptions().get(TRANSFORMERS_KEY) : null; + String transformers = MapUtils.isNotEmpty(request.getOptions()) ? request.getOptions().get(TRANSFORMERS_KEY) : null; setEntityTransformerHandlers(source, transformers); - AtlasImportResult result = new AtlasImportResult(request, userName, requestingIP, hostName, System.currentTimeMillis()); + AtlasImportResult result = new AtlasImportResult(request, userName, requestingIP, hostName, System.currentTimeMillis()); result.setExportResult(source.getExportResult()); return asyncImportTaskExecutor.run(result, source); } finally { - LOG.info("<== asyncImport(user={}, from={}, request={})", userName, requestingIP, request); + LOG.info("<== asyncImport(user={}, from={})", userName, requestingIP); } } @@ -255,7 +253,7 @@ public void onImportTypeDef(AtlasTypesDef typesDef, String importId) throws Atla throw new AtlasBaseException(AtlasErrorCode.IMPORT_NOT_FOUND, importId); } - AtlasImportResult result = importRequest.getImportResult(); + AtlasImportResult result = importRequest.getImportResult(); try { RequestContext.get().setImportInProgress(true); @@ -270,9 +268,10 @@ public void onImportTypeDef(AtlasTypesDef typesDef, String importId) throws Atla importRequest.setImportResult(result); - asyncImportService.updateImportRequest(importRequest); + asyncImportService.populateCache(importRequest); + asyncImportService.saveImport(importId); - LOG.info("<== onImportTypeDef()"); + LOG.info("<== onImportTypeDef(importId={})", importId); } } @@ -288,9 +287,7 @@ public Boolean onImportEntity(AtlasEntityWithExtInfo entityWithExtInfo, String i AtlasImportResult result = importRequest.getImportResult(); float importProgress = importRequest.getImportDetails().getImportProgress(); - int importedEntitiesCounter = importRequest.getImportDetails().getImportedEntitiesCount(); - int failedEntitiesCounter = importRequest.getImportDetails().getFailedEntitiesCount(); - Set processedEntities = new HashSet<>(result.getProcessedEntities()); + Set processedEntities = result.getProcessedEntities(); List failedEntities = importRequest.getImportDetails().getFailedEntities(); EntityMutationResponse entityMutationResponse = null; long startTimestamp = System.currentTimeMillis(); @@ -301,39 +298,31 @@ public Boolean onImportEntity(AtlasEntityWithExtInfo entityWithExtInfo, String i TypesUtil.Pair resp = this.bulkImporter.asyncImport(entityWithExtInfo, entityMutationResponse, result, processedEntities, failedEntities, position, importRequest.getImportDetails().getTotalEntitiesCount(), importProgress); - importedEntitiesCounter += 1; - - importRequest.getImportDetails().setImportedEntitiesCount(importedEntitiesCounter); - - result.setProcessedEntities(new ArrayList<>(processedEntities)); + result.setProcessedEntities(processedEntities); + importRequest.getImportDetails().setImportedEntitiesCount(importRequest.getImportDetails().getImportedEntitiesCount() + 1); importRequest.getImportDetails().setImportProgress(resp.right); } catch (AtlasBaseException abe) { LOG.warn("Failed to import entity: {} at position: {} for import: {}", entityWithExtInfo.getEntity().getGuid(), position, importId, abe); - failedEntitiesCounter += 1; - importRequest.getImportDetails().setFailedEntitiesCount(failedEntitiesCounter); - failedEntities.add(entityWithExtInfo.getEntity().getGuid()); - importRequest.getImportDetails().setFailedEntities(failedEntities); + importRequest.getImportDetails().setFailedEntitiesCount(importRequest.getImportDetails().getFailedEntitiesCount() + 1); + importRequest.getImportDetails().getFailedEntities().add(entityWithExtInfo.getEntity().getGuid()); importRequest.getImportDetails().addFailure(entityWithExtInfo.getEntity().getGuid(), abe.getMessage()); } finally { RequestContext.get().setImportInProgress(false); result.incrementMeticsCounter("duration", getDuration(System.currentTimeMillis(), startTimestamp)); + importRequest.setImportResult(result); importRequest.setCompletedTime(System.currentTimeMillis()); - asyncImportService.updateImportRequest(importRequest); + asyncImportService.populateCache(importRequest); LOG.info("<== onImportEntity(importId={}, position={})", importId, position); } - if (importRequest.getImportDetails().getPublishedEntityCount() <= - importRequest.getImportDetails().getImportedEntitiesCount() + importRequest.getImportDetails().getFailedEntitiesCount()) { - onImportComplete(importId); - return true; - } - return false; + return importRequest.getImportDetails().getPublishedEntityCount() <= + importRequest.getImportDetails().getImportedEntitiesCount() + importRequest.getImportDetails().getFailedEntitiesCount(); } @Override @@ -359,7 +348,8 @@ public void onImportComplete(String importId) throws AtlasBaseException { importRequest.setStatus(FAILED); } - asyncImportService.updateImportRequest(importRequest); + asyncImportService.populateCache(importRequest); + asyncImportService.saveImport(importId); AtlasImportResult result = importRequest.getImportResult(); diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutor.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutor.java index 11f2802fe79..d489368de0a 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutor.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutor.java @@ -94,14 +94,14 @@ public AtlasAsyncImportRequest run(AtlasImportResult result, EntityImportStream } public void publishTypeDefNotification(AtlasAsyncImportRequest importRequest, AtlasTypesDef atlasTypesDef) throws AtlasBaseException { - LOG.info("==> publishTypeDefNotification()"); + LOG.info("==> publishTypeDefNotification(importId={})", importRequest.getImportId()); try { HookNotification typeDefImportNotification = new ImportNotification.AtlasTypesDefImportNotification(importRequest.getImportId(), importRequest.getImportResult().getUserName(), atlasTypesDef); sendToTopic(importRequest.getTopicName(), typeDefImportNotification); } finally { - LOG.info("<== publishTypeDefNotification()"); + LOG.info("<== publishTypeDefNotification(importId={})", importRequest.getImportId()); } } @@ -134,26 +134,26 @@ public void delete() { @VisibleForTesting void publishImportRequest(AtlasAsyncImportRequest importRequest, EntityImportStream entityImportStream) throws AtlasBaseException { try { - LOG.info("==> publishImportRequest(atlasAsyncImportRequest={})", importRequest); + LOG.info("==> publishImportRequest(importId={})", importRequest.getImportId()); publishTypeDefNotification(importRequest, entityImportStream.getTypesDef()); publishEntityNotification(importRequest, entityImportStream); importRequest.setStagedTime(System.currentTimeMillis()); - importService.updateImportRequest(importRequest); + importService.populateCache(importRequest); importTaskListener.onReceiveImportRequest(importRequest); } finally { notificationInterface.closeProducer(ASYNC_IMPORT, importRequest.getTopicName()); - LOG.info("<== publishImportRequest()"); + LOG.info("<== publishImportRequest(importId={})", importRequest.getImportId()); } } @VisibleForTesting void publishEntityNotification(AtlasAsyncImportRequest importRequest, EntityImportStream entityImportStream) { - LOG.info("==> publishEntityNotification()"); + LOG.info("==> publishEntityNotification(importId={})", importRequest.getImportId()); int publishedEntityCounter = importRequest.getImportDetails().getPublishedEntityCount(); int failedEntityCounter = importRequest.getImportDetails().getFailedEntitiesCount(); @@ -187,11 +187,16 @@ void publishEntityNotification(AtlasAsyncImportRequest importRequest, EntityImpo importRequest.getImportTrackingInfo().setStartEntityPosition(startEntityPosition); importRequest.getImportDetails().setPublishedEntityCount(publishedEntityCounter); - importService.updateImportRequest(importRequest); + importService.populateCache(importRequest); - LOG.info("<== publishEntityNotification()"); + if (publishedEntityCounter % 100 == 0) { + LOG.info("AsyncImport(id={}): published {} out of {} entities so far)", + importRequest.getImportId(), publishedEntityCounter, importRequest.getImportDetails().getTotalEntitiesCount()); + } } } + + LOG.info("<== publishEntityNotification(importId={})", importRequest.getImportId()); } @VisibleForTesting @@ -220,6 +225,8 @@ AtlasAsyncImportRequest registerRequest(AtlasImportResult result, String importI || ObjectUtils.equals(existingImportRequest.getStatus(), ImportStatus.PARTIAL_SUCCESS) || ObjectUtils.equals(existingImportRequest.getStatus(), ImportStatus.FAILED) || ObjectUtils.equals(existingImportRequest.getStatus(), ImportStatus.ABORTED)) { + importService.deleteRequest(existingImportRequest); + AtlasAsyncImportRequest newImportRequest = new AtlasAsyncImportRequest(result); newImportRequest.setImportId(importId); @@ -229,7 +236,7 @@ AtlasAsyncImportRequest registerRequest(AtlasImportResult result, String importI return withRetry(() -> { importService.saveImportRequest(newImportRequest); LOG.info("registerRequest(importId={}): registered new request", importId); - return newImportRequest; }, importId); + return importService.fetchImportRequestByImportId(newImportRequest.getImportId()); }, importId); } else if (ObjectUtils.equals(existingImportRequest.getStatus(), ImportStatus.STAGING)) { // if we are resuming staging, we need to update the latest request received at existingImportRequest.setReceivedTime(System.currentTimeMillis()); diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/AsyncImportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/AsyncImportServiceTest.java index 50378b63e6e..22daf9b6a40 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/AsyncImportServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/AsyncImportServiceTest.java @@ -110,7 +110,7 @@ public void testSaveImportRequest() throws AtlasBaseException { asyncImportService.saveImportRequest(importRequest); - verify(dataAccess, times(1)).save(importRequest); + verify(dataAccess, times(1)).saveNoLoad(importRequest); } @Test @@ -123,7 +123,7 @@ public void testUpdateImportRequest() throws AtlasBaseException { asyncImportService.updateImportRequest(importRequest); - verify(dataAccess, times(1)).save(importRequest); + verify(dataAccess, times(1)).saveNoLoad(importRequest); } @Test diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java index 5731f4bcebf..6f461cf2c0e 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java @@ -26,7 +26,6 @@ import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.impexp.AtlasAsyncImportRequest; import org.apache.atlas.model.impexp.AtlasExportRequest; -import org.apache.atlas.model.impexp.AtlasExportResult; import org.apache.atlas.model.impexp.AtlasImportRequest; import org.apache.atlas.model.impexp.AtlasImportResult; import org.apache.atlas.model.instance.AtlasEntity; @@ -65,11 +64,11 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import static org.apache.atlas.model.impexp.AtlasAsyncImportRequest.ImportStatus.FAILED; -import static org.apache.atlas.model.impexp.AtlasAsyncImportRequest.ImportStatus.PARTIAL_SUCCESS; import static org.apache.atlas.model.impexp.AtlasAsyncImportRequest.ImportStatus.PROCESSING; import static org.apache.atlas.model.impexp.AtlasExportRequest.FETCH_TYPE_FULL; import static org.apache.atlas.model.impexp.AtlasExportRequest.FETCH_TYPE_INCREMENTAL; @@ -87,13 +86,10 @@ import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.testng.Assert.assertEquals; @@ -466,8 +462,9 @@ public void testOnImportTypeDef(AtlasAsyncImportRequest importRequest, boolean s fail("Unexpected exception thrown: " + e.getMessage()); } - // Verify updateImportRequest() is called - verify(asyncImportService).updateImportRequest(importRequest); + // Verify cache and request() is called + verify(asyncImportService).populateCache(importRequest); + verify(asyncImportService).saveImport(importId); } } @@ -524,7 +521,7 @@ public void testOnImportEntityWhenProcessingFailsAndDidNotReachEndShouldReturnFa importDetails.setFailedEntitiesCount(5); importDetails.setPublishedEntityCount(10); - importResult.setProcessedEntities(new ArrayList<>()); + importResult.setProcessedEntities(new HashSet<>()); importRequest.setImportResult(importResult); importRequest.setImportDetails(importDetails); importRequest.setStatus(PROCESSING); @@ -577,7 +574,7 @@ public void testOnImportEntityWhenProcessingSucceedsButDidNotReachEndShouldRetur importDetails.setFailedEntitiesCount(5); importDetails.setPublishedEntityCount(10); - importResult.setProcessedEntities(new ArrayList<>()); + importResult.setProcessedEntities(new HashSet<>()); importRequest.setImportId(importId); importRequest.setImportResult(importResult); importRequest.setImportDetails(importDetails); @@ -606,221 +603,6 @@ public void testOnImportEntityWhenProcessingSucceedsButDidNotReachEndShouldRetur assertEquals(importRequest.getStatus(), PROCESSING); } - @Test - public void testOnImportEntityWhenProcessingReachesEndStatusIsPartialSuccessIfFailedEntityCountIsGreaterThanZero() throws AtlasBaseException { - String importId = "test-import-id"; - int position = 1; - AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = mock(AtlasEntity.AtlasEntityWithExtInfo.class); - AtlasEntity mockEntity = mock(AtlasEntity.class); - when(entityWithExtInfo.getEntity()).thenReturn(mockEntity); - when(mockEntity.getGuid()).thenReturn("entity-guid"); - - EntityMutationResponse mockEntityMutationResponse = mock(EntityMutationResponse.class); - float mockProgress = 75.0f; // Simulated new progress value - TypesUtil.Pair mockResponse = TypesUtil.Pair.of(mockEntityMutationResponse, mockProgress); - - AsyncImportService asyncImportService = mock(AsyncImportService.class); - AuditsWriter auditsWriter = mock(AuditsWriter.class); - BulkImporter bulkImporter = mock(BulkImporter.class); - - AtlasAsyncImportRequest importRequest = new AtlasAsyncImportRequest(); - AtlasImportResult importResult = new AtlasImportResult(); - AtlasAsyncImportRequest.ImportDetails importDetails = new AtlasAsyncImportRequest.ImportDetails(); - AtlasExportResult exportResult = new AtlasExportResult(); - - exportResult.setRequest(new AtlasExportRequest()); - importResult.setExportResult(exportResult); - importResult.setRequest(new AtlasImportRequest()); - importDetails.setImportedEntitiesCount(5); - importDetails.setFailedEntitiesCount(4); - importDetails.setPublishedEntityCount(10); - - importResult.setProcessedEntities(new ArrayList<>()); - importRequest.setImportId(importId); - importRequest.setImportResult(importResult); - importRequest.setImportDetails(importDetails); - importRequest.setStatus(PROCESSING); - - when(asyncImportService.fetchImportRequestByImportId(importId)).thenReturn(importRequest); - when(bulkImporter.asyncImport(any(), any(), any(), any(), any(), anyInt(), anyInt(), anyFloat())) - .thenReturn(mockResponse); - - ImportService spyImportService = spy(new ImportService( - mock(AtlasTypeDefStore.class), - mock(AtlasTypeRegistry.class), - bulkImporter, - auditsWriter, - mock(ImportTransformsShaper.class), - mock(TableReplicationRequestProcessor.class), - mock(AsyncImportTaskExecutor.class), - asyncImportService, - mock(AtlasAuditService.class))); - doNothing().when(spyImportService).processReplicationDeletion(any(), any()); - doNothing().when(auditsWriter).write(anyString(), any(AtlasImportResult.class), anyLong(), anyLong(), any()); - doNothing().when(spyImportService).addToImportOperationAudits(any()); - - boolean result = spyImportService.onImportEntity(entityWithExtInfo, importId, position); - - assertTrue(result); - assertEquals(importRequest.getImportDetails().getImportedEntitiesCount(), 6); - assertEquals(importRequest.getImportDetails().getFailedEntitiesCount(), 4); - assertEquals(importRequest.getStatus(), PARTIAL_SUCCESS); - assertEquals(importRequest.getImportResult().getOperationStatus(), AtlasImportResult.OperationStatus.PARTIAL_SUCCESS); - - verify(spyImportService, times(1)).processReplicationDeletion(any(), any()); - verify(spyImportService, times(1)).addToImportOperationAudits(any()); - } - - @Test - public void testOnImportCompleteWhenProcessingReachesEndStatusIsPartialSuccessIfFailedEntityCountIsGreaterThanZero() throws AtlasBaseException { - String importId = "test-import-id"; - - AtlasAsyncImportRequest importRequest = new AtlasAsyncImportRequest(); - AtlasImportResult importResult = new AtlasImportResult(); - AtlasAsyncImportRequest.ImportDetails importDetails = new AtlasAsyncImportRequest.ImportDetails(); - AtlasExportResult exportResult = new AtlasExportResult(); - - importDetails.setImportedEntitiesCount(2); - importDetails.setFailedEntitiesCount(3); - importDetails.setPublishedEntityCount(5); - - importResult.setRequest(new AtlasImportRequest()); - importResult.setExportResult(exportResult); - importRequest.setImportId(importId); - importRequest.setImportDetails(importDetails); - importRequest.setImportResult(importResult); - importRequest.setStatus(PROCESSING); - - AsyncImportService asyncImportService = mock(AsyncImportService.class); - AuditsWriter auditsWriter = mock(AuditsWriter.class); - - when(asyncImportService.fetchImportRequestByImportId(importId)).thenReturn(importRequest); - - ImportService importService = new ImportService( - mock(AtlasTypeDefStore.class), - mock(AtlasTypeRegistry.class), - mock(BulkImporter.class), - auditsWriter, - mock(ImportTransformsShaper.class), - mock(TableReplicationRequestProcessor.class), - mock(AsyncImportTaskExecutor.class), - asyncImportService, - mock(AtlasAuditService.class)); - - importService.onImportComplete(importId); - - assertEquals(importRequest.getStatus(), PARTIAL_SUCCESS); - assertEquals(importResult.getOperationStatus(), AtlasImportResult.OperationStatus.PARTIAL_SUCCESS); - } - - @Test - public void testOnImportEntityWhenProcessingReachesEndStatusIsFailureIfImportedEntityCountIsZero() throws AtlasBaseException { - String importId = "test-import-id"; - int position = 1; - AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = mock(AtlasEntity.AtlasEntityWithExtInfo.class); - AtlasEntity mockEntity = mock(AtlasEntity.class); - when(entityWithExtInfo.getEntity()).thenReturn(mockEntity); - when(mockEntity.getGuid()).thenReturn("entity-guid"); - - EntityMutationResponse mockEntityMutationResponse = mock(EntityMutationResponse.class); - float mockProgress = 75.0f; // Simulated new progress value - TypesUtil.Pair mockResponse = TypesUtil.Pair.of(mockEntityMutationResponse, mockProgress); - - AsyncImportService asyncImportService = mock(AsyncImportService.class); - AuditsWriter auditsWriter = mock(AuditsWriter.class); - BulkImporter bulkImporter = mock(BulkImporter.class); - - AtlasAsyncImportRequest importRequest = new AtlasAsyncImportRequest(); - AtlasImportResult importResult = new AtlasImportResult(); - AtlasAsyncImportRequest.ImportDetails importDetails = new AtlasAsyncImportRequest.ImportDetails(); - AtlasExportResult exportResult = new AtlasExportResult(); - - exportResult.setRequest(new AtlasExportRequest()); - importResult.setExportResult(exportResult); - importResult.setRequest(new AtlasImportRequest()); - importDetails.setImportedEntitiesCount(0); - importDetails.setFailedEntitiesCount(9); - importDetails.setPublishedEntityCount(10); - importDetails.setTotalEntitiesCount(10); - - importResult.setProcessedEntities(new ArrayList<>()); - importRequest.setImportId(importId); - importRequest.setImportResult(importResult); - importRequest.setImportDetails(importDetails); - importRequest.setStatus(PROCESSING); - - when(asyncImportService.fetchImportRequestByImportId(importId)).thenReturn(importRequest); - when(bulkImporter.asyncImport(any(), any(), any(), any(), any(), anyInt(), anyInt(), anyFloat())) - .thenThrow(new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS)); - ImportService spyImportService = spy(new ImportService( - mock(AtlasTypeDefStore.class), - mock(AtlasTypeRegistry.class), - bulkImporter, - auditsWriter, - mock(ImportTransformsShaper.class), - mock(TableReplicationRequestProcessor.class), - mock(AsyncImportTaskExecutor.class), - asyncImportService, - mock(AtlasAuditService.class))); - - doNothing().when(spyImportService).processReplicationDeletion(any(), any()); - doNothing().when(auditsWriter).write(anyString(), any(AtlasImportResult.class), anyLong(), anyLong(), any()); - doNothing().when(spyImportService).addToImportOperationAudits(any()); - - boolean result = spyImportService.onImportEntity(entityWithExtInfo, importId, position); - - assertTrue(result); - assertEquals(importRequest.getImportDetails().getImportedEntitiesCount(), 0); - assertEquals(importRequest.getImportDetails().getFailedEntitiesCount(), 10); - assertEquals(importRequest.getStatus(), FAILED); - - verify(spyImportService, times(1)).processReplicationDeletion(any(), any()); - verify(spyImportService, times(1)).addToImportOperationAudits(any()); - } - - @Test - public void testOnImportCompleteWhenProcessingReachesEndStatusIsFailureIfImportedEntityCountIsZero() throws AtlasBaseException { - String importId = "test-import-id"; - - AtlasAsyncImportRequest importRequest = new AtlasAsyncImportRequest(); - AtlasImportResult importResult = new AtlasImportResult(); - AtlasAsyncImportRequest.ImportDetails importDetails = new AtlasAsyncImportRequest.ImportDetails(); - AtlasExportResult exportResult = new AtlasExportResult(); - - importDetails.setImportedEntitiesCount(0); - importDetails.setFailedEntitiesCount(5); - importDetails.setPublishedEntityCount(5); - importDetails.setTotalEntitiesCount(5); - - importResult.setRequest(new AtlasImportRequest()); - importResult.setExportResult(exportResult); - importRequest.setImportId(importId); - importRequest.setImportDetails(importDetails); - importRequest.setImportResult(importResult); - importRequest.setStatus(PROCESSING); - - AsyncImportService asyncImportService = mock(AsyncImportService.class); - AuditsWriter auditsWriter = mock(AuditsWriter.class); - - when(asyncImportService.fetchImportRequestByImportId(importId)).thenReturn(importRequest); - - ImportService importService = new ImportService( - mock(AtlasTypeDefStore.class), - mock(AtlasTypeRegistry.class), - mock(BulkImporter.class), - auditsWriter, - mock(ImportTransformsShaper.class), - mock(TableReplicationRequestProcessor.class), - mock(AsyncImportTaskExecutor.class), - asyncImportService, - mock(AtlasAuditService.class)); - - importService.onImportComplete(importId); - - assertEquals(importRequest.getStatus(), FAILED); - assertEquals(importResult.getOperationStatus(), AtlasImportResult.OperationStatus.FAIL); - } - @Test public void importServiceProcessesIOException() { ImportService importService = new ImportService(typeDefStore, typeRegistry, null, null, null, null, null, null, atlasAuditService); diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsShaperTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsShaperTest.java index f9f1dcc0573..95b8ca13f47 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsShaperTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportTransformsShaperTest.java @@ -35,7 +35,7 @@ import javax.inject.Inject; import java.io.IOException; -import java.util.List; +import java.util.Set; import static org.apache.atlas.utils.TestLoadModelUtils.loadFsModel; import static org.testng.Assert.assertEquals; @@ -73,7 +73,7 @@ public void newTagIsCreatedAndEntitiesAreTagged() throws AtlasBaseException, IOE assertEntities(result.getProcessedEntities(), TAG_NAME); } - private void assertEntities(List entityGuids, String tagName) throws AtlasBaseException { + private void assertEntities(Set entityGuids, String tagName) throws AtlasBaseException { for (String guid : entityGuids) { AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = this.entityStore.getById(guid); diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java index 1764d34511d..07691d34eda 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java @@ -67,7 +67,7 @@ public static InputStream getInputStreamFrom(String fileName) { return ZipFileResourceTestUtils.getFileInputStream(fileName); } - public static void verifyImportedEntities(List creationOrder, List processedEntities) { + public static void verifyImportedEntities(List creationOrder, Set processedEntities) { Set lhs = com.google.common.collect.Sets.newHashSet(creationOrder); Set rhs = com.google.common.collect.Sets.newHashSet(processedEntities); Set difference = Sets.difference(lhs, rhs); diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutorTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutorTest.java index 1fe38885ed7..8748f6b66b4 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutorTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AsyncImportTaskExecutorTest.java @@ -88,15 +88,19 @@ public void setup() { @Test void testRunSuccess() throws AtlasBaseException { - AtlasImportResult mockResult = mock(AtlasImportResult.class); - EntityImportStream mockEntityImportStream = mock(EntityImportStream.class); + AtlasImportResult mockResult = mock(AtlasImportResult.class); + EntityImportStream mockEntityImportStream = mock(EntityImportStream.class); + AtlasAsyncImportRequest savedRequest = new AtlasAsyncImportRequest(mockResult); + + savedRequest.setImportId("import-md5-hash"); + savedRequest.setStatus(AtlasAsyncImportRequest.ImportStatus.STAGING); when(mockEntityImportStream.getMd5Hash()).thenReturn("import-md5-hash"); when(mockEntityImportStream.size()).thenReturn(5); when(mockEntityImportStream.getCreationOrder()).thenReturn(Collections.emptyList()); when(mockEntityImportStream.hasNext()).thenReturn(false); - when(importService.fetchImportRequestByImportId("import-md5-hash")).thenReturn(null); + when(importService.fetchImportRequestByImportId("import-md5-hash")).thenReturn(null).thenReturn(savedRequest); doNothing().when(importService).saveImportRequest(any(AtlasAsyncImportRequest.class)); AtlasAsyncImportRequest result = asyncImportTaskExecutor.run(mockResult, mockEntityImportStream); @@ -189,7 +193,7 @@ void testPublishImportRequestHappyPath() throws AtlasBaseException { asyncImportTaskExecutor.publishImportRequest(mockImportRequest, mockEntityImportStream); - verify(importService).updateImportRequest(mockImportRequest); + verify(importService).populateCache(mockImportRequest); verify(notificationInterface).closeProducer(NotificationInterface.NotificationType.ASYNC_IMPORT, "test-topic"); verify(importTaskListener).onReceiveImportRequest(mockImportRequest); } @@ -246,7 +250,7 @@ void testPublishEntityNotificationHappyPath() throws NotificationException { verify(notificationInterface).send(eq("test-topic"), anyList(), any()); verify(mockEntityImportStream).onImportComplete("entity-guid"); - verify(importService).updateImportRequest(mockImportRequest); + verify(importService).populateCache(mockImportRequest); assertEquals(mockImportRequest.getImportTrackingInfo().getStartEntityPosition(), 1); assertEquals(mockImportRequest.getImportDetails().getPublishedEntityCount(), 1); } @@ -266,7 +270,7 @@ void testPublishEntityNotificationNullEntity() throws NotificationException { verify(notificationInterface, never()).send(anyString(), anyList(), any()); verify(mockEntityImportStream, never()).onImportComplete(anyString()); - verify(importService).updateImportRequest(mockImportRequest); + verify(importService).populateCache(mockImportRequest); assertEquals(mockImportRequest.getImportTrackingInfo().getStartEntityPosition(), 1); assertEquals(mockImportRequest.getImportDetails().getPublishedEntityCount(), 0); } @@ -299,7 +303,7 @@ void testPublishEntityNotificationExceptionInSendToTopic() throws NotificationEx verify(notificationInterface).send(eq("test-topic"), anyList(), any()); verify(mockEntityImportStream, never()).onImportComplete("entity-guid"); - verify(importService).updateImportRequest(mockImportRequest); + verify(importService).populateCache(mockImportRequest); assertEquals(mockImportRequest.getImportTrackingInfo().getStartEntityPosition(), 1); assertEquals(mockImportRequest.getImportDetails().getFailedEntitiesCount(), 1); assertEquals(mockImportRequest.getImportDetails().getPublishedEntityCount(), 0); @@ -334,7 +338,7 @@ void testPublishEntityNotificationIgnoreFailedEntityAndProcessNext() throws Noti verify(notificationInterface, times(2)).send(eq("test-topic"), anyList(), any()); verify(mockEntityImportStream, times(1)).onImportComplete("entity-guid"); - verify(importService, times(2)).updateImportRequest(mockImportRequest); + verify(importService, times(2)).populateCache(mockImportRequest); assertEquals(mockImportRequest.getImportDetails().getPublishedEntityCount(), 1); assertEquals(mockImportRequest.getImportDetails().getFailedEntitiesCount(), 1); } @@ -411,6 +415,9 @@ public Object[][] registerRequestScenarios() { public void testRegisterRequest(String existingStatus, String expectedOutcome) throws AtlasBaseException { AtlasImportResult mockResult = mock(AtlasImportResult.class); AtlasAsyncImportRequest existingRequest = null; + AtlasAsyncImportRequest savedRequest = new AtlasAsyncImportRequest(mockResult); + + savedRequest.setImportId("import-id"); if (!"null".equals(existingStatus)) { existingRequest = mock(AtlasAsyncImportRequest.class); @@ -419,7 +426,7 @@ public void testRegisterRequest(String existingStatus, String expectedOutcome) t when(existingRequest.getImportDetails()).thenReturn(new AtlasAsyncImportRequest.ImportDetails()); } - when(importService.fetchImportRequestByImportId("import-id")).thenReturn(existingRequest); + when(importService.fetchImportRequestByImportId("import-id")).thenReturn(existingRequest).thenReturn(savedRequest); AtlasAsyncImportRequest result = asyncImportTaskExecutor.registerRequest(mockResult, "import-id", 10, Collections.emptyList()); @@ -453,15 +460,15 @@ public void testRegisterRequestThrowsException() throws AtlasBaseException { @Test public void testWithRetrySucceedsAfterLockingConflict() throws Exception { - AtlasImportResult result = mock(AtlasImportResult.class); - AtlasAsyncImportRequest newRequest = new AtlasAsyncImportRequest(result); + AtlasImportResult result = mock(AtlasImportResult.class); + AtlasAsyncImportRequest savedRequest = new AtlasAsyncImportRequest(result); // First call fails with a PermanentLockingException, second succeeds doThrow(new RuntimeException(new PermanentLockingException("lock conflict"))) .doNothing() .when(importService).saveImportRequest(any(AtlasAsyncImportRequest.class)); - when(importService.fetchImportRequestByImportId("import-id")).thenReturn(null); + when(importService.fetchImportRequestByImportId("import-id")).thenReturn(null).thenReturn(savedRequest); AtlasAsyncImportRequest response = asyncImportTaskExecutor.registerRequest(result, "import-id", 5, Collections.emptyList()); diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/bulkimport/RegularImportTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/bulkimport/RegularImportTest.java index a7f5bcf00eb..df4bd8cd946 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/bulkimport/RegularImportTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/bulkimport/RegularImportTest.java @@ -393,7 +393,7 @@ private AtlasEntity createMockEntity(String typeName, String guid) { private AtlasImportResult createMockAtlasImportResult() { AtlasImportResult mockResult = mock(AtlasImportResult.class); - when(mockResult.getProcessedEntities()).thenReturn(new ArrayList<>()); + when(mockResult.getProcessedEntities()).thenReturn(new HashSet<>()); return mockResult; } } diff --git a/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java b/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java index 1c04b432a28..619602eb285 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java +++ b/webapp/src/main/java/org/apache/atlas/notification/ImportTaskListenerImpl.java @@ -130,11 +130,12 @@ public int getHandlerOrder() { @Override public void onReceiveImportRequest(AtlasAsyncImportRequest importRequest) throws AtlasBaseException { try { - LOG.info("==> onReceiveImportRequest(atlasAsyncImportRequest={})", importRequest); + LOG.info("==> onReceiveImportRequest(importId={})", importRequest.getImportId()); importRequest.setStatus(ImportStatus.WAITING); - asyncImportService.updateImportRequest(importRequest); + asyncImportService.populateCache(importRequest); + asyncImportService.saveImport(importRequest.getImportId()); requestQueue.put(importRequest.getImportId()); startNextImportInQueue(); @@ -145,7 +146,7 @@ public void onReceiveImportRequest(AtlasAsyncImportRequest importRequest) throws throw new AtlasBaseException(IMPORT_QUEUEING_FAILED, e, importRequest.getImportId()); } finally { - LOG.info("<== onReceiveImportRequest(atlasAsyncImportRequest={})", importRequest); + LOG.info("<== onReceiveImportRequest(importId={})", importRequest.getImportId()); } } @@ -241,6 +242,8 @@ void startAsyncImportIfAvailable(String importId) { return; } + LOG.info("startingImport(importId={})", nextImport.getImportId()); + ExecutorService exec = ensureExecutorAlive(); if (exec != null) { exec.submit(() -> startImportConsumer(nextImport)); @@ -261,7 +264,9 @@ AtlasAsyncImportRequest getNextImportFromQueue() { LOG.info("==> getNextImportFromQueue()"); final int maxRetries = 5; - int retryCount = 0; + + int retryCount = 0; + AtlasAsyncImportRequest nextImport = null; while (retryCount < maxRetries) { try { @@ -278,24 +283,24 @@ AtlasAsyncImportRequest getNextImportFromQueue() { // Reset retry count because we got a valid importId (even if it's invalid later) retryCount = 0; - AtlasAsyncImportRequest importRequest = asyncImportService.fetchImportRequestByImportId(importId); + nextImport = asyncImportService.fetchImportRequestByImportId(importId); - if (isNotValidImportRequest(importRequest)) { - LOG.info("Import request {}, is not in a valid status to start import, hence skipping..", importRequest); + if (isNotValidImportRequest(nextImport)) { + LOG.info("Import request {}, is not in a valid status to start import, hence skipping..", nextImport); continue; } - LOG.info("<== getImportIdFromQueue(nextImportId={})", importRequest.getImportId()); + LOG.info("<== getImportIdFromQueue(nextImportId={})", nextImport.getImportId()); - return importRequest; + return nextImport; } catch (InterruptedException e) { LOG.error("Thread interrupted while waiting for importId from the queue", e); // Restore the interrupt flag Thread.currentThread().interrupt(); - return null; + return nextImport; } } @@ -347,24 +352,27 @@ void populateRequestQueue() { private void startImportConsumer(AtlasAsyncImportRequest importRequest) { try { - LOG.info("==> startImportConsumer(atlasAsyncImportRequest={})", importRequest); - - notificationHookConsumer.startAsyncImportConsumer(NotificationInterface.NotificationType.ASYNC_IMPORT, importRequest.getImportId(), importRequest.getTopicName()); + LOG.info("==> startImportConsumer(importId={})", importRequest.getImportId()); importRequest.setStatus(ImportStatus.PROCESSING); importRequest.setProcessingStartTime(System.currentTimeMillis()); - } catch (Exception e) { - LOG.error("Failed to start consumer for import: {}, marking import as failed", importRequest, e); + asyncImportService.populateCache(importRequest); + asyncImportService.saveImportRequest(importRequest); + + notificationHookConsumer.startAsyncImportConsumer(NotificationInterface.NotificationType.ASYNC_IMPORT, importRequest.getImportId(), importRequest.getTopicName()); + } catch (Exception e) { importRequest.setStatus(ImportStatus.FAILED); - } finally { - asyncImportService.updateImportRequest(importRequest); + LOG.error("Failed to start consumer for import: {}, marking import as failed", importRequest, e); + } finally { if (ObjectUtils.equals(importRequest.getStatus(), ImportStatus.FAILED)) { + asyncImportService.saveImport(importRequest.getImportId()); + onCompleteImportRequest(importRequest.getImportId()); } - LOG.info("<== startImportConsumer(atlasAsyncImportRequest={})", importRequest); + LOG.info("<== startImportConsumer(importId={})", importRequest.getImportId()); } } diff --git a/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java b/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java index c30b652da96..bc9b97bf8f9 100644 --- a/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java +++ b/webapp/src/main/java/org/apache/atlas/notification/NotificationHookConsumer.java @@ -1463,16 +1463,20 @@ void handleMessage(AtlasKafkaMessage kafkaMsg) { final String importId = entityImportNotification.getImportId(); final AtlasEntityWithExtInfo entityWithExtInfo = entityImportNotification.getEntity(); final int position = entityImportNotification.getPosition(); - boolean completeImport = false; + + LOG.info("==> IMPORT_ENTITY:processing entity: {} at position: {}", importId, position); try { importRequestComplete = asyncImporter.onImportEntity(entityWithExtInfo, importId, position); } catch (AtlasBaseException abe) { importRequestComplete = true; - asyncImporter.onImportComplete(importId); - LOG.error("IMPORT_ENTITY: {} failed to import entity: {}", importId, entityImportNotification); + } finally { + if (importRequestComplete) { + asyncImporter.onImportComplete(importId); + } + LOG.info("<== IMPORT_ENTITY:processing entity: {} at position: {}", importId, position); } } break; diff --git a/webapp/src/test/java/org/apache/atlas/notification/ImportTaskListenerImplTest.java b/webapp/src/test/java/org/apache/atlas/notification/ImportTaskListenerImplTest.java index 76020d2da22..fc7ab67633a 100644 --- a/webapp/src/test/java/org/apache/atlas/notification/ImportTaskListenerImplTest.java +++ b/webapp/src/test/java/org/apache/atlas/notification/ImportTaskListenerImplTest.java @@ -128,7 +128,8 @@ public void testOnReceiveImportRequestAddsRequestToQueue() throws InterruptedExc Thread.sleep(500); verify(requestQueue, times(1)).put("import123"); - verify(asyncImportService, times(1)).updateImportRequest(importRequest); + verify(asyncImportService, times(1)).populateCache(importRequest); + verify(asyncImportService, times(1)).saveImport("import123"); } @Test @@ -152,7 +153,8 @@ public void testOnReceiveImportRequestHandlesQueueException() throws Interrupted importTaskListener.onReceiveImportRequest(importRequest); } finally { verify(requestQueue, times(1)).put("import123"); - verify(asyncImportService, times(1)).updateImportRequest(importRequest); + verify(asyncImportService, times(1)).populateCache(importRequest); + verify(asyncImportService, times(1)).saveImport("import123"); } } diff --git a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java index 83d7ba21ae1..7723ee75ace 100644 --- a/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java +++ b/webapp/src/test/java/org/apache/atlas/web/resources/AdminResourceTest.java @@ -1261,7 +1261,7 @@ public void testImportDataWithReplicatedFromOption() throws Exception { AtlasImportResult mockResult = mock(AtlasImportResult.class); when(mockResult.getOperationStatus()).thenReturn(AtlasImportResult.OperationStatus.SUCCESS); - when(mockResult.getProcessedEntities()).thenReturn(new ArrayList<>()); + when(mockResult.getProcessedEntities()).thenReturn(new HashSet<>()); when(mockResult.getMetrics()).thenReturn(new HashMap()); when(mockResult.getExportResult()).thenReturn(mock(AtlasExportResult.class)); when(mockResult.getExportResult().getRequest()).thenReturn(null); From 673e98b358331fbff8659d5f902f8f4973567ab7 Mon Sep 17 00:00:00 2001 From: Brijesh Bhalala <32086209+Brijesh619@users.noreply.github.com> Date: Tue, 26 May 2026 16:39:21 +0530 Subject: [PATCH 09/51] ATLAS-5301: Atlas React UI: Nested Subcategories not visible in Glossary Tree Structure View (#645) (cherry picked from commit a3c6637468fff3bfea3cd1f05d6f7778b7667247) --- .../SideBar/SideBarTree/CustomFiltersTree.tsx | 38 ++-- .../SideBar/SideBarTree/GlossaryTree.tsx | 183 +++++++++--------- .../views/SideBar/SideBarTree/SideBarTree.tsx | 17 -- 3 files changed, 103 insertions(+), 135 deletions(-) diff --git a/dashboard/src/views/SideBar/SideBarTree/CustomFiltersTree.tsx b/dashboard/src/views/SideBar/SideBarTree/CustomFiltersTree.tsx index c8794486129..72c6d3a0eff 100644 --- a/dashboard/src/views/SideBar/SideBarTree/CustomFiltersTree.tsx +++ b/dashboard/src/views/SideBar/SideBarTree/CustomFiltersTree.tsx @@ -19,7 +19,6 @@ import { useState, useEffect, useMemo } from "react"; import SideBarTree from "../../SideBar/SideBarTree/SideBarTree.tsx"; import { customSortBy, - customSortByObjectKeys, groupBy, isArray, isEmpty @@ -29,7 +28,6 @@ import type { Props } from "@models/treeStructureType.ts"; import { ChildrenInterface, ChildrenInterfaces, - ServiceTypeFlatInterface, ServiceTypeInterface } from "@models/entityTreeType.ts"; import { @@ -47,9 +45,8 @@ const CustomFiltersTree = ({ sideBarOpen, searchTerm }: Props) => { ); const { relationshipSearch = {} } = globalSessionData || {}; - const [savedSearchType, setsavedSearchType] = useState(true); const [savedSearchTypeData, setSavedSearchTypeData] = useState< - SavedSearchArrType + SavedSearchArrType >([]); const [customFilterLoader, setCustomFilterLoader] = useState(false); @@ -76,9 +73,7 @@ const CustomFiltersTree = ({ sideBarOpen, searchTerm }: Props) => { ]; let searchTypes = !isEmpty(savedSearchData) - ? savedSearchType - ? groupBy(savedSearchData, "searchType") - : savedSearchData + ? groupBy(savedSearchData, "searchType") : groupBy(emptySearchTypes, "searchType"); for (let type in searchTypes) { const getType = (type: string) => { @@ -101,21 +96,20 @@ const CustomFiltersTree = ({ sideBarOpen, searchTerm }: Props) => { parent: type })); }; - let name = savedSearchType ? getType(type) : searchTypes[type].name; + let name = getType(type); let children = - savedSearchType && !isEmpty(savedSearchData) + !isEmpty(savedSearchData) ? getChildren(searchTypes[type] as SavedSearchDataType[], type) : []; savedSearchTypeArr.push({ name, children, types: "parent", - parent: savedSearchType ? type : searchTypes[type].searchType + parent: type }); } const existingSearchTypes = savedSearchTypeArr.map((child) => child.parent); - if (savedSearchType) { emptySearchTypes.forEach((typeObj) => { if (!existingSearchTypes.includes(typeObj.searchType)) { savedSearchTypeArr.push({ @@ -126,9 +120,8 @@ const CustomFiltersTree = ({ sideBarOpen, searchTerm }: Props) => { }); } }); - } setSavedSearchTypeData(savedSearchTypeArr as any); - }, [savedSearchData, savedSearchType]); + }, [savedSearchData]); const generateChildrenData = useMemo(() => { const child = (childs: any) => { @@ -157,35 +150,26 @@ const CustomFiltersTree = ({ sideBarOpen, searchTerm }: Props) => { serviceTypeData.map((type: any) => ({ id: type.name, label: type.name, - children: savedSearchType - ? child(type.children as ChildrenInterfaces[]) - : [], + children: child(type.children as ChildrenInterfaces[]), types: type.types, parent: type.parent })); - }, [savedSearchType]); + }, []); const treeData = useMemo(() => { - return savedSearchType - ? customSortBy( + return customSortBy( generateChildrenData( savedSearchTypeData as unknown as SavedSearchArrInterface[] ), ["label"] - ) - : generateChildrenData( - customSortByObjectKeys( - savedSearchTypeData as ServiceTypeFlatInterface[] - ) ); - }, [savedSearchType, savedSearchTypeData]); + }, [savedSearchTypeData]); return ( { newServiceTypeArr = glossaryData != null ? glossaryData.map( - (glossary: { - name: string; - subTypes: []; - guid: string; - superTypes: string[]; - categories: EnumCategoryRelation[]; - terms: EnumCategoryRelation[]; + (glossary: { + name: string; + subTypes: []; + guid: string; + superTypes: string[]; + categories: EnumCategoryRelation[]; + terms: EnumCategoryRelation[]; + }) => { + let categoryRelation: EnumCategoryRelation[] = []; + + glossary?.categories?.map((obj: EnumCategoryRelations) => { + if (obj.parentCategoryGuid != undefined) { + categoryRelation.push(obj as EnumCategoryRelations); + } + }); + + const getChildren = (glossaries: { + children: EnumCategoryRelation[]; + parent: string; }) => { - let categoryRelation: EnumCategoryRelation[] = []; - - glossary?.categories?.map((obj: EnumCategoryRelations) => { - if (obj.parentCategoryGuid != undefined) { - categoryRelation.push(obj as EnumCategoryRelations); - } - }); - - const getChildren = (glossaries: { - children: EnumCategoryRelation[]; - parent: string; - }) => { - return !isEmpty(glossaries.children) - ? glossaries.children - .map((glossariesType: any) => { - const getChild = () => { - return categoryRelation - .map((obj: EnumCategoryRelations) => { - if ( - obj.parentCategoryGuid == - glossariesType.categoryGuid - ) { - return { - ["name"]: obj.displayText, - id: obj.displayText, - ["children"]: [], - types: "child", - parent: glossaries.parent, - cGuid: glossaryType - ? obj.termGuid - : obj.categoryGuid, - guid: glossary.guid - }; - } - }) - .filter(Boolean); - }; - if (glossariesType.parentCategoryGuid == undefined) { - return { - ["name"]: glossariesType.displayText, - id: glossariesType.displayText, - ["children"]: getChild(), - types: "child", - parent: glossaries.parent, - cGuid: glossaryType - ? glossariesType.termGuid - : glossariesType.categoryGuid, - guid: glossary.guid - }; - } - }) - .filter(Boolean) - : []; - }; - - let name: string = glossary.name, - children: any = glossaryType - ? getChildren({ - children: glossary?.terms, - parent: glossary.name - }) - : getChildren({ - children: glossary?.categories, - parent: glossary.name - }); - - return { - [name]: { - ["name"]: name, - ["children"]: children || [], - id: glossary.guid, - types: "parent", - parent: name, - guid: glossary.guid - } - }; - } - ) + return !isEmpty(glossaries.children) + ? glossaries.children + .map((glossariesType: any) => { + const getChild = (parentGuid: string | undefined): any => { + if (!parentGuid) return []; + return categoryRelation + .map((obj: EnumCategoryRelations) => { + if ( + obj.parentCategoryGuid == + parentGuid + ) { + return { + ["name"]: obj.displayText, + id: obj.displayText, + ["children"]: getChild(obj.categoryGuid), + types: "child", + parent: glossaries.parent, + cGuid: glossaryType + ? obj.termGuid + : obj.categoryGuid, + guid: glossary.guid + }; + } + }) + .filter(Boolean); + }; + if (glossariesType.parentCategoryGuid == undefined) { + return { + ["name"]: glossariesType.displayText, + id: glossariesType.displayText, + ["children"]: getChild(glossariesType.categoryGuid), + types: "child", + parent: glossaries.parent, + cGuid: glossaryType + ? glossariesType.termGuid + : glossariesType.categoryGuid, + guid: glossary.guid + }; + } + }) + .filter(Boolean) + : []; + }; + + let name: string = glossary.name, + children: any = glossaryType + ? getChildren({ + children: glossary?.terms, + parent: glossary.name + }) + : getChildren({ + children: glossary?.categories, + parent: glossary.name + }); + + return { + [name]: { + ["name"]: name, + ["children"]: children || [], + id: glossary.guid, + types: "parent", + parent: name, + guid: glossary.guid + } + }; + } + ) : []; setGlossaryData(newServiceTypeArr); @@ -162,10 +163,10 @@ const GlossaryTree = ({ sideBarOpen, searchTerm }: Props) => { children: obj?.children != undefined ? child( - obj.children.filter( - Boolean - ) as unknown as ChildrenInterfaces[] - ) + obj.children.filter( + Boolean + ) as unknown as ChildrenInterfaces[] + ) : [], types: obj?.types, parent: obj?.parent, @@ -193,8 +194,8 @@ const GlossaryTree = ({ sideBarOpen, searchTerm }: Props) => { const treeData = useMemo(() => { return !isEmpty(glossaryData) ? generateChildrenData( - customSortByObjectKeys(glossaryTypeData as ServiceTypeInterface[]) - ) + customSortByObjectKeys(glossaryTypeData as ServiceTypeInterface[]) + ) : noTreeData(); }, [glossaryType, glossaryTypeData]); diff --git a/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx b/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx index bc9e444c278..ec36f54abf4 100644 --- a/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx +++ b/dashboard/src/views/SideBar/SideBarTree/SideBarTree.tsx @@ -1042,23 +1042,6 @@ const BarTreeView: FC<{
    - {treeName == "CustomFilters" && ( - - { - e.stopPropagation(); - if (setisEmptyServicetype) { - setisEmptyServicetype(!isEmptyServicetype); - } - }} - fontSize="small" - className="menuitem-icon" - /> - - )} {(treeName == "Entities" || treeName == "Classifications" || From 680c70016228af4e931d47195ef356d0f932610f Mon Sep 17 00:00:00 2001 From: Farhan Khan Date: Wed, 27 May 2026 14:52:54 +0530 Subject: [PATCH 10/51] Updated memberlist details in pom.xml (cherry-picked from commit d476ca64124dd2f91c7cac62c46fa2142be5c534) --- pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pom.xml b/pom.xml index a48b50536cc..c5fa6b1f31a 100644 --- a/pom.xml +++ b/pom.xml @@ -1825,6 +1825,16 @@ America/New_York + + fkhan + Farhan Khan + fkhan@apache.org + Freestone Infotech + + committer + + Asia/Kolkata + grahamwallis Graham Wallis From 4694a8cc1e5362cb1bbc13c7da7e14337a27fe03 Mon Sep 17 00:00:00 2001 From: Brijesh Bhalala <32086209+Brijesh619@users.noreply.github.com> Date: Fri, 29 May 2026 12:26:40 +0530 Subject: [PATCH 11/51] ATLAS-5298: Atlas-React UI: Fix Critical XSS Vulnerability in sanitize-html dependency (#641) ( cherry-picked from commit 079e44c9e6d72819a4a89041f562f8528119f86a) --- dashboard/package-lock.json | 58 +++++++++++++++++++++++++++++++++---- dashboard/package.json | 4 +-- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index db87c13fa86..b1bf5f292bd 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "dashboard", "version": "0.0.0", + "hasInstallScript": true, "dependencies": { "@dnd-kit/core": "6.1.0", "@dnd-kit/modifiers": "7.0.0", @@ -40,7 +41,7 @@ "react-router-dom": "6.30.3", "react-toastify": "10.0.5", "redux": "5.0.1", - "sanitize-html": "2.13.0" + "sanitize-html": "^2.17.4" }, "devDependencies": { "@types/autosuggest-highlight": "3.2.3", @@ -3952,6 +3953,12 @@ "url": "https://github.com/sponsors/kossnocorp" } }, + "node_modules/dayjs": { + "version": "1.11.20", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", + "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", + "license": "MIT" + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -5107,6 +5114,15 @@ "json-buffer": "3.0.1" } }, + "node_modules/launder": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/launder/-/launder-1.7.1.tgz", + "integrity": "sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw==", + "license": "MIT", + "dependencies": { + "dayjs": "^1.11.7" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6157,19 +6173,51 @@ "license": "MIT" }, "node_modules/sanitize-html": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.13.0.tgz", - "integrity": "sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==", + "version": "2.17.4", + "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.4.tgz", + "integrity": "sha512-2HW7v2ol/uAM7sX4hbD8Z59OGWmAPrvjL8E71UWlBcj6m+kcF6ilQBLny+cIgY214QJeJT5tQuxKKqX0SQqjGQ==", "license": "MIT", "dependencies": { "deepmerge": "^4.2.2", "escape-string-regexp": "^4.0.0", - "htmlparser2": "^8.0.0", + "htmlparser2": "^10.1.0", "is-plain-object": "^5.0.0", + "launder": "^1.7.1", "parse-srcset": "^1.0.2", "postcss": "^8.3.11" } }, + "node_modules/sanitize-html/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/sanitize-html/node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, "node_modules/sass": { "version": "1.74.1", "resolved": "https://registry.npmjs.org/sass/-/sass-1.74.1.tgz", diff --git a/dashboard/package.json b/dashboard/package.json index 6cb8364f188..ba25f638ae3 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -44,7 +44,7 @@ "react-router-dom": "6.30.3", "react-toastify": "10.0.5", "redux": "5.0.1", - "sanitize-html": "2.13.0" + "sanitize-html": "2.17.4" }, "devDependencies": { "@types/autosuggest-highlight": "3.2.3", @@ -77,4 +77,4 @@ "js-yaml": "4.1.1", "immutable": "4.3.8" } -} \ No newline at end of file +} From 86a375f7ea93447f9b704131e7aca1e6062f93e8 Mon Sep 17 00:00:00 2001 From: Prasad Pawar <49935882+pawarprasad123@users.noreply.github.com> Date: Wed, 3 Jun 2026 12:56:01 +0530 Subject: [PATCH 12/51] ATLAS-5307: Atlas UI: Update frontend npm dependencies in dashboard, dashboardv2, and docs (#653) ( cherry-picked from commit 81325f2fa7d36f8bb09d9a326538452b6bfcd38d) --- dashboard/package-lock.json | 49 +- dashboard/package.json | 8 +- .../Lineage/atlas-lineage/package-lock.json | 611 +++++++---------- .../views/Lineage/atlas-lineage/package.json | 2 +- dashboardv2/package-lock.json | 6 +- dashboardv2/package.json | 2 +- .../atlas-lineage/package-lock.json | 621 +++++++----------- .../external_lib/atlas-lineage/package.json | 2 +- docs/package-lock.json | 251 +++---- docs/package.json | 11 +- 10 files changed, 680 insertions(+), 883 deletions(-) diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index b1bf5f292bd..2f4b0684d66 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -23,7 +23,7 @@ "@types/react-redux": "7.1.33", "@types/sanitize-html": "2.13.0", "autosuggest-highlight": "3.3.4", - "axios": "1.13.5", + "axios": "1.15.2", "d3": "5.16.0", "d3-tip": "0.7.1", "dagre-d3": "0.6.4", @@ -41,7 +41,7 @@ "react-router-dom": "6.30.3", "react-toastify": "10.0.5", "redux": "5.0.1", - "sanitize-html": "^2.17.4" + "sanitize-html": "2.17.4" }, "devDependencies": { "@types/autosuggest-highlight": "3.2.3", @@ -59,7 +59,7 @@ "recharts": "2.15.1", "sass": "1.74.1", "typescript": "5.2.2", - "vite": "6.4.1" + "vite": "6.4.2" } }, "node_modules/@babel/code-frame": { @@ -3061,14 +3061,14 @@ } }, "node_modules/axios": { - "version": "1.13.5", - "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "version": "1.15.2", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.15.2.tgz", + "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" + "proxy-from-env": "^2.1.0" } }, "node_modules/babel-plugin-macros": { @@ -4595,9 +4595,9 @@ } }, "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, @@ -5160,15 +5160,15 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash-es": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.23.tgz", - "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", "license": "MIT" }, "node_modules/lodash.clonedeep": { @@ -5581,10 +5581,13 @@ "license": "MIT" }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/punycode": { "version": "2.3.1", @@ -6629,9 +6632,9 @@ } }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "6.4.2", + "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/dashboard/package.json b/dashboard/package.json index ba25f638ae3..2dd2fac50c5 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -26,7 +26,7 @@ "@types/react-redux": "7.1.33", "@types/sanitize-html": "2.13.0", "autosuggest-highlight": "3.3.4", - "axios": "1.13.5", + "axios": "1.15.2", "d3": "5.16.0", "d3-tip": "0.7.1", "dagre-d3": "0.6.4", @@ -62,7 +62,7 @@ "recharts": "2.15.1", "sass": "1.74.1", "typescript": "5.2.2", - "vite": "6.4.1" + "vite": "6.4.2" }, "overrides": { "loader-utils": "3.2.1", @@ -73,7 +73,9 @@ "elliptic": "6.6.1", "rollup": "4.59.0", "d3-color": "3.1.0", - "lodash-es": "4.17.23", + "lodash": "4.18.1", + "lodash-es": "4.18.1", + "flatted": "3.4.2", "js-yaml": "4.1.1", "immutable": "4.3.8" } diff --git a/dashboard/src/views/Lineage/atlas-lineage/package-lock.json b/dashboard/src/views/Lineage/atlas-lineage/package-lock.json index dc0df8a1d40..793f48116ce 100644 --- a/dashboard/src/views/Lineage/atlas-lineage/package-lock.json +++ b/dashboard/src/views/Lineage/atlas-lineage/package-lock.json @@ -14,9 +14,9 @@ "platform": "1.3.5" }, "devDependencies": { - "@babel/core": "7.23.2", + "@babel/core": "7.29.0", "@babel/plugin-transform-class-properties": "7.23.3", - "@babel/preset-env": "7.23.2", + "@babel/preset-env": "7.29.5", "babel-loader": "8.1.0", "css-loader": "3.5.3", "mini-css-extract-plugin": "0.9.0", @@ -27,20 +27,6 @@ "webpack-cli": "3.3.11" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -57,9 +43,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.3", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", "dev": true, "license": "MIT", "engines": { @@ -67,22 +53,22 @@ } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -185,9 +171,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", - "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", + "version": "0.6.8", + "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", "dependencies": { @@ -405,14 +391,15 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -421,100 +408,98 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz", + "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -552,142 +537,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", @@ -911,6 +760,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", @@ -927,6 +793,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", @@ -1093,9 +976,9 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "dev": true, "license": "MIT", "dependencies": { @@ -1346,6 +1229,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", @@ -1511,91 +1411,82 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.2", - "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.23.2.tgz", - "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "version": "7.29.5", + "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.29.5.tgz", + "integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.2", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/compat-data": "^7.29.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.22.5", - "@babel/plugin-syntax-import-attributes": "^7.22.5", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.23.2", - "@babel/plugin-transform-async-to-generator": "^7.22.5", - "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-class-static-block": "^7.22.11", - "@babel/plugin-transform-classes": "^7.22.15", - "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.23.0", - "@babel/plugin-transform-dotall-regex": "^7.22.5", - "@babel/plugin-transform-duplicate-keys": "^7.22.5", - "@babel/plugin-transform-dynamic-import": "^7.22.11", - "@babel/plugin-transform-exponentiation-operator": "^7.22.5", - "@babel/plugin-transform-export-namespace-from": "^7.22.11", - "@babel/plugin-transform-for-of": "^7.22.15", - "@babel/plugin-transform-function-name": "^7.22.5", - "@babel/plugin-transform-json-strings": "^7.22.11", - "@babel/plugin-transform-literals": "^7.22.5", - "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", - "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.23.0", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-modules-systemjs": "^7.23.0", - "@babel/plugin-transform-modules-umd": "^7.22.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.22.5", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-numeric-separator": "^7.22.11", - "@babel/plugin-transform-object-rest-spread": "^7.22.15", - "@babel/plugin-transform-object-super": "^7.22.5", - "@babel/plugin-transform-optional-catch-binding": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-parameters": "^7.22.15", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-property-literals": "^7.22.5", - "@babel/plugin-transform-regenerator": "^7.22.10", - "@babel/plugin-transform-reserved-words": "^7.22.5", - "@babel/plugin-transform-shorthand-properties": "^7.22.5", - "@babel/plugin-transform-spread": "^7.22.5", - "@babel/plugin-transform-sticky-regex": "^7.22.5", - "@babel/plugin-transform-template-literals": "^7.22.5", - "@babel/plugin-transform-typeof-symbol": "^7.22.5", - "@babel/plugin-transform-unicode-escapes": "^7.22.10", - "@babel/plugin-transform-unicode-property-regex": "^7.22.5", - "@babel/plugin-transform-unicode-regex": "^7.22.5", - "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.29.0", + "@babel/plugin-transform-async-to-generator": "^7.28.6", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.28.6", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", + "@babel/plugin-transform-modules-systemjs": "^7.29.4", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.29.0", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", "@babel/preset-modules": "0.1.6-no-external-plugins", - "@babel/types": "^7.23.0", - "babel-plugin-polyfill-corejs2": "^0.4.6", - "babel-plugin-polyfill-corejs3": "^0.8.5", - "babel-plugin-polyfill-regenerator": "^0.5.3", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1605,6 +1496,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-class-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", @@ -1679,6 +1587,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -2165,61 +2084,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.7", - "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", - "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "version": "0.14.2", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4", - "core-js-compat": "^3.33.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.4", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", - "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "version": "0.6.8", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -2963,9 +2848,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.48.0", - "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.48.0.tgz", - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", + "version": "3.49.0", + "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", "dependencies": { @@ -5125,9 +5010,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.debounce": { @@ -6742,13 +6627,13 @@ } }, "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-7.0.3.tgz", + "integrity": "sha512-h+cZ/XXarqDgCjo+YSyQU/ulDEESGGf8AMK9pPNmhNSl/FzPl6L8pMp1leca5z6NuG6tvV/auC8/43tmovowww==", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" + "engines": { + "node": ">=20.0.0" } }, "node_modules/set-blocking": { diff --git a/dashboard/src/views/Lineage/atlas-lineage/package.json b/dashboard/src/views/Lineage/atlas-lineage/package.json index 6f1675f2f1f..a517d59712b 100644 --- a/dashboard/src/views/Lineage/atlas-lineage/package.json +++ b/dashboard/src/views/Lineage/atlas-lineage/package.json @@ -1 +1 @@ -{"name":"atlas-lineage-module","version":"1.0.0","description":"The module will help to render the lineage graph with the help dagre-d3,d3 js lib","main":"dist/index.js","scripts":{"start":"NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider webpack --watch","build":"NODE_OPTIONS=--openssl-legacy-provider webpack"},"repository":{"type":"git","url":"git+https://github.com/apache/atlas.git"},"keywords":["lineage","dagre-d3","d3"],"author":"kevalbhatt","license":"Apache-2.0","bugs":{"url":"https://github.com/apache/atlas/issues"},"homepage":"https://github.com/apache/atlas#readme","dependencies":{"d3-tip":"0.9.1","dagre-d3":"0.6.4","platform":"1.3.5"},"devDependencies":{"@babel/core":"7.23.2","@babel/preset-env":"7.23.2","babel-loader":"8.1.0","@babel/plugin-transform-class-properties":"7.23.3","css-loader":"3.5.3","mini-css-extract-plugin":"0.9.0","path":"0.12.7","sass":"1.26.5","sass-loader":"8.0.2","webpack":"4.43.0","webpack-cli":"3.3.11"},"overrides":{"json5":"2.2.3","elliptic":"6.6.1","form-data":"2.5.5","pbkdf2":"3.1.5","sha.js":"2.4.12","loader-utils":"1.4.2","cipher-base":"1.0.5","decode-uri-component":"0.2.1","browserify-sign":"4.2.2","lodash":"4.17.23","y18n":"4.0.1","braces":"3.0.3","d3-color":"3.1.0","immutable":"4.3.8"}} \ No newline at end of file +{"name":"atlas-lineage-module","version":"1.0.0","description":"The module will help to render the lineage graph with the help dagre-d3,d3 js lib","main":"dist/index.js","scripts":{"start":"NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider webpack --watch","build":"NODE_OPTIONS=--openssl-legacy-provider webpack"},"repository":{"type":"git","url":"git+https://github.com/apache/atlas.git"},"keywords":["lineage","dagre-d3","d3"],"author":"kevalbhatt","license":"Apache-2.0","bugs":{"url":"https://github.com/apache/atlas/issues"},"homepage":"https://github.com/apache/atlas#readme","dependencies":{"d3-tip":"0.9.1","dagre-d3":"0.6.4","platform":"1.3.5"},"devDependencies":{"@babel/core":"7.29.0","@babel/preset-env":"7.29.5","babel-loader":"8.1.0","@babel/plugin-transform-class-properties":"7.23.3","css-loader":"3.5.3","mini-css-extract-plugin":"0.9.0","path":"0.12.7","sass":"1.26.5","sass-loader":"8.0.2","webpack":"4.43.0","webpack-cli":"3.3.11"},"overrides":{"json5":"2.2.3","elliptic":"6.6.1","form-data":"2.5.5","pbkdf2":"3.1.5","sha.js":"2.4.12","loader-utils":"1.4.2","cipher-base":"1.0.5","decode-uri-component":"0.2.1","browserify-sign":"4.2.2","lodash":"4.18.1","serialize-javascript":"7.0.3","@babel/plugin-transform-modules-systemjs":"7.29.4","y18n":"4.0.1","braces":"3.0.3","d3-color":"3.1.0","immutable":"4.3.8"}} \ No newline at end of file diff --git a/dashboardv2/package-lock.json b/dashboardv2/package-lock.json index d16848132d1..d0f870f5cd5 100644 --- a/dashboardv2/package-lock.json +++ b/dashboardv2/package-lock.json @@ -3118,9 +3118,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/longest": { diff --git a/dashboardv2/package.json b/dashboardv2/package.json index 2f2274cda5c..81e6df054b9 100644 --- a/dashboardv2/package.json +++ b/dashboardv2/package.json @@ -77,7 +77,7 @@ }, "overrides": { "underscore": "1.13.8", - "lodash": "4.17.23", + "lodash": "4.18.1", "d3-color": "3.1.0", "js-yaml": "3.14.2", "immutable": "4.3.8", diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json b/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json index a0b3adfedb1..669ba6f33c4 100644 --- a/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json +++ b/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json @@ -14,9 +14,9 @@ "platform": "1.3.5" }, "devDependencies": { - "@babel/core": "7.23.2", + "@babel/core": "7.29.0", "@babel/plugin-transform-class-properties": "7.23.3", - "@babel/preset-env": "7.23.2", + "@babel/preset-env": "7.29.5", "babel-loader": "8.1.0", "css-loader": "3.5.3", "mini-css-extract-plugin": "0.9.0", @@ -27,20 +27,6 @@ "webpack-cli": "3.3.11" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -57,9 +43,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "version": "7.29.3", + "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", "dev": true, "license": "MIT", "engines": { @@ -67,22 +53,22 @@ } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -225,9 +211,9 @@ } }, "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", - "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", + "version": "0.6.8", + "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", "dev": true, "license": "MIT", "dependencies": { @@ -445,14 +431,15 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -461,100 +448,98 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.3", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz", + "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -592,142 +577,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", @@ -951,6 +800,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", @@ -967,6 +833,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.28.6", "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", @@ -1133,9 +1016,9 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "dev": true, "license": "MIT", "dependencies": { @@ -1386,6 +1269,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.27.1", "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", @@ -1551,91 +1451,82 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.23.2", - "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.23.2.tgz", - "integrity": "sha512-BW3gsuDD+rvHL2VO2SjAUNTBe5YrjsTiDyqamPDWY723na3/yPQ65X5oQkFVJZ0o50/2d+svm1rkPoJeR1KxVQ==", + "version": "7.29.5", + "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.29.5.tgz", + "integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.23.2", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-validator-option": "^7.22.15", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15", + "@babel/compat-data": "^7.29.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.22.5", - "@babel/plugin-syntax-import-attributes": "^7.22.5", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.22.5", - "@babel/plugin-transform-async-generator-functions": "^7.23.2", - "@babel/plugin-transform-async-to-generator": "^7.22.5", - "@babel/plugin-transform-block-scoped-functions": "^7.22.5", - "@babel/plugin-transform-block-scoping": "^7.23.0", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-class-static-block": "^7.22.11", - "@babel/plugin-transform-classes": "^7.22.15", - "@babel/plugin-transform-computed-properties": "^7.22.5", - "@babel/plugin-transform-destructuring": "^7.23.0", - "@babel/plugin-transform-dotall-regex": "^7.22.5", - "@babel/plugin-transform-duplicate-keys": "^7.22.5", - "@babel/plugin-transform-dynamic-import": "^7.22.11", - "@babel/plugin-transform-exponentiation-operator": "^7.22.5", - "@babel/plugin-transform-export-namespace-from": "^7.22.11", - "@babel/plugin-transform-for-of": "^7.22.15", - "@babel/plugin-transform-function-name": "^7.22.5", - "@babel/plugin-transform-json-strings": "^7.22.11", - "@babel/plugin-transform-literals": "^7.22.5", - "@babel/plugin-transform-logical-assignment-operators": "^7.22.11", - "@babel/plugin-transform-member-expression-literals": "^7.22.5", - "@babel/plugin-transform-modules-amd": "^7.23.0", - "@babel/plugin-transform-modules-commonjs": "^7.23.0", - "@babel/plugin-transform-modules-systemjs": "^7.23.0", - "@babel/plugin-transform-modules-umd": "^7.22.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.22.5", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11", - "@babel/plugin-transform-numeric-separator": "^7.22.11", - "@babel/plugin-transform-object-rest-spread": "^7.22.15", - "@babel/plugin-transform-object-super": "^7.22.5", - "@babel/plugin-transform-optional-catch-binding": "^7.22.11", - "@babel/plugin-transform-optional-chaining": "^7.23.0", - "@babel/plugin-transform-parameters": "^7.22.15", - "@babel/plugin-transform-private-methods": "^7.22.5", - "@babel/plugin-transform-private-property-in-object": "^7.22.11", - "@babel/plugin-transform-property-literals": "^7.22.5", - "@babel/plugin-transform-regenerator": "^7.22.10", - "@babel/plugin-transform-reserved-words": "^7.22.5", - "@babel/plugin-transform-shorthand-properties": "^7.22.5", - "@babel/plugin-transform-spread": "^7.22.5", - "@babel/plugin-transform-sticky-regex": "^7.22.5", - "@babel/plugin-transform-template-literals": "^7.22.5", - "@babel/plugin-transform-typeof-symbol": "^7.22.5", - "@babel/plugin-transform-unicode-escapes": "^7.22.10", - "@babel/plugin-transform-unicode-property-regex": "^7.22.5", - "@babel/plugin-transform-unicode-regex": "^7.22.5", - "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.29.0", + "@babel/plugin-transform-async-to-generator": "^7.28.6", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.28.6", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", + "@babel/plugin-transform-modules-systemjs": "^7.29.4", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.29.0", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", "@babel/preset-modules": "0.1.6-no-external-plugins", - "@babel/types": "^7.23.0", - "babel-plugin-polyfill-corejs2": "^0.4.6", - "babel-plugin-polyfill-corejs3": "^0.8.5", - "babel-plugin-polyfill-regenerator": "^0.5.3", - "core-js-compat": "^3.31.0", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { @@ -1645,6 +1536,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-class-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", @@ -1729,6 +1637,17 @@ "@jridgewell/trace-mapping": "^0.3.24" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -2225,61 +2144,27 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.8.7", - "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.7.tgz", - "integrity": "sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==", + "version": "0.14.2", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.4", - "core-js-compat": "^3.33.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.4.4", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.4.tgz", - "integrity": "sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.5", - "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", - "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.5.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.5.0", - "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", - "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "version": "0.6.8", + "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" + "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -3009,9 +2894,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.48.0", - "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.48.0.tgz", - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", + "version": "3.49.0", + "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", "dev": true, "license": "MIT", "dependencies": { @@ -5178,9 +5063,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.debounce": { @@ -6806,6 +6691,16 @@ "semver": "bin/semver" } }, + "node_modules/serialize-javascript": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-7.0.3.tgz", + "integrity": "sha512-h+cZ/XXarqDgCjo+YSyQU/ulDEESGGf8AMK9pPNmhNSl/FzPl6L8pMp1leca5z6NuG6tvV/auC8/43tmovowww==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz", @@ -7453,16 +7348,6 @@ "node": ">= 4" } }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/terser-webpack-plugin/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/package.json b/dashboardv2/public/js/external_lib/atlas-lineage/package.json index 82cdc214cbd..816dbb2e441 100644 --- a/dashboardv2/public/js/external_lib/atlas-lineage/package.json +++ b/dashboardv2/public/js/external_lib/atlas-lineage/package.json @@ -1 +1 @@ -{"name":"atlas-lineage-module","version":"1.0.0","description":"The module will help to render the lineage graph with the help dagre-d3,d3 js lib","main":"dist/index.js","scripts":{"start":"NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider webpack --watch","build":"NODE_OPTIONS=--openssl-legacy-provider webpack"},"repository":{"type":"git","url":"git+https://github.com/apache/atlas.git"},"keywords":["lineage","dagre-d3","d3"],"author":"kevalbhatt","license":"Apache-2.0","bugs":{"url":"https://github.com/apache/atlas/issues"},"homepage":"https://github.com/apache/atlas#readme","dependencies":{"d3-tip":"0.9.1","dagre-d3":"0.6.4","platform":"1.3.5"},"devDependencies":{"@babel/core":"7.23.2","@babel/preset-env":"7.23.2","babel-loader":"8.1.0","@babel/plugin-transform-class-properties":"7.23.3","css-loader":"3.5.3","mini-css-extract-plugin":"0.9.0","path":"0.12.7","sass":"1.74.1","sass-loader":"8.0.2","webpack":"4.43.0","webpack-cli":"3.3.11"},"overrides":{"json5":"2.2.3","form-data":"2.5.5","tar":"7.5.8","pbkdf2":"3.1.5","sha.js":"2.4.12","elliptic":"6.6.1","loader-utils":"1.4.2","qs":"6.14.1","braces":"3.0.3","lodash":"4.17.23","d3-color":"3.1.0","immutable":"4.3.8"}} \ No newline at end of file +{"name":"atlas-lineage-module","version":"1.0.0","description":"The module will help to render the lineage graph with the help dagre-d3,d3 js lib","main":"dist/index.js","scripts":{"start":"NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider webpack --watch","build":"NODE_OPTIONS=--openssl-legacy-provider webpack"},"repository":{"type":"git","url":"git+https://github.com/apache/atlas.git"},"keywords":["lineage","dagre-d3","d3"],"author":"kevalbhatt","license":"Apache-2.0","bugs":{"url":"https://github.com/apache/atlas/issues"},"homepage":"https://github.com/apache/atlas#readme","dependencies":{"d3-tip":"0.9.1","dagre-d3":"0.6.4","platform":"1.3.5"},"devDependencies":{"@babel/core":"7.29.0","@babel/preset-env":"7.29.5","babel-loader":"8.1.0","@babel/plugin-transform-class-properties":"7.23.3","css-loader":"3.5.3","mini-css-extract-plugin":"0.9.0","path":"0.12.7","sass":"1.74.1","sass-loader":"8.0.2","webpack":"4.43.0","webpack-cli":"3.3.11"},"overrides":{"json5":"2.2.3","form-data":"2.5.5","tar":"7.5.8","pbkdf2":"3.1.5","sha.js":"2.4.12","elliptic":"6.6.1","loader-utils":"1.4.2","qs":"6.14.1","braces":"3.0.3","lodash":"4.18.1","serialize-javascript":"7.0.3","@babel/plugin-transform-modules-systemjs":"7.29.4","d3-color":"3.1.0","immutable":"4.3.8"}} \ No newline at end of file diff --git a/docs/package-lock.json b/docs/package-lock.json index f84f1081cf5..2976d7128c9 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -22,7 +22,7 @@ "@babel/core": "7.16.7", "@babel/plugin-syntax-dynamic-import": "7.8.3", "@babel/preset-react": "7.16.7", - "axios": "1.13.5", + "axios": "1.15.2", "babel-loader": "8.0.6", "babel-plugin-lodash": "3.3.4", "babel-plugin-react-transform": "3.0.0", @@ -78,13 +78,14 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -137,14 +138,15 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "version": "7.29.1", + "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { @@ -358,6 +360,15 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", @@ -371,25 +382,27 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "license": "MIT", "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "license": "MIT", "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" }, "engines": { "node": ">=6.9.0" @@ -410,9 +423,10 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -462,17 +476,19 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -526,11 +542,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.29.3", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "license": "MIT", "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1351,14 +1368,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "version": "7.29.4", + "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.29.0" }, "engines": { "node": ">=6.9.0" @@ -2118,42 +2136,45 @@ } }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.28.6", + "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" @@ -2200,43 +2221,35 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "version": "0.3.13", + "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "version": "0.3.31", + "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -3527,15 +3540,15 @@ } }, "node_modules/axios": { - "version": "1.13.5", - "resolved": "https://registry.npmmirror.com/axios/-/axios-1.13.5.tgz", - "integrity": "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q==", + "version": "1.15.2", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.15.2.tgz", + "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==", "dev": true, "license": "MIT", "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", - "proxy-from-env": "^1.1.0" + "proxy-from-env": "^2.1.0" } }, "node_modules/babel-core": { @@ -7229,9 +7242,9 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" }, "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "version": "3.1.2", + "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "funding": [ { "type": "github", @@ -9637,9 +9650,9 @@ } }, "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "license": "MIT" }, "node_modules/lodash.debounce": { @@ -10355,9 +10368,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.2", - "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.3.2.tgz", - "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -11082,9 +11095,10 @@ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -11386,11 +11400,14 @@ } }, "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/prr": { "version": "1.0.1", @@ -13062,6 +13079,15 @@ "node": ">= 0.8" } }, + "node_modules/serialize-javascript": { + "version": "7.0.3", + "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-7.0.3.tgz", + "integrity": "sha512-h+cZ/XXarqDgCjo+YSyQU/ulDEESGGf8AMK9pPNmhNSl/FzPl6L8pMp1leca5z6NuG6tvV/auC8/43tmovowww==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/serve": { "version": "11.3.2", "resolved": "https://registry.npmjs.org/serve/-/serve-11.3.2.tgz", @@ -14055,15 +14081,6 @@ "node": ">= 4" } }, - "node_modules/terser-webpack-plugin/node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/terser-webpack-plugin/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/docs/package.json b/docs/package.json index f6322401bd6..36543cabbf1 100644 --- a/docs/package.json +++ b/docs/package.json @@ -19,7 +19,7 @@ "@babel/core": "7.16.7", "@babel/plugin-syntax-dynamic-import": "7.8.3", "@babel/preset-react": "7.16.7", - "axios": "1.13.5", + "axios": "1.15.2", "babel-loader": "8.0.6", "babel-plugin-lodash": "3.3.4", "babel-plugin-react-transform": "3.0.0", @@ -53,7 +53,7 @@ "form-data": "2.5.5", "pbkdf2": "3.1.5", "sha.js": "2.4.12", - "node-forge": "1.3.2", + "node-forge": "1.4.0", "trim-newlines": "3.0.1", "ip": "npm:neoip@2.1.0", "webpack-dev-middleware": "5.3.4", @@ -61,7 +61,12 @@ "ws": "5.2.4", "nth-check": "2.0.1", "acorn": "6.4.1", - "lodash": "4.17.23", + "lodash": "4.18.1", + "@babel/plugin-transform-modules-systemjs": "7.29.4", + "serialize-javascript": "7.0.3", + "fast-uri": "3.1.2", + "picomatch": "2.3.2", + "axios": "1.15.2", "react-dev-utils": "11.0.4", "@babel/runtime": "7.26.10", "ajv": "6.12.6", From 78cc7e29c232c0c64748546c36d9952c99d5becf Mon Sep 17 00:00:00 2001 From: Prasad Pawar <49935882+pawarprasad123@users.noreply.github.com> Date: Thu, 4 Jun 2026 19:39:26 +0530 Subject: [PATCH 13/51] ATLAS-5174: Set up Test Infrastructure and Configuration for Atlas Dashboard (#632) ( cherry-picked form the commit b2c03255b6cf0a8a17e9979d58331f3841d5f877 ) * ATLAS-5174: Set up Test Infrastructure and Configuration for Atlas Dashboard * ATLAS-5174: Set up Test Infrastructure and Configuration for Atlas Dashboard * ATLAS-5174: Set up Test Infrastructure and Configuration for Atlas Dashboard * ATLAS-5174: Set up Test Infrastructure and Configuration for Atlas Dashboard --- dashboard/.babelrc.json | 10 + dashboard/.eslintrc.cjs | 23 +- dashboard/.gitignore | 3 + dashboard/jest.config.js | 157 + dashboard/package-lock.json | 11489 ++++++++++------ dashboard/package.json | 27 +- dashboard/pom.xml | 15 + dashboard/src/ErrorBoundary.tsx | 26 +- dashboard/src/__mocks__/fileMock.ts | 19 + dashboard/src/__mocks__/react-quill-new.tsx | 36 + dashboard/src/__mocks__/styleMock.ts | 19 + dashboard/src/__mocks__/table-layout-mock.tsx | 189 + .../__tests__/apache-license-header.test.ts | 152 + dashboard/src/setupTests.simple.ts | 68 + dashboard/src/setupTests.ts | 131 + dashboard/src/utils/test-utils.tsx | 130 + dashboard/tsconfig.build.json | 14 + dashboard/tsconfig.json | 9 + dashboard/tsconfig.test.json | 42 + 19 files changed, 8648 insertions(+), 3911 deletions(-) create mode 100644 dashboard/.babelrc.json create mode 100644 dashboard/jest.config.js create mode 100644 dashboard/src/__mocks__/fileMock.ts create mode 100644 dashboard/src/__mocks__/react-quill-new.tsx create mode 100644 dashboard/src/__mocks__/styleMock.ts create mode 100644 dashboard/src/__mocks__/table-layout-mock.tsx create mode 100644 dashboard/src/__tests__/apache-license-header.test.ts create mode 100644 dashboard/src/setupTests.simple.ts create mode 100644 dashboard/src/setupTests.ts create mode 100644 dashboard/src/utils/test-utils.tsx create mode 100644 dashboard/tsconfig.build.json create mode 100644 dashboard/tsconfig.test.json diff --git a/dashboard/.babelrc.json b/dashboard/.babelrc.json new file mode 100644 index 00000000000..a110ea138fa --- /dev/null +++ b/dashboard/.babelrc.json @@ -0,0 +1,10 @@ +{ + "presets": [ + ["@babel/preset-env", { "targets": { "node": "12" } }], + ["@babel/preset-react", { "runtime": "automatic" }], + ["@babel/preset-typescript", { "allExtensions": true, "isTSX": true }] + ] +} + + + diff --git a/dashboard/.eslintrc.cjs b/dashboard/.eslintrc.cjs index 0bc8d4b8247..34b4d8c20e1 100644 --- a/dashboard/.eslintrc.cjs +++ b/dashboard/.eslintrc.cjs @@ -45,5 +45,26 @@ module.exports = { "prefer-const": "off", "no-var": "off", "no-useless-catch": "warn" - } + }, + overrides: [ + { + files: [ + "**/__tests__/**/*.{ts,tsx}", + "**/*.{test,spec}.{ts,tsx}", + "**/setupTests*.ts", + "src/**/__mocks__/**/*.{ts,tsx}", + ], + env: { jest: true }, + rules: { + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/no-unused-vars": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/no-loss-of-precision": "off", + "no-extra-semi": "off", + "no-mixed-spaces-and-tabs": "off", + "react-hooks/rules-of-hooks": "off", + "react-hooks/exhaustive-deps": "off", + }, + }, + ], }; diff --git a/dashboard/.gitignore b/dashboard/.gitignore index 25a47d23450..cc821816ad3 100644 --- a/dashboard/.gitignore +++ b/dashboard/.gitignore @@ -26,5 +26,8 @@ node_modules/ dist/ .vite/ .env + +# Local Dependabot export for governance tests (optional) +config/dependabot-alerts.local.json *.log .vscode/ diff --git a/dashboard/jest.config.js b/dashboard/jest.config.js new file mode 100644 index 00000000000..22648e6e3da --- /dev/null +++ b/dashboard/jest.config.js @@ -0,0 +1,157 @@ +/* + * 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. + */ + +/** + * Jest configuration for the Atlas React dashboard + */ + +const runDependencyGovernance = process.env.RUN_DEPENDENCY_GOVERNANCE === '1' + +const config = { + preset: 'ts-jest/presets/js-with-ts', + testEnvironment: 'jsdom', + + // Test file patterns + testMatch: [ + '/src/**/__tests__/**/*.{ts,tsx}', + '/src/**/*.{test,spec}.{ts,tsx}' + ], + + // Setup files + setupFilesAfterEnv: ['/src/setupTests.simple.ts'], + + // Module name mapping for path aliases + moduleNameMapper: { + '^@/(.*)$': '/src/$1', + '^@components/(.*)$': '/src/components/$1', + '^@api/(.*)\.js$': '/src/api/$1.ts', + '^@api/(.*)$': '/src/api/$1', + '^@utils/(.*)\.js$': '/src/utils/$1.ts', + '^@utils/(.*)$': '/src/utils/$1', + '^@styles/(.*)$': '/src/styles/$1', + '^@services/(.*)$': '/src/services/$1', + '^@views/(.*)$': '/src/views/$1', + '^@hooks/(.*)$': '/src/hooks/$1', + '^@models/(.*)$': '/src/models/$1', + '^@contexts/(.*)$': '/src/contexts/$1', + '^@redux/(.*)$': '/src/redux/$1', + '\\.(css|less|scss|sass)$': '/src/__mocks__/styleMock.ts', + '\\.(jpg|jpeg|png|gif|svg|webp)$': '/src/__mocks__/fileMock.ts' + }, + + // File extensions to consider + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], + + // Transform files (updated ts-jest config format) + transform: { + '^.+\\.(ts|tsx)$': ['ts-jest', { + tsconfig: 'tsconfig.test.json' + }], + '^.+\\.(js|jsx|mjs|cjs)$': 'babel-jest' + }, + + // Files to ignore during transformation + // Allow transpiling ESM-only d3 transitive deps for jest.requireActual('d3') + transformIgnorePatterns: [ + 'node_modules/(?!(@testing-library|@adobe/css-tools|react-quill-new|d3|d3-[-\\w]+|internmap|.*\\.mjs$))' + ], + + // Module paths to ignore (exclude bin/, dist/, build/, target/) + modulePathIgnorePatterns: [ + '/bin/', + '/dist/', + '/build/', + '/target/' + ], + + testPathIgnorePatterns: [ + '/bin/', + '/dist/', + '/build/', + '/target/', + ...(runDependencyGovernance + ? [] + : ['/src/__tests__/governance/']) + ], + + // V8 avoids babel-plugin-istanbul + test-exclude, which breaks when npm + // overrides force minimatch@9 (minimatch is not a function in CJS). + coverageProvider: 'v8', + + // Coverage configuration (only collect when --coverage flag is used) + collectCoverage: false, + collectCoverageFrom: [ + 'src/**/*.{ts,tsx}', + '!src/**/*.d.ts', + '!src/**/__tests__/**', + '!src/**/*.test.{ts,tsx}', + '!src/**/*.spec.{ts,tsx}', + '!src/**/__mocks__/**', + '!src/**/setupTests*', + '!src/**/test-utils*' + ], + + coverageDirectory: 'coverage', + + coverageReporters: [ + 'text', + 'lcov', + 'html', + 'json-summary' + ], + + // Coverage thresholds + coverageThreshold: { + global: { + branches: 50, + functions: 50, + lines: 50, + statements: 50 + } + }, + + // Verbose output + verbose: true, + + // Clear mocks between tests + clearMocks: true, + + // Reset modules between tests + resetMocks: false, + + // Environment variables + testEnvironmentOptions: { + url: 'http://localhost:3000' + }, + + // Test timeout (prevent hanging tests) + testTimeout: 10000, // 10 seconds + + // Maximum number of concurrent workers + maxWorkers: '50%', + + // Bail on first failure (stop after first failing test suite) + bail: false, + + // Force exit after tests complete (prevent hanging) + forceExit: true, + + // Detect open handles that might prevent Jest from exiting + detectOpenHandles: false +}; + +export default config; \ No newline at end of file diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index 2f4b0684d66..f99afc97007 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -44,8 +44,15 @@ "sanitize-html": "2.17.4" }, "devDependencies": { + "@babel/preset-env": "7.28.5", + "@babel/preset-react": "7.28.5", + "@babel/preset-typescript": "7.28.5", + "@testing-library/jest-dom": "6.9.1", + "@testing-library/react": "14.3.1", + "@testing-library/user-event": "14.6.1", "@types/autosuggest-highlight": "3.2.3", "@types/d3": "5.16.5", + "@types/jest": "29.5.14", "@types/node": "20.11.25", "@types/react": "18.2.56", "@types/react-dom": "18.2.19", @@ -53,19 +60,27 @@ "@typescript-eslint/eslint-plugin": "7.0.2", "@typescript-eslint/parser": "7.0.2", "@vitejs/plugin-react-swc": "3.9.0", + "babel-jest": "29.7.0", "eslint": "8.56.0", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-react-refresh": "0.4.5", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", "recharts": "2.15.1", "sass": "1.74.1", + "semver": "7.5.4", + "ts-jest": "29.4.6", "typescript": "5.2.2", "vite": "6.4.2" } }, + "node_modules/@adobe/css-tools": { + "version": "4.4.4", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/code-frame": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", @@ -76,4986 +91,7808 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", - "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/parser": "^7.27.1", - "@babel/types": "^7.27.1", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "node_modules/@babel/core": { + "version": "7.28.5", + "dev": true, "license": "MIT", "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/generator": { + "version": "7.28.5", "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/parser": { + "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", - "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", + "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, - "bin": { - "parser": "bin/babel-parser.js" + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", - "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", - "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.27.1", - "@babel/parser": "^7.27.1", - "@babel/template": "^7.27.1", - "@babel/types": "^7.27.1", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/types": { + "node_modules/@babel/helper-module-imports": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@dnd-kit/accessibility": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz", - "integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==", + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.0.0" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "react": ">=16.8.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@dnd-kit/core": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.1.0.tgz", - "integrity": "sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==", + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@dnd-kit/accessibility": "^3.1.0", - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" + "@babel/types": "^7.27.1" }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@dnd-kit/modifiers": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-7.0.0.tgz", - "integrity": "sha512-BG/ETy3eBjFap7+zIti53f0PCLGDzNXyTmn6fSdrudORf+OH04MxrW4p5+mPu4mgMk9kM41iYONjc3DOUWTcfg==", + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@dnd-kit/core": "^6.1.0", - "react": ">=16.8.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@dnd-kit/sortable": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-8.0.0.tgz", - "integrity": "sha512-U3jk5ebVXe1Lr7c2wU7SBZjcWdQP+j7peHJfCspnA81enlu88Mgd7CC8Q+pub9ubP7eKVETzJW+IBAhsqbSu/g==", + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "@dnd-kit/core": "^6.1.0", - "react": ">=16.8.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@dnd-kit/utilities": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz", - "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==", + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.0.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, - "peerDependencies": { - "react": ">=16.8.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@emotion/babel-plugin": { - "version": "11.13.5", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", - "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/serialize": "^1.3.3", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@emotion/cache": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", - "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.9.0", - "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "stylis": "4.2.0" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@emotion/hash": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", - "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", - "license": "MIT" + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@emotion/is-prop-valid": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", - "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.3", + "dev": true, "license": "MIT", "dependencies": { - "@emotion/memoize": "^0.9.0" + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/@emotion/memoize": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", - "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", - "license": "MIT" + "node_modules/@babel/helpers": { + "version": "7.28.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/@emotion/react": { - "version": "11.11.4", - "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz", - "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==", + "node_modules/@babel/parser": { + "version": "7.28.5", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/cache": "^11.11.0", - "@emotion/serialize": "^1.1.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1", - "@emotion/weak-memoize": "^0.3.1", - "hoist-non-react-statics": "^3.3.1" + "@babel/types": "^7.28.5" }, - "peerDependencies": { - "react": ">=16.8.0" + "bin": { + "parser": "bin/babel-parser.js" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@emotion/react/node_modules/@emotion/weak-memoize": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", - "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==", - "license": "MIT" - }, - "node_modules/@emotion/serialize": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", - "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "dev": true, "license": "MIT", "dependencies": { - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.2", - "csstype": "^3.0.2" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@emotion/sheet": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", - "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", - "license": "MIT" - }, - "node_modules/@emotion/styled": { - "version": "11.11.0", - "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.0.tgz", - "integrity": "sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==", + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.11.0", - "@emotion/is-prop-valid": "^1.2.1", - "@emotion/serialize": "^1.1.2", - "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", - "@emotion/utils": "^1.2.1" + "@babel/helper-plugin-utils": "^7.27.1" }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" + "engines": { + "node": ">=6.9.0" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@emotion/unitless": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", - "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", - "license": "MIT" - }, - "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", - "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", - "license": "MIT", "peerDependencies": { - "react": ">=16.8.0" + "@babel/core": "^7.0.0" } }, - "node_modules/@emotion/utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", - "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", - "license": "MIT" - }, - "node_modules/@emotion/weak-memoize": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", - "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.4.3" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=6.9.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.5", "dev": true, "license": "MIT", "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=8" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.4", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.4" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/core": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.0.tgz", - "integrity": "sha512-FRdBLykrPPA6P76GGGqlex/e7fbe0F1ykgxHYNXQsH/iTEtjMj/f9bpY5oQqbjt5VgZvgz/uKXbGuROijh3VLA==", + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/dom": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.0.tgz", - "integrity": "sha512-lGTor4VlXcesUMh1cupTUTDoCxMb0V6bm3CnxHzQcw8Eaf1jQbgQX4i02fYgT0vJ82tb5MZ4CZk1LRGkktJCzg==", + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.0", - "@floating-ui/utils": "^0.2.9" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/react": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.8.tgz", - "integrity": "sha512-EQJ4Th328y2wyHR3KzOUOoTW2UKjFk53fmyahfwExnFQ8vnsMYqKc+fFPOkeYtj5tcp1DUMiNJ7BFhed7e9ONw==", + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/react-dom": "^2.1.2", - "@floating-ui/utils": "^0.2.9", - "tabbable": "^6.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "react": ">=17.0.0", - "react-dom": ">=17.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", - "license": "MIT" - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=10.10.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=12.22" + "node": ">=6.9.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.5", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=6.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/base": { - "version": "5.0.0-beta.40", - "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.40.tgz", - "integrity": "sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==", - "deprecated": "This package has been replaced by @base-ui-components/react", + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "@floating-ui/react-dom": "^2.0.8", - "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", - "@popperjs/core": "^2.11.8", - "clsx": "^2.1.0", - "prop-types": "^15.8.1" + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "node_modules/@mui/core-downloads-tracker": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.17.1.tgz", - "integrity": "sha512-OcZj+cs6EfUD39IoPBOgN61zf1XFVY+imsGoBDwXeSq2UHJZE3N59zzBOVjclck91Ne3e9gudONOeILvHCIhUA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/icons-material": { - "version": "5.15.15", - "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-5.15.15.tgz", - "integrity": "sha512-kkeU/pe+hABcYDH6Uqy8RmIsr2S/y5bP2rp+Gat4CcRjCcVne6KudS1NrZQhUCRysrTDCAhcbcf9gt+/+pGO2g==", + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@mui/material": "^5.0.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/material": { - "version": "5.15.15", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.15.15.tgz", - "integrity": "sha512-3zvWayJ+E1kzoIsvwyEvkTUKVKt1AjchFFns+JtluHCuvxgKcLSRJTADw37k0doaRtVAsyh8bz9Afqzv+KYrIA==", + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/base": "5.0.0-beta.40", - "@mui/core-downloads-tracker": "^5.15.15", - "@mui/system": "^5.15.15", - "@mui/types": "^7.2.14", - "@mui/utils": "^5.15.14", - "@types/react-transition-group": "^4.4.10", - "clsx": "^2.1.0", - "csstype": "^3.1.3", - "prop-types": "^15.8.1", - "react-is": "^18.2.0", - "react-transition-group": "^4.4.5" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/material/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" - }, - "node_modules/@mui/private-theming": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.17.1.tgz", - "integrity": "sha512-XMxU0NTYcKqdsG8LRmSoxERPXwMbp16sIXPcLVgLGII/bVNagX0xaheWAwFv8+zDK7tI3ajllkuD3GZZE++ICQ==", + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.5", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/utils": "^5.17.1", - "prop-types": "^15.8.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/styled-engine": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.18.0.tgz", - "integrity": "sha512-BN/vKV/O6uaQh2z5rXV+MBlVrEkwoS/TK75rFQ2mjxA7+NBo8qtTAOA4UaM0XeJfn7kh2wZ+xQw2HAx0u+TiBg==", + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "@emotion/cache": "^11.13.5", - "@emotion/serialize": "^1.3.3", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/system": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.18.0.tgz", - "integrity": "sha512-ojZGVcRWqWhu557cdO3pWHloIGJdzVtxs3rk0F9L+x55LsUjcMUVkEhiF7E4TMxZoF9MmIHGGs0ZX3FDLAf0Xw==", + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/private-theming": "^5.17.1", - "@mui/styled-engine": "^5.18.0", - "@mui/types": "~7.2.15", - "@mui/utils": "^5.17.1", - "clsx": "^2.1.0", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/types": { - "version": "7.2.24", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz", - "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==", + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "dev": true, "license": "MIT", - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/utils": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.17.1.tgz", - "integrity": "sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg==", + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.28.5", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "@mui/types": "~7.2.15", - "@types/prop-types": "^15.7.12", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^19.0.0" + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.5" }, "engines": { - "node": ">=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@mui/x-tree-view": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@mui/x-tree-view/-/x-tree-view-7.0.0.tgz", - "integrity": "sha512-9nus8fesjBT/V/SzjZKhABG3qvGtupkccoOnz43ebLts8MSYtR8jwnOMArwrVnzrEoaS4F4dv3M8SYVQkHWfaQ==", + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.24.0", - "@mui/base": "^5.0.0-beta.40", - "@mui/system": "^5.15.14", - "@mui/utils": "^5.15.14", - "@types/react-transition-group": "^4.4.10", - "clsx": "^2.1.0", - "prop-types": "^15.8.1", - "react-transition-group": "^4.4.5" + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" + "node": ">=6.9.0" }, "peerDependencies": { - "@emotion/react": "^11.9.0", - "@emotion/styled": "^11.8.1", - "@mui/material": "^5.15.14", - "react": "^17.0.0 || ^18.0.0", - "react-dom": "^17.0.0 || ^18.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { - "node": ">= 8" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", - "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "dev": true, "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@react-querybuilder/material": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@react-querybuilder/material/-/material-8.0.0.tgz", - "integrity": "sha512-TquBZME17SON5ZDFv3EweLTmdyRJZDFJzkQIJjUqDf1oGLjSAkFJ1f4ohbPAXweVVmBNUeE116ClFAKp3L0uyQ==", + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.4", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + }, "peerDependencies": { - "@emotion/react": "^11", - "@emotion/styled": "^11", - "@mui/icons-material": ">=5", - "@mui/material": ">=5", - "react": ">=18", - "react-querybuilder": "8.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@reduxjs/toolkit": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.2.6.tgz", - "integrity": "sha512-kH0r495c5z1t0g796eDQAkYbEQ3a1OLYN9o8jQQVZyKyw367pfRGS+qZLkHYvFHiUUdafpoSlQ2QYObIApjPWA==", + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "dev": true, "license": "MIT", "dependencies": { - "immer": "^10.0.3", - "redux": "^5.0.1", - "redux-thunk": "^3.1.0", - "reselect": "^5.1.0" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" }, "peerDependencies": { - "react": "^16.9.0 || ^17.0.0 || ^18", - "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" }, - "peerDependenciesMeta": { - "react": { - "optional": true - }, - "react-redux": { - "optional": true - } + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@remix-run/router": { - "version": "1.23.2", - "resolved": "https://registry.npmmirror.com/@remix-run/router/-/router-1.23.2.tgz", - "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==", + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.5", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, "engines": { - "node": ">=14.0.0" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ] + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.28.0", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.4", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.28.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.5", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.4", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.28.5", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.28.5", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.4", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.4", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/preset-react": { + "version": "7.28.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-transform-react-display-name": "^7.28.0", + "@babel/plugin-transform-react-jsx": "^7.27.1", + "@babel/plugin-transform-react-jsx-development": "^7.27.1", + "@babel/plugin-transform-react-pure-annotations": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/preset-typescript": { + "version": "7.28.5", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@standard-schema/spec": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", - "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", - "license": "MIT" - }, - "node_modules/@standard-schema/utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", - "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", - "license": "MIT" - }, - "node_modules/@swc/core": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.24.tgz", - "integrity": "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==", - "dev": true, - "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.21" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5" }, "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.11.24", - "@swc/core-darwin-x64": "1.11.24", - "@swc/core-linux-arm-gnueabihf": "1.11.24", - "@swc/core-linux-arm64-gnu": "1.11.24", - "@swc/core-linux-arm64-musl": "1.11.24", - "@swc/core-linux-x64-gnu": "1.11.24", - "@swc/core-linux-x64-musl": "1.11.24", - "@swc/core-win32-arm64-msvc": "1.11.24", - "@swc/core-win32-ia32-msvc": "1.11.24", - "@swc/core-win32-x64-msvc": "1.11.24" + "node": ">=6.9.0" }, "peerDependencies": { - "@swc/helpers": ">=0.5.17" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } + "@babel/core": "^7.0.0-0" } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz", - "integrity": "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/runtime": { + "version": "7.27.1", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz", - "integrity": "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "darwin" - ], + "node_modules/@babel/template": { + "version": "7.27.2", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz", - "integrity": "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz", - "integrity": "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz", - "integrity": "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz", - "integrity": "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/traverse": { + "version": "7.28.5", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz", - "integrity": "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "linux" - ], + "node_modules/@babel/types": { + "version": "7.28.5", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, "engines": { - "node": ">=10" + "node": ">=6.9.0" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz", - "integrity": "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==", - "cpu": [ - "arm64" - ], + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz", - "integrity": "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" + "node_modules/@dnd-kit/accessibility": { + "version": "3.1.1", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" } }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz", - "integrity": "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "Apache-2.0 AND MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" + "node_modules/@dnd-kit/core": { + "version": "6.1.0", + "license": "MIT", + "dependencies": { + "@dnd-kit/accessibility": "^3.1.0", + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/@swc/types": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz", - "integrity": "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==", - "dev": true, - "license": "Apache-2.0", + "node_modules/@dnd-kit/modifiers": { + "version": "7.0.0", + "license": "MIT", "dependencies": { - "@swc/counter": "^0.1.3" + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.1.0", + "react": ">=16.8.0" } }, - "node_modules/@tanstack/react-table": { - "version": "8.15.3", - "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.15.3.tgz", - "integrity": "sha512-aocQ4WpWiAh7R+yxNp+DGQYXeVACh5lv2kk96DjYgFiHDCB0cOFoYMT/pM6eDOzeMXR9AvPoLeumTgq8/0qX+w==", + "node_modules/@dnd-kit/sortable": { + "version": "8.0.0", "license": "MIT", "dependencies": { - "@tanstack/table-core": "8.15.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" }, "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" + "@dnd-kit/core": "^6.1.0", + "react": ">=16.8.0" } }, - "node_modules/@tanstack/table-core": { - "version": "8.15.3", - "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.15.3.tgz", - "integrity": "sha512-wOgV0HfEvuMOv8RlqdR9MdNNqq0uyvQtP39QOvGlggHvIObOE4exS+D5LGO8LZ3LUXxId2IlUKcHDHaGujWhUg==", + "node_modules/@dnd-kit/utilities": { + "version": "3.2.2", "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "tslib": "^2.0.0" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" + "peerDependencies": { + "react": ">=16.8.0" } }, - "node_modules/@types/autosuggest-highlight": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@types/autosuggest-highlight/-/autosuggest-highlight-3.2.3.tgz", - "integrity": "sha512-8Mb21KWtpn6PvRQXjsKhrXIcxbSloGqNH50RntwGeJsGPW4xvNhfml+3kKulaKpO/7pgZfOmzsJz7VbepArlGQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3": { - "version": "5.16.5", - "resolved": "https://registry.npmmirror.com/@types/d3/-/d3-5.16.5.tgz", - "integrity": "sha512-Wk49gITZbuxW8BdF1fe882c4BKcwQNPCts/2d9XszS9y0/eJDNXxF/f91ciAApI3TiSraEUp9Ncx7oV2KBLgBg==", - "dev": true, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", "license": "MIT", "dependencies": { - "@types/d3-array": "^1", - "@types/d3-axis": "^1", - "@types/d3-brush": "^1", - "@types/d3-chord": "^1", - "@types/d3-collection": "*", - "@types/d3-color": "^1", - "@types/d3-contour": "^1", - "@types/d3-dispatch": "^1", - "@types/d3-drag": "^1", - "@types/d3-dsv": "^1", - "@types/d3-ease": "^1", - "@types/d3-fetch": "^1", - "@types/d3-force": "^1", - "@types/d3-format": "^1", - "@types/d3-geo": "^1", - "@types/d3-hierarchy": "^1", - "@types/d3-interpolate": "^1", - "@types/d3-path": "^1", - "@types/d3-polygon": "^1", - "@types/d3-quadtree": "^1", - "@types/d3-random": "^1", - "@types/d3-scale": "^2", - "@types/d3-scale-chromatic": "^1", - "@types/d3-selection": "^1", - "@types/d3-shape": "^1", - "@types/d3-time": "^1", - "@types/d3-time-format": "^2", - "@types/d3-timer": "^1", - "@types/d3-transition": "^1", - "@types/d3-voronoi": "*", - "@types/d3-zoom": "^1" + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" } }, - "node_modules/@types/d3-array": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", - "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-axis": { - "version": "1.0.19", - "resolved": "https://registry.npmmirror.com/@types/d3-axis/-/d3-axis-1.0.19.tgz", - "integrity": "sha512-rXxE2jJYv6kar/6YWS8rM0weY+jjvnJvBxHKrIUqt3Yzomrfbf5tncpKG6jq6Aaw6TZyBcb1bxEWc0zGzcmbiw==", - "dev": true, + "node_modules/@emotion/cache": { + "version": "11.14.0", "license": "MIT", "dependencies": { - "@types/d3-selection": "^1" + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" } }, - "node_modules/@types/d3-brush": { - "version": "1.1.8", - "resolved": "https://registry.npmmirror.com/@types/d3-brush/-/d3-brush-1.1.8.tgz", - "integrity": "sha512-tPVjYAjJt02fgazF9yiX/309sj6qhIiIopLuHhP4FFFq9VKqu9NQBeCK3ger0RHVZGs9RKaSBUWyPUzii5biGQ==", - "dev": true, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", "license": "MIT", "dependencies": { - "@types/d3-selection": "^1" + "@emotion/memoize": "^0.9.0" } }, - "node_modules/@types/d3-chord": { - "version": "1.0.14", - "resolved": "https://registry.npmmirror.com/@types/d3-chord/-/d3-chord-1.0.14.tgz", - "integrity": "sha512-W9rCIbSAhwtmydW5iGg9dwTQIi3SGBOh68/T3ke3PyOgejuSLozmtAMaWNViGaGJCeuM4aFJHTUHQvMedl4ugA==", - "dev": true, + "node_modules/@emotion/memoize": { + "version": "0.9.0", "license": "MIT" }, - "node_modules/@types/d3-collection": { - "version": "1.0.13", - "resolved": "https://registry.npmmirror.com/@types/d3-collection/-/d3-collection-1.0.13.tgz", - "integrity": "sha512-v0Rgw3IZebRyamcwVmtTDCZ8OmQcj4siaYjNc7wGMZT7PmdSHawGsCOQMxyLvZ7lWjfohYLK0oXtilMOMgfY8A==", - "dev": true, - "license": "MIT" + "node_modules/@emotion/react": { + "version": "11.11.4", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "node_modules/@types/d3-color": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", - "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", - "dev": true, + "node_modules/@emotion/react/node_modules/@emotion/weak-memoize": { + "version": "0.3.1", "license": "MIT" }, - "node_modules/@types/d3-contour": { - "version": "1.3.6", - "resolved": "https://registry.npmmirror.com/@types/d3-contour/-/d3-contour-1.3.6.tgz", - "integrity": "sha512-RM/QHCx8j1ovj/p4cWCM3b48EIas6TTmfG+LR2Ud8npTqgrWTjMNCpHtoj47Qa3dJsifONXGu54VuFkXWL2mIg==", - "dev": true, + "node_modules/@emotion/serialize": { + "version": "1.3.3", "license": "MIT", "dependencies": { - "@types/d3-array": "^1", - "@types/geojson": "*" + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" } }, - "node_modules/@types/d3-contour/node_modules/@types/d3-array": { - "version": "1.2.12", - "resolved": "https://registry.npmmirror.com/@types/d3-array/-/d3-array-1.2.12.tgz", - "integrity": "sha512-zIq9wCg/JO7MGC6vq3HRDaVYkqgSPIDjpo3JhAQxl7PHYVPA5D9SMiBfjW/ZoAvPd2a+rkovqBg0nS0QOChsJQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-dispatch": { - "version": "1.0.12", - "resolved": "https://registry.npmmirror.com/@types/d3-dispatch/-/d3-dispatch-1.0.12.tgz", - "integrity": "sha512-vrhleoVNhGJGx7GQZ4207lYGyMbW/yj/iJTSvLKyfAp8nXFF+19dnMpPN/nEVs6fudIsQc7ZelBFUMe3aJDmKw==", - "dev": true, + "node_modules/@emotion/sheet": { + "version": "1.4.0", "license": "MIT" }, - "node_modules/@types/d3-drag": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/@types/d3-drag/-/d3-drag-1.2.8.tgz", - "integrity": "sha512-QM6H8E6r9/51BcE4NEluQ0f9dTECCTDEALJSQIWn183+Mtz/6KvEjOxW8VzKYSnhhL+qMljMKKA1WOUUf/4Qhw==", - "dev": true, + "node_modules/@emotion/styled": { + "version": "11.11.0", "license": "MIT", "dependencies": { - "@types/d3-selection": "^1" + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.11.0", + "@emotion/is-prop-valid": "^1.2.1", + "@emotion/serialize": "^1.1.2", + "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", + "@emotion/utils": "^1.2.1" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/@types/d3-dsv": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/@types/d3-dsv/-/d3-dsv-1.2.8.tgz", - "integrity": "sha512-x1m1s0lVstZQ5/Kzp4bVIMee3fFuDm+hphVnvrYA7wU16XqwgbCBfeVvHYZzVQQIy4jyi3MEtgduLVuwIRCKLQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", - "dev": true, + "node_modules/@emotion/unitless": { + "version": "0.10.0", "license": "MIT" }, - "node_modules/@types/d3-fetch": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/@types/d3-fetch/-/d3-fetch-1.2.5.tgz", - "integrity": "sha512-5SpBGkHtH01Zi5gMGfEXZp72NcQJB83uskIrlj9N0z9w4vVP7dHIgDu3v8BLhhqn8Oj98wuIrlatdiYK3+q3tA==", - "dev": true, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", "license": "MIT", - "dependencies": { - "@types/d3-dsv": "^1" + "peerDependencies": { + "react": ">=16.8.0" } }, - "node_modules/@types/d3-force": { - "version": "1.2.7", - "resolved": "https://registry.npmmirror.com/@types/d3-force/-/d3-force-1.2.7.tgz", - "integrity": "sha512-zySqZfnxn67RVEGWzpD9dQA0AbNIp4Rj0qGvAuUdUNfGLrwuGCbEGAGze5hEdNaHJKQT2gTqr6j+qAzncm11ew==", - "dev": true, + "node_modules/@emotion/utils": { + "version": "1.4.2", "license": "MIT" }, - "node_modules/@types/d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/@types/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-mLxrC1MSWupOSncXN/HOlWUAAIffAEBaI4+PKy2uMPsKe4FNZlk7qrbTjmzJXITQQqBHivaks4Td18azgqnotA==", - "dev": true, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", "license": "MIT" }, - "node_modules/@types/d3-geo": { - "version": "1.12.7", - "resolved": "https://registry.npmmirror.com/@types/d3-geo/-/d3-geo-1.12.7.tgz", - "integrity": "sha512-QetZrWWjuMfCe0BHLjD+dOThlgk7YGZ2gj+yhFAbDN5TularNBEQiBs5/CIgX0+IBDjt7/fbkDd5V70J1LjjKA==", + "node_modules/@esbuild/linux-x64": { + "version": "0.25.4", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/geojson": "*" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@types/d3-hierarchy": { - "version": "1.1.11", - "resolved": "https://registry.npmmirror.com/@types/d3-hierarchy/-/d3-hierarchy-1.1.11.tgz", - "integrity": "sha512-lnQiU7jV+Gyk9oQYk0GGYccuexmQPTp08E0+4BidgFdiJivjEvf+esPSdZqCZ2C7UwTWejWpqetVaU8A+eX3FA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-interpolate": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", - "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", "dev": true, "license": "MIT", "dependencies": { - "@types/d3-color": "*" + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@types/d3-path": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", - "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-polygon": { - "version": "1.0.10", - "resolved": "https://registry.npmmirror.com/@types/d3-polygon/-/d3-polygon-1.0.10.tgz", - "integrity": "sha512-+hbHsFdCMs23vk9p/SpvIkHkCpl0vxkP2qWR2vEk0wRi0BXODWgB/6aHnfrz/BeQnk20XzZiQJIZ+11TGxuYMQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-quadtree": { - "version": "1.0.13", - "resolved": "https://registry.npmmirror.com/@types/d3-quadtree/-/d3-quadtree-1.0.13.tgz", - "integrity": "sha512-BAQD6gTHnXqmI7JRhXwM2pEYJJF27AT1f6zCC192BKAUhigzd5HZjdje5ufRXmYcUM/fr2IJ9KqVMeXaljmmOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-random": { - "version": "1.1.5", - "resolved": "https://registry.npmmirror.com/@types/d3-random/-/d3-random-1.1.5.tgz", - "integrity": "sha512-gB5CR+7xYMj56pt5zmSyDBjTNMEy96PdfUb2qBaAT9bmPcf4P/YHfhhTI5y8JoiqaSRLJY+3mqtaE9loBgB6Ng==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", "dev": true, "license": "MIT", - "dependencies": { - "@types/d3-time": "*" + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@types/d3-scale-chromatic": { - "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-1.5.4.tgz", - "integrity": "sha512-HwLVEm8laYTNOR9Kc9745XDKgRa69VIIChNkSKJgrJOsDLI9QSiFSH2Bi4wMbGrvFs+X64azev7NfBPq+VOFVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-selection": { - "version": "1.4.7", - "resolved": "https://registry.npmmirror.com/@types/d3-selection/-/d3-selection-1.4.7.tgz", - "integrity": "sha512-aLaTOjdOJEFPhij59NdNwppvpHBheZFlLbcb7cIZZYLC0he9Wmdd/u4+1NZxlr7ncK+mq1PLmowMPw1GONrIQg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-shape": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", - "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", "dev": true, "license": "MIT", "dependencies": { - "@types/d3-path": "*" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@types/d3-time": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", - "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-time-format": { - "version": "2.3.4", - "resolved": "https://registry.npmmirror.com/@types/d3-time-format/-/d3-time-format-2.3.4.tgz", - "integrity": "sha512-xdDXbpVO74EvadI3UDxjxTdR6QIxm1FKzEA/+F8tL4GWWUg/hgvBqf6chql64U5A9ZUGWo7pEu4eNlyLwbKdhg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-transition": { - "version": "1.3.6", - "resolved": "https://registry.npmmirror.com/@types/d3-transition/-/d3-transition-1.3.6.tgz", - "integrity": "sha512-Y8NwxuHV4ElbCkN7tJcuwENYKiAL+ktU6tNDLHqZ141YsaT3kwa5ZA5eqiJwHYWQzXMjF+FgL6/Sxo9IGSwmNQ==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", "dev": true, "license": "MIT", "dependencies": { - "@types/d3-selection": "^1" + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/d3-voronoi": { - "version": "1.1.12", - "resolved": "https://registry.npmmirror.com/@types/d3-voronoi/-/d3-voronoi-1.1.12.tgz", - "integrity": "sha512-DauBl25PKZZ0WVJr42a6CNvI6efsdzofl9sajqZr2Gf5Gu733WkDdUGiPkUHXiUvYGzNNlFQde2wdZdfQPG+yw==", + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", "dev": true, - "license": "MIT" + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "node_modules/@types/d3-zoom": { - "version": "1.8.7", - "resolved": "https://registry.npmmirror.com/@types/d3-zoom/-/d3-zoom-1.8.7.tgz", - "integrity": "sha512-HJWci3jXwFIuFKDqGn5PmuwrhZvuFdrnUmtSKCLXFAWyf2lAIUKMKh1/lHOkWBl/f4KVupGricJiqkQy+cVTog==", + "node_modules/@eslint/js": { + "version": "8.56.0", "dev": true, "license": "MIT", - "dependencies": { - "@types/d3-interpolate": "^1", - "@types/d3-selection": "^1" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@types/d3-zoom/node_modules/@types/d3-color": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/@types/d3-color/-/d3-color-1.4.5.tgz", - "integrity": "sha512-5sNP3DmtSnSozxcjqmzQKsDOuVJXZkceo1KJScDc1982kk/TS9mTPc6lpli1gTu1MIBF1YWutpHpjucNWcIj5g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-zoom/node_modules/@types/d3-interpolate": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-1.4.5.tgz", - "integrity": "sha512-k9L18hXXv7OvK4PqW1kSFYIzasGOvfhPUWmHFkoZ8/ci99EAmY4HoF6zMefrHl0SGV7XYc7Qq2MNh8dK3edg5A==", - "dev": true, + "node_modules/@floating-ui/core": { + "version": "1.7.0", "license": "MIT", "dependencies": { - "@types/d3-color": "^1" + "@floating-ui/utils": "^0.2.9" } }, - "node_modules/@types/d3/node_modules/@types/d3-array": { - "version": "1.2.12", - "resolved": "https://registry.npmmirror.com/@types/d3-array/-/d3-array-1.2.12.tgz", - "integrity": "sha512-zIq9wCg/JO7MGC6vq3HRDaVYkqgSPIDjpo3JhAQxl7PHYVPA5D9SMiBfjW/ZoAvPd2a+rkovqBg0nS0QOChsJQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3/node_modules/@types/d3-color": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/@types/d3-color/-/d3-color-1.4.5.tgz", - "integrity": "sha512-5sNP3DmtSnSozxcjqmzQKsDOuVJXZkceo1KJScDc1982kk/TS9mTPc6lpli1gTu1MIBF1YWutpHpjucNWcIj5g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3/node_modules/@types/d3-ease": { - "version": "1.0.13", - "resolved": "https://registry.npmmirror.com/@types/d3-ease/-/d3-ease-1.0.13.tgz", - "integrity": "sha512-VAA4H8YNaNN0+UNIlpkwkLOj7xL5EGdyiQpdlAvOIRHckjGFCLK8eMoUd4+IMNEhQgweq0Yk/Dfzr70xhUo6hA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3/node_modules/@types/d3-interpolate": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/@types/d3-interpolate/-/d3-interpolate-1.4.5.tgz", - "integrity": "sha512-k9L18hXXv7OvK4PqW1kSFYIzasGOvfhPUWmHFkoZ8/ci99EAmY4HoF6zMefrHl0SGV7XYc7Qq2MNh8dK3edg5A==", - "dev": true, + "node_modules/@floating-ui/dom": { + "version": "1.7.0", "license": "MIT", "dependencies": { - "@types/d3-color": "^1" + "@floating-ui/core": "^1.7.0", + "@floating-ui/utils": "^0.2.9" } }, - "node_modules/@types/d3/node_modules/@types/d3-path": { - "version": "1.0.11", - "resolved": "https://registry.npmmirror.com/@types/d3-path/-/d3-path-1.0.11.tgz", - "integrity": "sha512-4pQMp8ldf7UaB/gR8Fvvy69psNHkTpD/pVw3vmEi8iZAB9EPMBruB1JvHO4BIq9QkUUd2lV1F5YXpMNj7JPBpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3/node_modules/@types/d3-scale": { - "version": "2.2.10", - "resolved": "https://registry.npmmirror.com/@types/d3-scale/-/d3-scale-2.2.10.tgz", - "integrity": "sha512-j4V7qQ+CQzK2KpvI5NDejdPAcds+fTzNGqWXrCXv1zNR33HRir0bMdhzN1OHDQLNXYffW/zOr3FOS2qlHDEgrw==", - "dev": true, + "node_modules/@floating-ui/react": { + "version": "0.27.8", "license": "MIT", "dependencies": { - "@types/d3-time": "^1" + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.9", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" } }, - "node_modules/@types/d3/node_modules/@types/d3-shape": { - "version": "1.3.12", - "resolved": "https://registry.npmmirror.com/@types/d3-shape/-/d3-shape-1.3.12.tgz", - "integrity": "sha512-8oMzcd4+poSLGgV0R1Q1rOlx/xdmozS4Xab7np0eamFFUYq71AU9pOCJEFnkXW2aI/oXdVYJzw6pssbSut7Z9Q==", - "dev": true, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.2", "license": "MIT", "dependencies": { - "@types/d3-path": "^1" + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" } }, - "node_modules/@types/d3/node_modules/@types/d3-time": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/@types/d3-time/-/d3-time-1.1.4.tgz", - "integrity": "sha512-JIvy2HjRInE+TXOmIGN5LCmeO0hkFZx5f9FZ7kiN+D+YTcc8pptsiLiuHsvwxwC7VVKmJ2ExHUgNlAiV7vQM9g==", - "dev": true, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", "license": "MIT" }, - "node_modules/@types/d3/node_modules/@types/d3-timer": { - "version": "1.0.12", - "resolved": "https://registry.npmmirror.com/@types/d3-timer/-/d3-timer-1.0.12.tgz", - "integrity": "sha512-Tv9tkA4y3UvGQnrHyYAQhf5x/297FuYwotS4UW2TpwLblvRahbyL8r9HFYTJLPfPRqS63hwlqRItjKGmKtJxNg==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", "dev": true, - "license": "MIT" + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, - "node_modules/@types/geojson": { - "version": "7946.0.16", - "resolved": "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.16.tgz", - "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, - "node_modules/@types/history": { - "version": "4.7.11", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", - "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", "dev": true, - "license": "MIT" - }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.6.tgz", - "integrity": "sha512-lPByRJUer/iN/xa4qpyL0qmL11DqNW81iU/IG1S3uvRUq4oKagz8VCxZjiWkumgt66YT3vOdDgZ0o32sGKtCEw==", - "license": "MIT", + "license": "ISC", "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "license": "MIT" - }, - "node_modules/@types/prop-types": { - "version": "15.7.14", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", - "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.2.56", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.56.tgz", - "integrity": "sha512-NpwHDMkS/EFZF2dONFQHgkPRwhvgq/OAvIaGQzxGSBmaeR++kTg6njr15Vatz0/2VcCEwJQFi6Jf4Q0qBu0rLA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", - "@types/scheduler": "*", - "csstype": "^3.0.2" + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/react-dom": { - "version": "18.2.19", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.19.tgz", - "integrity": "sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", "dev": true, "license": "MIT", "dependencies": { - "@types/react": "*" + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@types/react-redux": { - "version": "7.1.33", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", - "integrity": "sha512-NF8m5AjWCkert+fosDsN3hAlHzpjSiXlVy9EgQEmLoBhaNXbmyeGs/aj5dQzKuF+/q+S7JQagorGDW8pJ28Hmg==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, "license": "MIT", "dependencies": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/@types/react-redux/node_modules/redux": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", - "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.9.2" + "engines": { + "node": ">=8" } }, - "node_modules/@types/react-router": { - "version": "5.1.20", - "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", - "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", "dev": true, "license": "MIT", - "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*" + "engines": { + "node": ">=8" } }, - "node_modules/@types/react-router-dom": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", - "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "node_modules/@jest/console": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "@types/history": "^4.7.11", - "@types/react": "*", - "@types/react-router": "*" + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@types/react-transition-group": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", - "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "node_modules/@jest/core": { + "version": "29.7.0", + "dev": true, "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, "peerDependencies": { - "@types/react": "*" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/@types/sanitize-html": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.13.0.tgz", - "integrity": "sha512-X31WxbvW9TjIhZZNyNBZ/p5ax4ti7qsNDBDEnH4zAgmEh35YnFD1UiS6z9Cd34kKm0LslFW0KPmTQzu/oGtsqQ==", + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, "license": "MIT", - "dependencies": { - "htmlparser2": "^8.0.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@types/scheduler": { - "version": "0.26.0", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.26.0.tgz", - "integrity": "sha512-WFHp9YUJQ6CKshqoC37iOlHnQSmxNc795UhB26CyBBttrN9svdIrUjl/NjnNmfcwtncN0h/0PPAFWv9ovP8mLA==", - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "node_modules/@jest/core/node_modules/pretty-format": { + "version": "29.7.0", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz", - "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==", + "node_modules/@jest/core/node_modules/react-is": { + "version": "18.3.1", + "dev": true, "license": "MIT" }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz", - "integrity": "sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg==", + "node_modules/@jest/environment": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/type-utils": "7.0.2", - "@typescript-eslint/utils": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.4", - "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@jest/expect": { + "version": "29.7.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@jest/expect-utils": { + "version": "29.7.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "jest-get-type": "^29.6.3" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/parser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", - "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", + "node_modules/@jest/fake-timers": { + "version": "29.7.0", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", - "debug": "^4.3.4" + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", - "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "node_modules/@jest/globals": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz", - "integrity": "sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ==", + "node_modules/@jest/reporters": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.0.2", - "@typescript-eslint/utils": "7.0.2", - "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "eslint": "^8.56.0" + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, "peerDependenciesMeta": { - "typescript": { + "node-notifier": { "optional": true } } }, - "node_modules/@typescript-eslint/types": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", - "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", - "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "node_modules/@jest/reporters/node_modules/glob": { + "version": "7.2.3", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/visitor-keys": "7.0.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "*" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", "dependencies": { - "yallist": "^4.0.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { "node": ">=10" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@jest/schemas": { + "version": "29.6.3", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@sinclair/typebox": "^0.27.8" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/utils": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.2.tgz", - "integrity": "sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw==", + "node_modules/@jest/source-map": { + "version": "29.6.3", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.0.2", - "@typescript-eslint/types": "7.0.2", - "@typescript-eslint/typescript-estree": "7.0.2", - "semver": "^7.5.4" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@jest/test-result": { + "version": "29.7.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", - "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "node_modules/@jest/transform": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.0.2", - "eslint-visitor-keys": "^3.4.1" + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@jest/transform/node_modules/signal-exit": { + "version": "3.0.7", "dev": true, "license": "ISC" }, - "node_modules/@vitejs/plugin-react-swc": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.9.0.tgz", - "integrity": "sha512-jYFUSXhwMCYsh/aQTgSGLIN3Foz5wMbH9ahb0Zva//UzwZYbMiZd7oT3AU9jHT9DLswYDswsRwPU9jVF3yA48Q==", + "node_modules/@jest/transform/node_modules/write-file-atomic": { + "version": "4.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@swc/core": "^1.11.21" + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" }, - "peerDependencies": { - "vite": "^4 || ^5 || ^6" + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "node_modules/@jest/types": { + "version": "29.6.3", "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=0.4.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mui/base": { + "version": "5.0.0-beta.40", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@floating-ui/react-dom": "^2.0.8", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@popperjs/core": "^2.11.8", + "clsx": "^2.1.0", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", + "node_modules/@mui/core-downloads-tracker": { + "version": "5.17.1", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "5.15.15", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@babel/runtime": "^7.23.9" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^5.0.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, + "node_modules/@mui/material": { + "version": "5.15.15", "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/base": "5.0.0-beta.40", + "@mui/core-downloads-tracker": "^5.15.15", + "@mui/system": "^5.15.15", + "@mui/types": "^7.2.14", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^18.2.0", + "react-transition-group": "^4.4.5" + }, "engines": { - "node": ">=8" + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "node_modules/@mui/material/node_modules/react-is": { + "version": "18.3.1", "license": "MIT" }, - "node_modules/attr-accept": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", - "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/autosuggest-highlight": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/autosuggest-highlight/-/autosuggest-highlight-3.3.4.tgz", - "integrity": "sha512-j6RETBD2xYnrVcoV1S5R4t3WxOlWZKyDQjkwnggDPSjF5L4jV98ZltBpvPvbkM1HtoSe5o+bNrTHyjPbieGeYA==", + "node_modules/@mui/private-theming": { + "version": "5.17.1", "license": "MIT", "dependencies": { - "remove-accents": "^0.4.2" + "@babel/runtime": "^7.23.9", + "@mui/utils": "^5.17.1", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/axios": { - "version": "1.15.2", - "resolved": "https://registry.npmmirror.com/axios/-/axios-1.15.2.tgz", - "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==", + "node_modules/@mui/styled-engine": { + "version": "5.18.0", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.11", - "form-data": "^4.0.5", - "proxy-from-env": "^2.1.0" + "@babel/runtime": "^7.23.9", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } } }, - "node_modules/babel-plugin-macros": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", - "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "node_modules/@mui/system": { + "version": "5.18.0", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" + "@babel/runtime": "^7.23.9", + "@mui/private-theming": "^5.17.1", + "@mui/styled-engine": "^5.18.0", + "@mui/types": "~7.2.15", + "@mui/utils": "^5.17.1", + "clsx": "^2.1.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" }, "engines": { - "node": ">=10", - "npm": ">=6" + "node": ">=12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } } }, - "node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, + "node_modules/@mui/types": { + "version": "7.2.24", "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, + "node_modules/@mui/utils": { + "version": "5.17.1", "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@mui/types": "~7.2.15", + "@types/prop-types": "^15.7.12", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.0.0" + }, "engines": { - "node": ">=8" + "node": ">=12.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } } }, - "node_modules/brace-expansion": { - "version": "5.0.3", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.3.tgz", - "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", - "dev": true, + "node_modules/@mui/x-tree-view": { + "version": "7.0.0", "license": "MIT", "dependencies": { - "balanced-match": "^4.0.2" + "@babel/runtime": "^7.24.0", + "@mui/base": "^5.0.0-beta.40", + "@mui/system": "^5.15.14", + "@mui/utils": "^5.15.14", + "@types/react-transition-group": "^4.4.10", + "clsx": "^2.1.0", + "prop-types": "^15.8.1", + "react-transition-group": "^4.4.5" }, "engines": { - "node": "18 || 20 || >=22" + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.9.0", + "@emotion/styled": "^11.8.1", + "@mui/material": "^5.15.14", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, "engines": { - "node": ">=8" + "node": ">= 8" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, "engines": { - "node": ">= 0.4" + "node": ">= 8" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, "engines": { - "node": ">=6" + "node": ">= 8" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-querybuilder/material": { + "version": "8.0.0", + "license": "MIT", + "peerDependencies": { + "@emotion/react": "^11", + "@emotion/styled": "^11", + "@mui/icons-material": ">=5", + "@mui/material": ">=5", + "react": ">=18", + "react-querybuilder": "8.0.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.2.6", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" }, - "engines": { - "node": ">=10" + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } } }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/@remix-run/router": { + "version": "1.23.2", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "license": "MIT" + }, + "node_modules/@swc/core": { + "version": "1.11.24", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.21" }, "engines": { - "node": ">= 8.10.0" + "node": ">=10" }, "funding": { - "url": "https://paulmillr.com/funding/" + "type": "opencollective", + "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "@swc/core-darwin-arm64": "1.11.24", + "@swc/core-darwin-x64": "1.11.24", + "@swc/core-linux-arm-gnueabihf": "1.11.24", + "@swc/core-linux-arm64-gnu": "1.11.24", + "@swc/core-linux-arm64-musl": "1.11.24", + "@swc/core-linux-x64-gnu": "1.11.24", + "@swc/core-linux-x64-musl": "1.11.24", + "@swc/core-win32-arm64-msvc": "1.11.24", + "@swc/core-win32-ia32-msvc": "1.11.24", + "@swc/core-win32-x64-msvc": "1.11.24" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.11.24", + "cpu": [ + "x64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 6" + "node": ">=10" } }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.11.24", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" + "node": ">=10" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@swc/counter": { + "version": "0.1.3", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.21", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tanstack/react-table": { + "version": "8.15.3", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@tanstack/table-core": "8.15.3" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "node_modules/@tanstack/table-core": { + "version": "8.15.3", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "node_modules/@testing-library/dom": { + "version": "9.3.4", + "dev": true, "license": "MIT", "dependencies": { - "delayed-stream": "~1.0.0" + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.1.3", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">=14" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "license": "MIT" + "node_modules/@testing-library/dom/node_modules/aria-query": { + "version": "5.1.3", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "deep-equal": "^2.0.5" + } }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "node_modules/@testing-library/dom/node_modules/dom-accessibility-api": { + "version": "0.5.16", + "dev": true, "license": "MIT" }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "dev": true, "license": "MIT", "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" }, "engines": { - "node": ">=10" + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/@testing-library/react": { + "version": "14.3.1", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^9.0.0", + "@types/react-dom": "^18.0.0" }, "engines": { - "node": ">= 8" + "node": ">=14" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "license": "MIT" + "node_modules/@testing-library/user-event": { + "version": "14.6.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } }, - "node_modules/d3": { - "version": "5.16.0", - "resolved": "https://registry.npmmirror.com/d3/-/d3-5.16.0.tgz", - "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" } }, - "node_modules/d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", - "license": "BSD-3-Clause" + "node_modules/@types/aria-query": { + "version": "5.0.4", + "dev": true, + "license": "MIT" }, - "node_modules/d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==", - "license": "BSD-3-Clause" + "node_modules/@types/autosuggest-highlight": { + "version": "3.2.3", + "dev": true, + "license": "MIT" }, - "node_modules/d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "license": "BSD-3-Clause", + "node_modules/@types/babel__core": { + "version": "7.20.5", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" } }, - "node_modules/d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "license": "BSD-3-Clause", + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "1", - "d3-path": "1" - } - }, - "node_modules/d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-color": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz", - "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", - "license": "ISC", - "engines": { - "node": ">=12" + "@babel/types": "^7.0.0" } }, - "node_modules/d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "license": "BSD-3-Clause", + "node_modules/@types/babel__template": { + "version": "7.4.4", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "^1.1.1" + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "node_modules/d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "license": "BSD-3-Clause", + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1", - "d3-selection": "1" + "@babel/types": "^7.28.2" } }, - "node_modules/d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "license": "BSD-3-Clause", + "node_modules/@types/d3": { + "version": "5.16.5", + "dev": true, + "license": "MIT", "dependencies": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - }, - "bin": { - "csv2json": "bin/dsv2json", - "csv2tsv": "bin/dsv2dsv", - "dsv2dsv": "bin/dsv2dsv", - "dsv2json": "bin/dsv2json", - "json2csv": "bin/json2dsv", - "json2dsv": "bin/json2dsv", - "json2tsv": "bin/json2dsv", - "tsv2csv": "bin/dsv2dsv", - "tsv2json": "bin/dsv2json" + "@types/d3-array": "^1", + "@types/d3-axis": "^1", + "@types/d3-brush": "^1", + "@types/d3-chord": "^1", + "@types/d3-collection": "*", + "@types/d3-color": "^1", + "@types/d3-contour": "^1", + "@types/d3-dispatch": "^1", + "@types/d3-drag": "^1", + "@types/d3-dsv": "^1", + "@types/d3-ease": "^1", + "@types/d3-fetch": "^1", + "@types/d3-force": "^1", + "@types/d3-format": "^1", + "@types/d3-geo": "^1", + "@types/d3-hierarchy": "^1", + "@types/d3-interpolate": "^1", + "@types/d3-path": "^1", + "@types/d3-polygon": "^1", + "@types/d3-quadtree": "^1", + "@types/d3-random": "^1", + "@types/d3-scale": "^2", + "@types/d3-scale-chromatic": "^1", + "@types/d3-selection": "^1", + "@types/d3-shape": "^1", + "@types/d3-time": "^1", + "@types/d3-time-format": "^2", + "@types/d3-timer": "^1", + "@types/d3-transition": "^1", + "@types/d3-voronoi": "*", + "@types/d3-zoom": "^1" } }, - "node_modules/d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==", - "license": "BSD-3-Clause" + "node_modules/@types/d3-array": { + "version": "3.2.1", + "dev": true, + "license": "MIT" }, - "node_modules/d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "license": "BSD-3-Clause", + "node_modules/@types/d3-axis": { + "version": "1.0.19", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dsv": "1" + "@types/d3-selection": "^1" } }, - "node_modules/d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "license": "BSD-3-Clause", + "node_modules/@types/d3-brush": { + "version": "1.1.8", + "dev": true, + "license": "MIT", "dependencies": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" + "@types/d3-selection": "^1" } }, - "node_modules/d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==", - "license": "BSD-3-Clause" + "node_modules/@types/d3-chord": { + "version": "1.0.14", + "dev": true, + "license": "MIT" }, - "node_modules/d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "1" - } + "node_modules/@types/d3-collection": { + "version": "1.0.13", + "dev": true, + "license": "MIT" }, - "node_modules/d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==", - "license": "BSD-3-Clause" + "node_modules/@types/d3-color": { + "version": "3.1.3", + "dev": true, + "license": "MIT" }, - "node_modules/d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", - "license": "BSD-3-Clause", + "node_modules/@types/d3-contour": { + "version": "1.3.6", + "dev": true, + "license": "MIT", "dependencies": { - "d3-color": "1" + "@types/d3-array": "^1", + "@types/geojson": "*" } }, - "node_modules/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", - "license": "BSD-3-Clause" + "node_modules/@types/d3-contour/node_modules/@types/d3-array": { + "version": "1.2.12", + "dev": true, + "license": "MIT" }, - "node_modules/d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", - "license": "BSD-3-Clause" + "node_modules/@types/d3-dispatch": { + "version": "1.0.12", + "dev": true, + "license": "MIT" }, - "node_modules/d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==", - "license": "BSD-3-Clause" + "node_modules/@types/d3-drag": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "^1" + } + }, + "node_modules/@types/d3-dsv": { + "version": "1.2.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-fetch": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-dsv": "^1" + } + }, + "node_modules/@types/d3-force": { + "version": "1.2.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-format": { + "version": "1.4.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-geo": { + "version": "1.12.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "1.1.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-polygon": { + "version": "1.0.10", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-quadtree": { + "version": "1.0.13", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-random": { + "version": "1.1.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "1.5.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-selection": { + "version": "1.4.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-shape": { + "version": "3.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-time-format": { + "version": "2.3.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-transition": { + "version": "1.3.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-selection": "^1" + } + }, + "node_modules/@types/d3-voronoi": { + "version": "1.1.12", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-zoom": { + "version": "1.8.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-interpolate": "^1", + "@types/d3-selection": "^1" + } + }, + "node_modules/@types/d3-zoom/node_modules/@types/d3-color": { + "version": "1.4.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3-zoom/node_modules/@types/d3-interpolate": { + "version": "1.4.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-color": "^1" + } + }, + "node_modules/@types/d3/node_modules/@types/d3-array": { + "version": "1.2.12", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3/node_modules/@types/d3-color": { + "version": "1.4.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3/node_modules/@types/d3-ease": { + "version": "1.0.13", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3/node_modules/@types/d3-interpolate": { + "version": "1.4.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-color": "^1" + } + }, + "node_modules/@types/d3/node_modules/@types/d3-path": { + "version": "1.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3/node_modules/@types/d3-scale": { + "version": "2.2.10", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-time": "^1" + } + }, + "node_modules/@types/d3/node_modules/@types/d3-shape": { + "version": "1.3.12", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/d3-path": "^1" + } + }, + "node_modules/@types/d3/node_modules/@types/d3-time": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/d3/node_modules/@types/d3-timer": { + "version": "1.0.12", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/geojson": { + "version": "7946.0.16", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hoist-non-react-statics": { + "version": "3.3.6", + "license": "MIT", + "dependencies": { + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/jest/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@types/jest/node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@types/jest/node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/jsdom": { + "version": "20.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.11.25", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.2.56", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.2.19", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-redux": { + "version": "7.1.33", + "license": "MIT", + "dependencies": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, + "node_modules/@types/react-redux/node_modules/redux": { + "version": "4.2.1", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/sanitize-html": { + "version": "2.13.0", + "license": "MIT", + "dependencies": { + "htmlparser2": "^8.0.0" + } + }, + "node_modules/@types/scheduler": { + "version": "0.26.0", + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.3", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/type-utils": "7.0.2", + "@typescript-eslint/utils": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.0.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/utils": "7.0.2", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.0.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "7.0.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-react-swc": { + "version": "3.9.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@swc/core": "^1.11.21" + }, + "peerDependencies": { + "vite": "^4 || ^5 || ^6" + } + }, + "node_modules/abab": { + "version": "2.0.6", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/acorn": { + "version": "8.14.1", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.1.0", + "acorn-walk": "^8.0.2" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/attr-accept": { + "version": "2.2.5", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/autosuggest-highlight": { + "version": "3.3.4", + "license": "MIT", + "dependencies": { + "remove-accents": "^0.4.2" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.15.2", + "resolved": "https://registry.npmmirror.com/axios/-/axios-1.15.2.tgz", + "integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.11", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.11", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001762", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "dev": true, + "license": "MIT" + }, + "node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.47.0", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css.escape": { + "version": "1.5.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cssom": { + "version": "0.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.1.3", + "license": "MIT" + }, + "node_modules/d3": { + "version": "5.16.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "node_modules/d3-array": { + "version": "1.2.4", + "license": "BSD-3-Clause" + }, + "node_modules/d3-axis": { + "version": "1.0.12", + "license": "BSD-3-Clause" + }, + "node_modules/d3-brush": { + "version": "1.1.6", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/d3-chord": { + "version": "1.0.6", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1", + "d3-path": "1" + } + }, + "node_modules/d3-collection": { + "version": "1.0.7", + "license": "BSD-3-Clause" + }, + "node_modules/d3-color": { + "version": "3.1.0", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "1.3.2", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "^1.1.1" + } + }, + "node_modules/d3-dispatch": { + "version": "1.0.6", + "license": "BSD-3-Clause" + }, + "node_modules/d3-drag": { + "version": "1.2.5", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "node_modules/d3-dsv": { + "version": "1.2.0", + "license": "BSD-3-Clause", + "dependencies": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json", + "csv2tsv": "bin/dsv2dsv", + "dsv2dsv": "bin/dsv2dsv", + "dsv2json": "bin/dsv2json", + "json2csv": "bin/json2dsv", + "json2dsv": "bin/json2dsv", + "json2tsv": "bin/json2dsv", + "tsv2csv": "bin/dsv2dsv", + "tsv2json": "bin/dsv2json" + } + }, + "node_modules/d3-ease": { + "version": "1.0.7", + "license": "BSD-3-Clause" + }, + "node_modules/d3-fetch": { + "version": "1.2.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dsv": "1" + } + }, + "node_modules/d3-force": { + "version": "1.2.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "node_modules/d3-format": { + "version": "1.4.5", + "license": "BSD-3-Clause" + }, + "node_modules/d3-geo": { + "version": "1.12.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/d3-hierarchy": { + "version": "1.1.9", + "license": "BSD-3-Clause" + }, + "node_modules/d3-interpolate": { + "version": "1.4.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/d3-path": { + "version": "1.0.9", + "license": "BSD-3-Clause" + }, + "node_modules/d3-polygon": { + "version": "1.0.6", + "license": "BSD-3-Clause" + }, + "node_modules/d3-quadtree": { + "version": "1.0.7", + "license": "BSD-3-Clause" }, "node_modules/d3-queue": { "version": "3.0.7", - "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", - "integrity": "sha512-2rs+6pNFKkrJhqe1rg5znw7dKJ7KZr62j9aLZfhondkrnz6U7VRmJj1UGcbD8MRc46c7H8m4SWhab8EalBQrkw==", - "license": "BSD-3-Clause" + "license": "BSD-3-Clause" + }, + "node_modules/d3-random": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/d3-request": { + "version": "1.0.6", + "license": "BSD-3-Clause", + "dependencies": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-dsv": "1", + "xmlhttprequest": "1" + } + }, + "node_modules/d3-scale": { + "version": "2.2.2", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "1.5.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "node_modules/d3-selection": { + "version": "1.4.2", + "license": "BSD-3-Clause" + }, + "node_modules/d3-shape": { + "version": "1.3.7", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-time": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/d3-time-format": { + "version": "2.3.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-time": "1" + } + }, + "node_modules/d3-timer": { + "version": "1.0.10", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip": { + "version": "0.7.1", + "license": "MIT", + "dependencies": { + "d3": "^4.2" + } + }, + "node_modules/d3-tip/node_modules/d3": { + "version": "4.13.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1.2.1", + "d3-axis": "1.0.8", + "d3-brush": "1.0.4", + "d3-chord": "1.0.4", + "d3-collection": "1.0.4", + "d3-color": "1.0.3", + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-dsv": "1.0.8", + "d3-ease": "1.0.3", + "d3-force": "1.1.0", + "d3-format": "1.2.2", + "d3-geo": "1.9.1", + "d3-hierarchy": "1.1.5", + "d3-interpolate": "1.1.6", + "d3-path": "1.0.5", + "d3-polygon": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-queue": "3.0.7", + "d3-random": "1.1.0", + "d3-request": "1.0.6", + "d3-scale": "1.0.7", + "d3-selection": "1.3.0", + "d3-shape": "1.2.0", + "d3-time": "1.0.8", + "d3-time-format": "2.1.1", + "d3-timer": "1.0.7", + "d3-transition": "1.1.1", + "d3-voronoi": "1.1.2", + "d3-zoom": "1.7.1" + } + }, + "node_modules/d3-tip/node_modules/d3-array": { + "version": "1.2.1", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-axis": { + "version": "1.0.8", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-brush": { + "version": "1.0.4", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-chord": { + "version": "1.0.4", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1", + "d3-path": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-collection": { + "version": "1.0.4", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-dispatch": { + "version": "1.0.3", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-drag": { + "version": "1.2.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-dsv": { + "version": "1.0.8", + "license": "BSD-3-Clause", + "dependencies": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json", + "csv2tsv": "bin/dsv2dsv", + "dsv2dsv": "bin/dsv2dsv", + "dsv2json": "bin/dsv2json", + "json2csv": "bin/json2dsv", + "json2dsv": "bin/json2dsv", + "json2tsv": "bin/json2dsv", + "tsv2csv": "bin/dsv2dsv", + "tsv2json": "bin/dsv2json" + } + }, + "node_modules/d3-tip/node_modules/d3-ease": { + "version": "1.0.3", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-force": { + "version": "1.1.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-format": { + "version": "1.2.2", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-geo": { + "version": "1.9.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-hierarchy": { + "version": "1.1.5", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-interpolate": { + "version": "1.1.6", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-path": { + "version": "1.0.5", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-polygon": { + "version": "1.0.3", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-quadtree": { + "version": "1.0.3", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-random": { + "version": "1.1.0", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-scale": { + "version": "1.0.7", + "license": "BSD-3-Clause", + "dependencies": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-color": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "node_modules/d3-tip/node_modules/d3-selection": { + "version": "1.3.0", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-shape": { + "version": "1.2.0", + "license": "BSD-3-Clause", + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-time": { + "version": "1.0.8", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-time-format": { + "version": "2.1.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-time": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-timer": { + "version": "1.0.7", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-transition": { + "version": "1.1.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "node_modules/d3-tip/node_modules/d3-voronoi": { + "version": "1.1.2", + "license": "BSD-3-Clause" + }, + "node_modules/d3-tip/node_modules/d3-zoom": { + "version": "1.7.1", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/d3-transition": { + "version": "1.3.2", + "license": "BSD-3-Clause", + "dependencies": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "node_modules/d3-voronoi": { + "version": "1.1.4", + "license": "BSD-3-Clause" + }, + "node_modules/d3-zoom": { + "version": "1.8.3", + "license": "BSD-3-Clause", + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/dagre": { + "version": "0.8.5", + "license": "MIT", + "dependencies": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/dagre-d3": { + "version": "0.6.4", + "license": "MIT", + "dependencies": { + "d3": "^5.14", + "dagre": "^0.8.5", + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/date-fns": { + "version": "4.1.0", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "dev": true, + "license": "MIT" + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "dev": true, + "license": "MIT" + }, + "node_modules/dedent": { + "version": "1.7.1", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.6.3", + "dev": true, + "license": "MIT" + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domexception": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "4.5.0", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.4", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.4", + "@esbuild/android-arm": "0.25.4", + "@esbuild/android-arm64": "0.25.4", + "@esbuild/android-x64": "0.25.4", + "@esbuild/darwin-arm64": "0.25.4", + "@esbuild/darwin-x64": "0.25.4", + "@esbuild/freebsd-arm64": "0.25.4", + "@esbuild/freebsd-x64": "0.25.4", + "@esbuild/linux-arm": "0.25.4", + "@esbuild/linux-arm64": "0.25.4", + "@esbuild/linux-ia32": "0.25.4", + "@esbuild/linux-loong64": "0.25.4", + "@esbuild/linux-mips64el": "0.25.4", + "@esbuild/linux-ppc64": "0.25.4", + "@esbuild/linux-riscv64": "0.25.4", + "@esbuild/linux-s390x": "0.25.4", + "@esbuild/linux-x64": "0.25.4", + "@esbuild/netbsd-arm64": "0.25.4", + "@esbuild/netbsd-x64": "0.25.4", + "@esbuild/openbsd-arm64": "0.25.4", + "@esbuild/openbsd-x64": "0.25.4", + "@esbuild/sunos-x64": "0.25.4", + "@esbuild/win32-arm64": "0.25.4", + "@esbuild/win32-ia32": "0.25.4", + "@esbuild/win32-x64": "0.25.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.56.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.56.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.5", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "license": "MIT" + }, + "node_modules/execa": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "dev": true, + "license": "ISC" + }, + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "license": "Apache-2.0" + }, + "node_modules/fast-equals": { + "version": "5.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-selector": { + "version": "0.6.0", + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/graphlib": { + "version": "2.1.8", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/handlebars": { + "version": "4.7.8", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "10.1.3", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } }, - "node_modules/d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==", - "license": "BSD-3-Clause" + "node_modules/immutable": { + "version": "4.3.8", + "dev": true, + "license": "MIT" }, - "node_modules/d3-request": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", - "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", - "license": "BSD-3-Clause", + "node_modules/import-fresh": { + "version": "3.3.1", + "license": "MIT", "dependencies": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-dsv": "1", - "xmlhttprequest": "1" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "license": "BSD-3-Clause", + "node_modules/import-local": { + "version": "3.2.0", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-color": "1", - "d3-interpolate": "1" + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" } }, - "node_modules/d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==", - "license": "BSD-3-Clause" + "node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "license": "BSD-3-Clause", + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", "dependencies": { - "d3-path": "1" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==", - "license": "BSD-3-Clause" + "node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "license": "ISC" }, - "node_modules/d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "license": "BSD-3-Clause", + "node_modules/internal-slot": { + "version": "1.1.0", + "dev": true, + "license": "MIT", "dependencies": { - "d3-time": "1" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" } }, - "node_modules/d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", - "license": "BSD-3-Clause" + "node_modules/internmap": { + "version": "2.0.3", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } }, - "node_modules/d3-tip": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.7.1.tgz", - "integrity": "sha512-jtVR86jEfpVhfMtJaJBzT3GYYfulID106s9gqiX8o8es2tRcsCeJhoWWZG3sfepP97j1CTxfxPoky014nfJ9Zg==", + "node_modules/is-arguments": { + "version": "1.2.0", + "dev": true, "license": "MIT", "dependencies": { - "d3": "^4.2" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz", - "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==", - "license": "BSD-3-Clause", + "node_modules/is-array-buffer": { + "version": "3.0.5", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "1.2.1", - "d3-axis": "1.0.8", - "d3-brush": "1.0.4", - "d3-chord": "1.0.4", - "d3-collection": "1.0.4", - "d3-color": "1.0.3", - "d3-dispatch": "1.0.3", - "d3-drag": "1.2.1", - "d3-dsv": "1.0.8", - "d3-ease": "1.0.3", - "d3-force": "1.1.0", - "d3-format": "1.2.2", - "d3-geo": "1.9.1", - "d3-hierarchy": "1.1.5", - "d3-interpolate": "1.1.6", - "d3-path": "1.0.5", - "d3-polygon": "1.0.3", - "d3-quadtree": "1.0.3", - "d3-queue": "3.0.7", - "d3-random": "1.1.0", - "d3-request": "1.0.6", - "d3-scale": "1.0.7", - "d3-selection": "1.3.0", - "d3-shape": "1.2.0", - "d3-time": "1.0.8", - "d3-time-format": "2.1.1", - "d3-timer": "1.0.7", - "d3-transition": "1.1.1", - "d3-voronoi": "1.1.2", - "d3-zoom": "1.7.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", - "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-axis": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz", - "integrity": "sha512-K0djTb26iQ6AsuD2d6Ka08wBHf4V30awIxV4XFuB/iLzYtTqqJlE/nIN0DBJJCX7lbOqbt2/oeX3r+sU5k2veg==", - "license": "BSD-3-Clause" + "node_modules/is-arrayish": { + "version": "0.2.1", + "license": "MIT" }, - "node_modules/d3-tip/node_modules/d3-brush": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz", - "integrity": "sha512-nUFueDzOlvwFvuOBynGSyJM7Wt1H9fKgJeoWFSg3ScS4c7FJBch92FKUJKum4xtgPYHdgH2C3bRg3GzSVltCJQ==", - "license": "BSD-3-Clause", + "node_modules/is-bigint": { + "version": "1.1.0", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-chord": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz", - "integrity": "sha512-o0ExexkK1N0KikUakKrQwttP5Flu8AYD6iBUh3AdPJqnTh6xlvcX5wFRuuo29sLOAr9+T4yZPUH1S3CCQJ1SlQ==", - "license": "BSD-3-Clause", + "node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", "dependencies": { - "d3-array": "1", - "d3-path": "1" + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/d3-tip/node_modules/d3-collection": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", - "integrity": "sha512-+TPxaBFzbzfpLF3Hjz8JPeuStNmJnyWAufu8VUfpDCDn5RieIgY+OQDjhKMDorf2naLgAjjZXLUQN7XFp/kgog==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-dispatch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", - "integrity": "sha512-Qh2DR3neW3lq/ug4oymXHYoIsA91nYt47ERb+fPKjRg6zLij06aP7KqHHl2NyziK9ASxrR3GLkHCtZvXe/jMVg==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-drag": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz", - "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==", - "license": "BSD-3-Clause", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "dev": true, + "license": "MIT", "dependencies": { - "d3-dispatch": "1", - "d3-selection": "1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-dsv": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz", - "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==", - "license": "BSD-3-Clause", + "node_modules/is-callable": { + "version": "1.2.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "license": "MIT", "dependencies": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" + "hasown": "^2.0.2" }, - "bin": { - "csv2json": "bin/dsv2json", - "csv2tsv": "bin/dsv2dsv", - "dsv2dsv": "bin/dsv2dsv", - "dsv2json": "bin/dsv2json", - "json2csv": "bin/json2dsv", - "json2dsv": "bin/json2dsv", - "json2tsv": "bin/json2dsv", - "tsv2csv": "bin/dsv2dsv", - "tsv2json": "bin/dsv2json" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-ease": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", - "integrity": "sha512-io3QwOJwVPAxRF2UXpKpCdz2wm/7VLFCQQ1yy+GzX6YCtt3vi2BGnimI8agSF5jyUrHsADyF303d2S+ps7zU8w==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-force": { + "node_modules/is-date-object": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", - "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", - "license": "BSD-3-Clause", + "dev": true, + "license": "MIT", "dependencies": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-format": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz", - "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==", - "license": "BSD-3-Clause" + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/d3-tip/node_modules/d3-geo": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz", - "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "1" + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/d3-tip/node_modules/d3-hierarchy": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz", - "integrity": "sha512-PcsLIhThc60mWnxlojIOH7Sc0tQ2DgLWfEwEAyzCtej5f3H9wSsRmrg5pEhKZLrwiJnI2zyw/pznJxL9a/Eugw==", - "license": "BSD-3-Clause" + "node_modules/is-generator-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/d3-tip/node_modules/d3-interpolate": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", - "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", - "license": "BSD-3-Clause", + "node_modules/is-glob": { + "version": "4.0.3", + "dev": true, + "license": "MIT", "dependencies": { - "d3-color": "1" + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/d3-tip/node_modules/d3-path": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", - "integrity": "sha512-eD76prgnTKYkLzHlY2UMyOEZXTpC+WOanCr1BLxo38w4fPPPq/LgCFqRQvqFU3AJngfZmmKR7rgKPZ4EGJ9Atw==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-polygon": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz", - "integrity": "sha512-2zP7GOvf4XOWTeQouK7fCO534yQxyhYYTw6GTqcXifIalHgA6qV/es+4GRQii9m6XxEPFcht4loobD/o2iEo1A==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-quadtree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", - "integrity": "sha512-U2Jc3jF3JOBGXIOnvWY9C4ekRwRX9hEVpMMmeduJyaxAwPmoe7t84iZFTLn1RwYOyrXxJF55H/Hrg186TFQQdw==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-random": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", - "integrity": "sha512-XuMbjx3Jq4EWfJP4g6nR7zns/bZfaVbWHWfR8auDkEiWCzVbWifmasfszV1ZRN3xXK3nY4RUFL2nTIhceGZSFQ==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-scale": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", - "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-color": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" + "node_modules/is-map": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-selection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz", - "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==", - "license": "BSD-3-Clause" + "node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } }, - "node_modules/d3-tip/node_modules/d3-shape": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz", - "integrity": "sha512-LP48zJ9ykPKjCdd0vSu5k2l4s8v1vI6vvdDeJtmgtTa+L6Ery0lzvOaV7pMunFuLv11hwSRZQnSnlhFl801aiw==", - "license": "BSD-3-Clause", + "node_modules/is-number-object": { + "version": "1.1.1", + "dev": true, + "license": "MIT", "dependencies": { - "d3-path": "1" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-time": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz", - "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==", - "license": "BSD-3-Clause" + "node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/d3-tip/node_modules/d3-time-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz", - "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-time": "1" + "node_modules/is-plain-object": { + "version": "5.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/d3-tip/node_modules/d3-timer": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", - "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==", - "license": "BSD-3-Clause" + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "dev": true, + "license": "MIT" }, - "node_modules/d3-tip/node_modules/d3-transition": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz", - "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==", - "license": "BSD-3-Clause", + "node_modules/is-regex": { + "version": "1.2.1", + "dev": true, + "license": "MIT", "dependencies": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-tip/node_modules/d3-voronoi": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", - "integrity": "sha512-RhGS1u2vavcO7ay7ZNAPo4xeDh/VYeGof3x5ZLJBQgYhLegxr3s5IykvWmJ94FTU6mcbtp4sloqZ54mP6R4Utw==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-tip/node_modules/d3-zoom": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz", - "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" + "node_modules/is-set": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "license": "BSD-3-Clause", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "dev": true, + "license": "MIT", "dependencies": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", - "license": "BSD-3-Clause" - }, - "node_modules/d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "license": "BSD-3-Clause", - "dependencies": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" + "node_modules/is-stream": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "node_modules/is-string": { + "version": "1.1.1", + "dev": true, "license": "MIT", "dependencies": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", + "node_modules/is-symbol": { + "version": "1.1.1", + "dev": true, "license": "MIT", "dependencies": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/date-fns": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", - "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "dev": true, "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/kossnocorp" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/dayjs": { - "version": "1.11.20", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", - "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/is-weakset": { + "version": "2.0.4", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/decimal.js-light": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", - "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "node_modules/isarray": { + "version": "2.0.5", "dev": true, "license": "MIT" }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "node_modules/isexe": { + "version": "2.0.0", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "license": "MIT", + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=8" } }, - "node_modules/dir-glob": { + "node_modules/istanbul-lib-report": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "path-type": "^4.0.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", "dev": true, - "license": "Apache-2.0", + "license": "BSD-3-Clause", "dependencies": { - "esutils": "^2.0.2" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=10" } }, - "node_modules/dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "license": "MIT", + "node_modules/istanbul-reports": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">=8" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "license": "BSD-2-Clause", + "node_modules/jest": { + "version": "29.7.0", + "dev": true, + "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0" + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/jest-changed-files": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", + "node_modules/jest-circus": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.12" + "node": ">=10" }, "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/jest-circus/node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } + "node_modules/jest-circus/node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "node_modules/jest-cli": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0" + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } } }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/jest-config": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } } }, - "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, - "hasInstallScript": true, "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, "engines": { - "node": ">=18" + "node": ">=10" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/jest-config/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "node_modules/jest-config/node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-diff": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", - "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.5.tgz", - "integrity": "sha512-D53FYKJa+fDmZMtriODxvhwrO+IOqrxoEo21gMA0sjHdU6dPVH4OhyFip9ypl8HOF5RV5KdTo+rBQLvnY2cO8w==", + "node_modules/jest-diff/node_modules/pretty-format": { + "version": "29.7.0", "dev": true, "license": "MIT", - "peerDependencies": { - "eslint": ">=7" + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/jest-diff/node_modules/react-is": { + "version": "18.3.1", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "detect-newline": "^3.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/jest-each/node_modules/pretty-format": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/jest-each/node_modules/react-is": { + "version": "18.3.1", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "MIT" + }, + "node_modules/jest-environment-jsdom": { + "version": "29.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/jsdom": "^20.0.0", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0", + "jsdom": "^20.0.0" + }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } } }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/jest-environment-jsdom/node_modules/agent-base": { + "version": "6.0.2", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "debug": "4" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">= 6.0.0" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/jest-environment-jsdom/node_modules/cssstyle": { + "version": "2.3.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "cssom": "~0.3.6" }, "engines": { - "node": ">=0.10" + "node": ">=8" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "node_modules/jest-environment-jsdom/node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/jest-environment-jsdom/node_modules/data-urls": { + "version": "3.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "estraverse": "^5.2.0" + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" }, "engines": { - "node": ">=4.0" + "node": ">=12" } }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": { + "version": "3.0.0", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, "engines": { - "node": ">=4.0" + "node": ">=12" } }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "node_modules/jest-environment-jsdom/node_modules/http-proxy-agent": { + "version": "5.0.0", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/eventemitter3": { + "node_modules/jest-environment-jsdom/node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, - "license": "MIT" - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "license": "Apache-2.0" + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } }, - "node_modules/fast-equals": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", - "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", + "node_modules/jest-environment-jsdom/node_modules/iconv-lite": { + "version": "0.6.3", "dev": true, "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, "engines": { - "node": ">=6.0.0" + "node": ">=0.10.0" } }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "node_modules/jest-environment-jsdom/node_modules/jsdom": { + "version": "20.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.8.1", + "acorn-globals": "^7.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.4.2", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.2", + "parse5": "^7.1.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.2", + "w3c-xmlserializer": "^4.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.11.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jest-environment-jsdom/node_modules/tr46": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" + "punycode": "^2.1.1" }, "engines": { - "node": ">=8.6.0" + "node": ">=12" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/jest-environment-jsdom/node_modules/w3c-xmlserializer": { + "version": "4.0.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "xml-name-validator": "^4.0.0" }, "engines": { - "node": ">= 6" + "node": ">=14" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "node_modules/jest-environment-jsdom/node_modules/whatwg-encoding": { + "version": "2.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "node_modules/jest-environment-jsdom/node_modules/whatwg-mimetype": { + "version": "3.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12" + } }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "node_modules/jest-environment-jsdom/node_modules/whatwg-url": { + "version": "11.0.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "reusify": "^1.0.4" + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/jest-environment-jsdom/node_modules/xml-name-validator": { + "version": "4.0.0", "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, + "license": "Apache-2.0", "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12" } }, - "node_modules/file-selector": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.6.0.tgz", - "integrity": "sha512-QlZ5yJC0VxHxQQsQhXvBaC7VRJ2uaxTf+Tfpu4Z/OcVQJVpZO+DGU0rkoVW5ce2SccxugvpBJoMvUs59iILYdw==", + "node_modules/jest-environment-node": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "tslib": "^2.4.0" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" }, "engines": { - "node": ">= 12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/jest-get-type": { + "version": "29.6.3", "dev": true, "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "license": "MIT" - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "node_modules/jest-haste-map": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" }, "engines": { - "node": ">=10" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "^2.3.2" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/jest-leak-detector": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmmirror.com/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "node_modules/jest-leak-detector/node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.11", - "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", - "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=10" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "node_modules/jest-leak-detector/node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/jest-leak-detector/node_modules/react-is": { + "version": "18.3.1", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/jest-matcher-utils": { + "version": "29.7.0", "dev": true, - "hasInstallScript": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "node_modules/jest-matcher-utils/node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/jest-matcher-utils/node_modules/react-is": { + "version": "18.3.1", "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } + "license": "MIT" }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/jest-message-util": { + "version": "29.7.0", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, "engines": { "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/jest-message-util/node_modules/pretty-format": { + "version": "29.7.0", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "node_modules/jest-message-util/node_modules/react-is": { + "version": "18.3.1", "dev": true, "license": "MIT" }, - "node_modules/graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "node_modules/jest-mock": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "lodash": "^4.17.15" + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/jest-regex-util": { + "version": "29.6.3", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/jest-resolve": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">= 0.4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "license": "BSD-3-Clause", + "node_modules/jest-runner": { + "version": "29.7.0", + "dev": true, + "license": "MIT", "dependencies": { - "react-is": "^16.7.0" + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "license": "MIT" + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "dev": true, "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "node_modules/jest-runtime": { + "version": "29.7.0", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "node_modules/jest-runtime/node_modules/glob": { + "version": "7.2.3", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">= 4" - } - }, - "node_modules/immer": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.3.tgz", - "integrity": "sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==", - "license": "MIT", + "node": "*" + }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/immer" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/immutable": { - "version": "4.3.8", - "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.8.tgz", - "integrity": "sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw==", + "node_modules/jest-snapshot": { + "version": "29.7.0", "dev": true, - "license": "MIT" - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "5.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.8.19" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/jest-snapshot/node_modules/pretty-format": { + "version": "29.7.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/jest-snapshot/node_modules/react-is": { + "version": "18.3.1", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/internmap": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", - "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "node_modules/jest-util": { + "version": "29.7.0", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, "engines": { - "node": ">=12" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/jest-validate": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "node_modules/jest-validate/node_modules/pretty-format": { + "version": "29.7.0", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "node_modules/jest-validate/node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/jest-watcher": { + "version": "29.7.0", "dev": true, "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, "engines": { - "node": ">=0.12.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/jest-worker": { + "version": "29.7.0", "dev": true, "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, "node_modules/js-tokens": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "license": "MIT", "dependencies": { @@ -5067,8 +7904,6 @@ }, "node_modules/jsesc": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "license": "MIT", "bin": { "jsesc": "bin/jsesc" @@ -5079,35 +7914,36 @@ }, "node_modules/json-buffer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/keyv": { "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { @@ -5116,17 +7952,23 @@ }, "node_modules/launder": { "version": "1.7.1", - "resolved": "https://registry.npmjs.org/launder/-/launder-1.7.1.tgz", + "resolved": "https://registry.npmmirror.com/launder/-/launder-1.7.1.tgz", "integrity": "sha512-mU6WRz5EusL9ZZuiZ5SO4Y6C0P9PAUR9iwdb6bzj4KDihm28DiHFw+/yk9DBH4f+Pv1wuzQ4e2jV3oQ7mkIqvw==", "license": "MIT", "dependencies": { "dayjs": "^1.11.7" } }, + "node_modules/leven": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5139,14 +7981,10 @@ }, "node_modules/lines-and-columns": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, "node_modules/locate-path": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { @@ -5173,28 +8011,29 @@ }, "node_modules/lodash.clonedeep": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "dev": true, "license": "MIT" }, "node_modules/lodash.isequal": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "dev": true, "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true, "license": "MIT" }, "node_modules/loose-envify": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -5203,19 +8042,66 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "dev": true, + "license": "ISC" + }, + "node_modules/makeerror": { + "version": "1.0.12", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/merge2": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", "engines": { @@ -5224,8 +8110,6 @@ }, "node_modules/micromatch": { "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -5238,8 +8122,6 @@ }, "node_modules/mime-db": { "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" @@ -5247,8 +8129,6 @@ }, "node_modules/mime-types": { "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -5257,10 +8137,24 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/minimatch": { "version": "9.0.7", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.7.tgz", - "integrity": "sha512-MOwgjc8tfrpn5QQEvjijjmDVtMw2oL88ugTevzxQnzRLm6l3fVEF2gzU0kYeYYKD8C66+IdGX6peJ4MyUlUnPg==", "dev": true, "license": "ISC", "dependencies": { @@ -5273,10 +8167,35 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimatch/node_modules/balanced-match": { + "version": "4.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "5.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/moment": { "version": "2.30.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", - "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "license": "MIT", "engines": { "node": "*" @@ -5284,8 +8203,6 @@ }, "node_modules/moment-timezone": { "version": "0.5.45", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", - "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", "license": "MIT", "dependencies": { "moment": "^2.29.4" @@ -5296,14 +8213,10 @@ }, "node_modules/ms": { "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", @@ -5318,55 +8231,141 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/neo-async": { + "version": "2.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/numeric-quantity": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/nwsapi": { + "version": "2.2.22", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/object-is": { + "version": "1.1.6", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/numeric-quantity": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/numeric-quantity/-/numeric-quantity-2.1.0.tgz", - "integrity": "sha512-oDkQ8nFuNVA+unEg1jd6dAS+O7eLXWWzsa4ViI0S0yFi6654GK0s74o8bF8uLRQdWIz/qFF1GABNFPfwAGQUsg==", + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">= 0.4" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/object.assign": { + "version": "4.1.7", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { @@ -5383,8 +8382,6 @@ }, "node_modules/p-limit": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5399,8 +8396,6 @@ }, "node_modules/p-locate": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { @@ -5413,16 +8408,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/parchment": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", - "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", "license": "BSD-3-Clause" }, "node_modules/parent-module": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "license": "MIT", "dependencies": { "callsites": "^3.0.0" @@ -5433,8 +8432,6 @@ }, "node_modules/parse-json": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", @@ -5451,14 +8448,32 @@ }, "node_modules/parse-srcset": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", - "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", "license": "MIT" }, + "node_modules/parse5": { + "version": "7.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { @@ -5467,8 +8482,6 @@ }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", "engines": { @@ -5477,8 +8490,6 @@ }, "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { @@ -5487,14 +8498,10 @@ }, "node_modules/path-parse": { "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "license": "MIT", "engines": { "node": ">=8" @@ -5502,14 +8509,10 @@ }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { @@ -5519,16 +8522,87 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/platform": { "version": "1.3.4", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz", - "integrity": "sha512-iPnLzoBruVgswLtQ06HuYW4JUYW+SupPyrzZnhVRPZuh9NDWojJYpQqR2Ro43XpUlh46l8ygbnWKVHO270XATg==", "license": "MIT" }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", "funding": [ { "type": "opencollective", @@ -5555,18 +8629,63 @@ }, "node_modules/prelude-ls": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-format/node_modules/react-is": { + "version": "17.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/prop-types": { "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -5576,8 +8695,6 @@ }, "node_modules/prop-types/node_modules/react-is": { "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, "node_modules/proxy-from-env": { @@ -5589,20 +8706,47 @@ "node": ">=10" } }, + "node_modules/psl": { + "version": "1.15.0", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, "node_modules/punycode": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.1.0", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/querystringify": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { @@ -5622,8 +8766,6 @@ }, "node_modules/quill": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", - "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", "license": "BSD-3-Clause", "dependencies": { "eventemitter3": "^5.0.1", @@ -5637,8 +8779,6 @@ }, "node_modules/quill-delta": { "version": "5.1.0", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", - "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", "license": "MIT", "dependencies": { "fast-diff": "^1.3.0", @@ -5651,8 +8791,6 @@ }, "node_modules/react": { "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -5663,8 +8801,6 @@ }, "node_modules/react-datepicker": { "version": "8.4.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-8.4.0.tgz", - "integrity": "sha512-6nPDnj8vektWCIOy9ArS3avus9Ndsyz5XgFCJ7nBxXASSpBdSL6lG9jzNNmViPOAOPh6T5oJyGaXuMirBLECag==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.27.3", @@ -5678,8 +8814,6 @@ }, "node_modules/react-dom": { "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", - "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -5691,8 +8825,6 @@ }, "node_modules/react-dropzone": { "version": "14.2.3", - "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz", - "integrity": "sha512-O3om8I+PkFKbxCukfIR3QAGftYXDZfOE2N1mr/7qebQJHs7U+/RSL/9xomJNpRg9kM5h9soQSdf0Gc7OHF5Fug==", "license": "MIT", "dependencies": { "attr-accept": "^2.2.2", @@ -5708,8 +8840,6 @@ }, "node_modules/react-hook-form": { "version": "7.53.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.0.tgz", - "integrity": "sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==", "license": "MIT", "engines": { "node": ">=18.0.0" @@ -5724,8 +8854,6 @@ }, "node_modules/react-idle-timer": { "version": "5.7.2", - "resolved": "https://registry.npmjs.org/react-idle-timer/-/react-idle-timer-5.7.2.tgz", - "integrity": "sha512-+BaPfc7XEUU5JFkwZCx6fO1bLVK+RBlFH+iY4X34urvIzZiZINP6v2orePx3E6pAztJGE7t4DzvL7if2SL/0GQ==", "license": "MIT", "peerDependencies": { "react": ">=16", @@ -5734,14 +8862,10 @@ }, "node_modules/react-is": { "version": "19.1.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", - "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", "license": "MIT" }, "node_modules/react-querybuilder": { "version": "8.0.0", - "resolved": "https://registry.npmjs.org/react-querybuilder/-/react-querybuilder-8.0.0.tgz", - "integrity": "sha512-vy+xBVsCOPdSHiQP6qjDx7nmavIjP6m5nixqXHKX9l+I1edHGHPfE4riN0YQ1KRPsMFCHpuiTBV8fpOloPqf6Q==", "license": "MIT", "dependencies": { "@reduxjs/toolkit": "^2.3.0", @@ -5755,8 +8879,6 @@ }, "node_modules/react-querybuilder/node_modules/@reduxjs/toolkit": { "version": "2.9.0", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.9.0.tgz", - "integrity": "sha512-fSfQlSRu9Z5yBkvsNhYF2rPS8cGXn/TZVrlwN1948QyZ8xMZ0JvP50S2acZNaf+o63u6aEeMjipFyksjIcWrog==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -5781,14 +8903,10 @@ }, "node_modules/react-querybuilder/node_modules/@types/use-sync-external-store": { "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", "license": "MIT" }, "node_modules/react-querybuilder/node_modules/react-redux": { "version": "9.2.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", - "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "license": "MIT", "dependencies": { "@types/use-sync-external-store": "^0.0.6", @@ -5810,8 +8928,6 @@ }, "node_modules/react-quill-new": { "version": "3.4.1", - "resolved": "https://registry.npmjs.org/react-quill-new/-/react-quill-new-3.4.1.tgz", - "integrity": "sha512-EM4EXlX3imgYH5H1Ml8OM0dXvb/hGtKXtzosrhF7MRiKqw5rDJSIDkty0x/L6yBiJzBycpLT24rCMtPELSQW9Q==", "license": "MIT", "dependencies": { "lodash-es": "^4.17.21", @@ -5825,8 +8941,6 @@ }, "node_modules/react-redux": { "version": "9.1.0", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.1.0.tgz", - "integrity": "sha512-6qoDzIO+gbrza8h3hjMA9aq4nwVFCKFtY2iLxCtVT38Swyy2C/dJCGBXHeHLtx6qlg/8qzc2MrhOeduf5K32wQ==", "license": "MIT", "dependencies": { "@types/use-sync-external-store": "^0.0.3", @@ -5852,8 +8966,6 @@ }, "node_modules/react-router": { "version": "6.30.3", - "resolved": "https://registry.npmmirror.com/react-router/-/react-router-6.30.3.tgz", - "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==", "license": "MIT", "dependencies": { "@remix-run/router": "1.23.2" @@ -5867,8 +8979,6 @@ }, "node_modules/react-router-dom": { "version": "6.30.3", - "resolved": "https://registry.npmmirror.com/react-router-dom/-/react-router-dom-6.30.3.tgz", - "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==", "license": "MIT", "dependencies": { "@remix-run/router": "1.23.2", @@ -5884,8 +8994,6 @@ }, "node_modules/react-smooth": { "version": "4.0.4", - "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz", - "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5900,8 +9008,6 @@ }, "node_modules/react-toastify": { "version": "10.0.5", - "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.5.tgz", - "integrity": "sha512-mNKt2jBXJg4O7pSdbNUfDdTsK9FIdikfsIE/yUCxbAEXl4HMyJaivrVFcn3Elvt5xvCQYhUZm+hqTIu1UXM3Pw==", "license": "MIT", "dependencies": { "clsx": "^2.1.0" @@ -5913,8 +9019,6 @@ }, "node_modules/react-transition-group": { "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.5.5", @@ -5929,8 +9033,6 @@ }, "node_modules/readdirp": { "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", "dependencies": { @@ -5942,8 +9044,6 @@ }, "node_modules/recharts": { "version": "2.15.1", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.1.tgz", - "integrity": "sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q==", "dev": true, "license": "MIT", "dependencies": { @@ -5966,59 +9066,135 @@ }, "node_modules/recharts-scale": { "version": "0.4.5", - "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz", - "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==", "dev": true, "license": "MIT", "dependencies": { "decimal.js-light": "^2.4.1" } }, - "node_modules/recharts/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "node_modules/recharts/node_modules/eventemitter3": { + "version": "4.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/recharts/node_modules/react-is": { + "version": "18.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/redent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", "dev": true, "license": "MIT" }, - "node_modules/recharts/node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "node_modules/regjsparser": { + "version": "0.13.0", "dev": true, - "license": "MIT" + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } }, - "node_modules/redux": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "node_modules/remove-accents": { + "version": "0.4.4", "license": "MIT" }, - "node_modules/redux-thunk": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", - "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, "license": "MIT", - "peerDependencies": { - "redux": "^5.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/remove-accents": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.4.tgz", - "integrity": "sha512-EpFcOa/ISetVHEXqu+VwI96KZBmq+a8LJnGkaeFw45epGlxIZz5dhEEnNZMsQXgORu3qaMoLX4qJCzOik6ytAg==", + "node_modules/requires-port": { + "version": "1.0.0", + "dev": true, "license": "MIT" }, "node_modules/reselect": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", - "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", "license": "MIT" }, "node_modules/resolve": { "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -6035,19 +9211,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/resolve-from": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "license": "MIT", "engines": { "node": ">=4" } }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/reusify": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { @@ -6057,9 +9256,6 @@ }, "node_modules/rimraf": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -6074,9 +9270,6 @@ }, "node_modules/rimraf/node_modules/glob": { "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { @@ -6096,8 +9289,6 @@ }, "node_modules/rollup": { "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", "dependencies": { @@ -6141,8 +9332,6 @@ }, "node_modules/run-parallel": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { @@ -6165,19 +9354,31 @@ }, "node_modules/rw": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", "license": "BSD-3-Clause" }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, "node_modules/sanitize-html": { "version": "2.17.4", - "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.4.tgz", + "resolved": "https://registry.npmmirror.com/sanitize-html/-/sanitize-html-2.17.4.tgz", "integrity": "sha512-2HW7v2ol/uAM7sX4hbD8Z59OGWmAPrvjL8E71UWlBcj6m+kcF6ilQBLny+cIgY214QJeJT5tQuxKKqX0SQqjGQ==", "license": "MIT", "dependencies": { @@ -6192,7 +9393,7 @@ }, "node_modules/sanitize-html/node_modules/entities": { "version": "7.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "engines": { @@ -6204,7 +9405,7 @@ }, "node_modules/sanitize-html/node_modules/htmlparser2": { "version": "10.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "resolved": "https://registry.npmmirror.com/htmlparser2/-/htmlparser2-10.1.0.tgz", "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", @@ -6223,8 +9424,6 @@ }, "node_modules/sass": { "version": "1.74.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.74.1.tgz", - "integrity": "sha512-w0Z9p/rWZWelb88ISOLyvqTWGmtmu2QJICqDBGyNnfG4OUnPX9BBjjYIXUpXCMOOg5MQWNpqzt876la1fsTvUA==", "dev": true, "license": "MIT", "dependencies": { @@ -6239,19 +9438,70 @@ "node": ">=14.0.0" } }, + "node_modules/saxes": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" } }, + "node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { @@ -6263,18 +9513,87 @@ }, "node_modules/shebang-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, "node_modules/slash": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", "engines": { @@ -6283,8 +9602,6 @@ }, "node_modules/source-map": { "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -6292,17 +9609,69 @@ }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, + "node_modules/stack-utils": { + "version": "2.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { @@ -6312,10 +9681,35 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { @@ -6327,59 +9721,82 @@ }, "node_modules/stylis": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", "license": "MIT" }, "node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/tabbable": { + "version": "6.2.0", + "license": "MIT" + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", "dependencies": { - "has-flag": "^4.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "license": "MIT", + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">= 0.4" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/tabbable": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", - "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", - "license": "MIT" - }, "node_modules/text-table": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true, "license": "MIT" }, "node_modules/tiny-invariant": { "version": "1.3.3", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { "version": "0.2.15", - "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6395,8 +9812,6 @@ }, "node_modules/tinyglobby/node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -6412,9 +9827,7 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", "dev": true, "license": "MIT", "engines": { @@ -6424,10 +9837,13 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tmpl": { + "version": "1.0.5", + "dev": true, + "license": "BSD-3-Clause" + }, "node_modules/to-regex-range": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6437,10 +9853,22 @@ "node": ">=8.0" } }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/ts-api-utils": { "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", "dev": true, "license": "MIT", "engines": { @@ -6450,16 +9878,74 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-jest": { + "version": "29.4.6", + "dev": true, + "license": "MIT", + "dependencies": { + "bs-logger": "^0.2.6", + "fast-json-stable-stringify": "^2.1.0", + "handlebars": "^4.7.8", + "json5": "^2.2.3", + "lodash.memoize": "^4.1.2", + "make-error": "^1.3.6", + "semver": "^7.7.3", + "type-fest": "^4.41.0", + "yargs-parser": "^21.1.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/transform": "^29.0.0 || ^30.0.0", + "@jest/types": "^29.0.0 || ^30.0.0", + "babel-jest": "^29.0.0 || ^30.0.0", + "jest": "^29.0.0 || ^30.0.0", + "jest-util": "^29.0.0 || ^30.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/transform": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jest-util": { + "optional": true + } + } + }, + "node_modules/ts-jest/node_modules/type-fest": { + "version": "4.41.0", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/tslib": { "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { @@ -6469,10 +9955,16 @@ "node": ">= 0.8.0" } }, + "node_modules/type-detect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/typescript": { "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", "dev": true, "license": "Apache-2.0", "bin": { @@ -6483,36 +9975,140 @@ "node": ">=14.17" } }, + "node_modules/uglify-js": { + "version": "3.19.3", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/undici-types": { "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, "license": "MIT" }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/use-sync-external-store": { "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/victory-vendor": { "version": "36.9.2", - "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz", - "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==", "dev": true, "license": "MIT AND ISC", "dependencies": { @@ -6534,8 +10130,6 @@ }, "node_modules/victory-vendor/node_modules/d3-array": { "version": "3.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", - "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", "dev": true, "license": "ISC", "dependencies": { @@ -6547,8 +10141,6 @@ }, "node_modules/victory-vendor/node_modules/d3-ease": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", - "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -6557,8 +10149,6 @@ }, "node_modules/victory-vendor/node_modules/d3-interpolate": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", - "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", "dev": true, "license": "ISC", "dependencies": { @@ -6570,8 +10160,6 @@ }, "node_modules/victory-vendor/node_modules/d3-path": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", "dev": true, "license": "ISC", "engines": { @@ -6580,8 +10168,6 @@ }, "node_modules/victory-vendor/node_modules/d3-scale": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", - "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", "dev": true, "license": "ISC", "dependencies": { @@ -6597,8 +10183,6 @@ }, "node_modules/victory-vendor/node_modules/d3-shape": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", - "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", "dev": true, "license": "ISC", "dependencies": { @@ -6610,8 +10194,6 @@ }, "node_modules/victory-vendor/node_modules/d3-time": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", - "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", "dev": true, "license": "ISC", "dependencies": { @@ -6623,8 +10205,6 @@ }, "node_modules/victory-vendor/node_modules/d3-timer": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", - "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", "dev": true, "license": "ISC", "engines": { @@ -6708,8 +10288,6 @@ }, "node_modules/vite/node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { @@ -6725,9 +10303,7 @@ } }, "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", "dev": true, "license": "MIT", "engines": { @@ -6737,10 +10313,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/walker": { + "version": "1.0.8", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, "node_modules/which": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { @@ -6753,43 +10343,126 @@ "node": ">= 8" } }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/word-wrap": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, + "node_modules/ws": { + "version": "8.18.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "dev": true, + "license": "MIT" + }, "node_modules/xmlhttprequest": { "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", "license": "MIT", "engines": { "node": ">=0.4.0" } }, + "node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/yallist": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", + "version": "2.9.0", "dev": true, "license": "ISC", "optional": true, @@ -6798,13 +10471,39 @@ "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" } }, "node_modules/yocto-queue": { "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { diff --git a/dashboard/package.json b/dashboard/package.json index 2dd2fac50c5..c35214b4d34 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -8,8 +8,21 @@ "dev": "vite", "build": "tsc && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 200", + "typecheck": "tsc --noEmit", "preview": "vite preview", - "prebuild": "cd src/views/Lineage/atlas-lineage && (npm ci 2>/dev/null || npm install) && npm run build" + "prebuild": "cd src/views/Lineage/atlas-lineage && (npm ci 2>/dev/null || npm install) && npm run build", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "test:all": "jest", + "test:ci": "jest --ci --coverage --maxWorkers=2", + "test:governance": "RUN_DEPENDENCY_GOVERNANCE=1 jest --testPathPattern=governance --runInBand", + "build:with-governance": "npm run test:governance && npm run build", + "test:debug": "node --inspect-brk node_modules/.bin/jest --runInBand", + "test:verbose": "jest --verbose", + "cypress:open": "cypress open", + "cypress:run": "cypress run", + "test:e2e": "cypress run" }, "dependencies": { "@dnd-kit/core": "6.1.0", @@ -47,8 +60,15 @@ "sanitize-html": "2.17.4" }, "devDependencies": { + "@babel/preset-env": "7.28.5", + "@babel/preset-react": "7.28.5", + "@babel/preset-typescript": "7.28.5", + "@testing-library/jest-dom": "6.9.1", + "@testing-library/react": "14.3.1", + "@testing-library/user-event": "14.6.1", "@types/autosuggest-highlight": "3.2.3", "@types/d3": "5.16.5", + "@types/jest": "29.5.14", "@types/node": "20.11.25", "@types/react": "18.2.56", "@types/react-dom": "18.2.19", @@ -56,11 +76,16 @@ "@typescript-eslint/eslint-plugin": "7.0.2", "@typescript-eslint/parser": "7.0.2", "@vitejs/plugin-react-swc": "3.9.0", + "babel-jest": "29.7.0", "eslint": "8.56.0", "eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-react-refresh": "0.4.5", + "jest": "29.7.0", + "jest-environment-jsdom": "29.7.0", "recharts": "2.15.1", "sass": "1.74.1", + "semver": "7.5.4", + "ts-jest": "29.4.6", "typescript": "5.2.2", "vite": "6.4.2" }, diff --git a/dashboard/pom.xml b/dashboard/pom.xml index 0dbf439003e..114742dbf2f 100644 --- a/dashboard/pom.xml +++ b/dashboard/pom.xml @@ -58,6 +58,7 @@ + org.apache.maven.plugins maven-resources-plugin 2.7 @@ -73,6 +74,20 @@ ${project.basedir}/ false + + + bin/** + dist/** + coverage/** + **/node_modules/** + target/** + + **/.cache/** + + ../dashboard/bin/** + ../dashboard/dist/** + ../dashboard/coverage/** + diff --git a/dashboard/src/ErrorBoundary.tsx b/dashboard/src/ErrorBoundary.tsx index 0edada99c45..95eb27eefe9 100644 --- a/dashboard/src/ErrorBoundary.tsx +++ b/dashboard/src/ErrorBoundary.tsx @@ -1,20 +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 + * 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 + * 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. + * 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. */ import { Component } from "react"; diff --git a/dashboard/src/__mocks__/fileMock.ts b/dashboard/src/__mocks__/fileMock.ts new file mode 100644 index 00000000000..f86ab8e0c10 --- /dev/null +++ b/dashboard/src/__mocks__/fileMock.ts @@ -0,0 +1,19 @@ +/* + * 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. + */ + +/** Mock for image and file imports in Jest tests */ +export default 'test-file-stub' diff --git a/dashboard/src/__mocks__/react-quill-new.tsx b/dashboard/src/__mocks__/react-quill-new.tsx new file mode 100644 index 00000000000..0fffe73b784 --- /dev/null +++ b/dashboard/src/__mocks__/react-quill-new.tsx @@ -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. + */ + +/** Mock for react-quill-new */ + +import React from 'react'; + +const ReactQuill = React.forwardRef(({ value, onChange, ...props }, ref) => { + return ( +
    +