Generat
_wait_for_meili_task(client.delete_index(temp_index_name))
+def _index_is_empty(index_name: str) -> bool:
+ """
+ Check if an index is empty
+
+ Args:
+ index_name (str): The name of the index to check
+ """
+ client = _get_meilisearch_client()
+ index = client.get_index(index_name)
+ return index.get_stats().number_of_documents == 0
+
+
+def _configure_index(index_name):
+ """
+ Configure the index. The following index settings are best changed on an empty index.
+ Changing them on a populated index will "re-index all documents in the index", which can take some time.
+
+ Args:
+ index_name (str): The name of the index to configure
+ """
+ client = _get_meilisearch_client()
+
+ # Mark usage_key as unique (it's not the primary key for the index, but nevertheless must be unique):
+ client.index(index_name).update_distinct_attribute(INDEX_DISTINCT_ATTRIBUTE)
+ # Mark which attributes can be used for filtering/faceted search:
+ client.index(index_name).update_filterable_attributes(INDEX_FILTERABLE_ATTRIBUTES)
+ # Mark which attributes are used for keyword search, in order of importance:
+ client.index(index_name).update_searchable_attributes(INDEX_SEARCHABLE_ATTRIBUTES)
+ # Mark which attributes can be used for sorting search results:
+ client.index(index_name).update_sortable_attributes(INDEX_SORTABLE_ATTRIBUTES)
+
+ # Update the search ranking rules to let the (optional) "sort" parameter take precedence over keyword relevance.
+ # cf https://www.meilisearch.com/docs/learn/core_concepts/relevancy
+ client.index(index_name).update_ranking_rules(INDEX_RANKING_RULES)
+
+
def _recurse_children(block, fn, status_cb: Callable[[str], None] | None = None) -> None:
"""
Recurse the children of an XBlock and call the given function for each
@@ -279,8 +322,75 @@ def is_meilisearch_enabled() -> bool:
return False
-# pylint: disable=too-many-statements
-def rebuild_index(status_cb: Callable[[str], None] | None = None) -> None:
+def reset_index(status_cb: Callable[[str], None] | None = None) -> None:
+ """
+ Reset the Meilisearch index, deleting all documents and reconfiguring it
+ """
+ if status_cb is None:
+ status_cb = log.info
+
+ status_cb("Creating new empty index...")
+ with _using_temp_index(status_cb) as temp_index_name:
+ _configure_index(temp_index_name)
+ status_cb("Index recreated!")
+ status_cb("Index reset complete.")
+
+
+def _is_index_configured(index_name: str) -> bool:
+ """
+ Check if an index is completely configured
+
+ Args:
+ index_name (str): The name of the index to check
+ """
+ client = _get_meilisearch_client()
+ index = client.get_index(index_name)
+ index_settings = index.get_settings()
+ for k, v in (
+ ("distinctAttribute", INDEX_DISTINCT_ATTRIBUTE),
+ ("filterableAttributes", INDEX_FILTERABLE_ATTRIBUTES),
+ ("searchableAttributes", INDEX_SEARCHABLE_ATTRIBUTES),
+ ("sortableAttributes", INDEX_SORTABLE_ATTRIBUTES),
+ ("rankingRules", INDEX_RANKING_RULES),
+ ):
+ setting = index_settings.get(k, [])
+ if isinstance(v, list):
+ v = set(v)
+ setting = set(setting)
+ if setting != v:
+ return False
+ return True
+
+
+def init_index(status_cb: Callable[[str], None] | None = None, warn_cb: Callable[[str], None] | None = None) -> None:
+ """
+ Initialize the Meilisearch index, creating it and configuring it if it doesn't exist
+ """
+ if status_cb is None:
+ status_cb = log.info
+ if warn_cb is None:
+ warn_cb = log.warning
+
+ if _index_exists(STUDIO_INDEX_NAME):
+ if _index_is_empty(STUDIO_INDEX_NAME):
+ warn_cb(
+ "The studio search index is empty. Please run ./manage.py cms reindex_studio"
+ " --experimental [--incremental]"
+ )
+ return
+ if not _is_index_configured(STUDIO_INDEX_NAME):
+ warn_cb(
+ "A rebuild of the index is required. Please run ./manage.py cms reindex_studio"
+ " --experimental [--incremental]"
+ )
+ return
+ status_cb("Index already exists and is configured.")
+ return
+
+ reset_index(status_cb)
+
+
+def rebuild_index(status_cb: Callable[[str], None] | None = None, incremental=False) -> None: # lint-amnesty, pylint: disable=too-many-statements
"""
Rebuild the Meilisearch index from scratch
"""
@@ -292,7 +402,14 @@ def rebuild_index(status_cb: Callable[[str], None] | None = None) -> None:
# Get the lists of libraries
status_cb("Counting libraries...")
- lib_keys = [lib.library_key for lib in lib_api.ContentLibrary.objects.select_related('org').only('org', 'slug')]
+ keys_indexed = []
+ if incremental:
+ keys_indexed = list(IncrementalIndexCompleted.objects.values_list("context_key", flat=True))
+ lib_keys = [
+ lib.library_key
+ for lib in lib_api.ContentLibrary.objects.select_related("org").only("org", "slug").order_by("-id")
+ if lib.library_key not in keys_indexed
+ ]
num_libraries = len(lib_keys)
# Get the list of courses
@@ -300,88 +417,25 @@ def rebuild_index(status_cb: Callable[[str], None] | None = None) -> None:
num_courses = CourseOverview.objects.count()
# Some counters so we can track our progress as indexing progresses:
- num_contexts = num_courses + num_libraries
- num_contexts_done = 0 # How many courses/libraries we've indexed
+ num_libs_skipped = len(keys_indexed)
+ num_contexts = num_courses + num_libraries + num_libs_skipped
+ num_contexts_done = 0 + num_libs_skipped # How many courses/libraries we've indexed
num_blocks_done = 0 # How many individual components/XBlocks we've indexed
status_cb(f"Found {num_courses} courses, {num_libraries} libraries.")
- with _using_temp_index(status_cb) as temp_index_name:
+ with _using_temp_index(status_cb) if not incremental else nullcontext(STUDIO_INDEX_NAME) as index_name:
############## Configure the index ##############
- # The following index settings are best changed on an empty index.
- # Changing them on a populated index will "re-index all documents in the index, which can take some time"
+ # The index settings are best changed on an empty index.
+ # Changing them on a populated index will "re-index all documents in the index", which can take some time
# and use more RAM. Instead, we configure an empty index then populate it one course/library at a time.
-
- # Mark usage_key as unique (it's not the primary key for the index, but nevertheless must be unique):
- client.index(temp_index_name).update_distinct_attribute(Fields.usage_key)
- # Mark which attributes can be used for filtering/faceted search:
- client.index(temp_index_name).update_filterable_attributes([
- # Get specific block/collection using combination of block_id and context_key
- Fields.block_id,
- Fields.block_type,
- Fields.context_key,
- Fields.usage_key,
- Fields.org,
- Fields.tags,
- Fields.tags + "." + Fields.tags_taxonomy,
- Fields.tags + "." + Fields.tags_level0,
- Fields.tags + "." + Fields.tags_level1,
- Fields.tags + "." + Fields.tags_level2,
- Fields.tags + "." + Fields.tags_level3,
- Fields.collections,
- Fields.collections + "." + Fields.collections_display_name,
- Fields.collections + "." + Fields.collections_key,
- Fields.type,
- Fields.access_id,
- Fields.last_published,
- Fields.content + "." + Fields.problem_types,
- ])
- # Mark which attributes are used for keyword search, in order of importance:
- client.index(temp_index_name).update_searchable_attributes([
- # Keyword search does _not_ search the course name, course ID, breadcrumbs, block type, or other fields.
- Fields.display_name,
- Fields.block_id,
- Fields.content,
- Fields.description,
- Fields.tags,
- Fields.collections,
- # If we don't list the following sub-fields _explicitly_, they're only sometimes searchable - that is, they
- # are searchable only if at least one document in the index has a value. If we didn't list them here and,
- # say, there were no tags.level3 tags in the index, the client would get an error if trying to search for
- # these sub-fields: "Attribute `tags.level3` is not searchable."
- Fields.tags + "." + Fields.tags_taxonomy,
- Fields.tags + "." + Fields.tags_level0,
- Fields.tags + "." + Fields.tags_level1,
- Fields.tags + "." + Fields.tags_level2,
- Fields.tags + "." + Fields.tags_level3,
- Fields.collections + "." + Fields.collections_display_name,
- Fields.collections + "." + Fields.collections_key,
- Fields.published + "." + Fields.display_name,
- Fields.published + "." + Fields.published_description,
- ])
- # Mark which attributes can be used for sorting search results:
- client.index(temp_index_name).update_sortable_attributes([
- Fields.display_name,
- Fields.created,
- Fields.modified,
- Fields.last_published,
- ])
-
- # Update the search ranking rules to let the (optional) "sort" parameter take precedence over keyword relevance.
- # cf https://www.meilisearch.com/docs/learn/core_concepts/relevancy
- client.index(temp_index_name).update_ranking_rules([
- "sort",
- "words",
- "typo",
- "proximity",
- "attribute",
- "exactness",
- ])
+ if not incremental:
+ _configure_index(index_name)
############## Libraries ##############
status_cb("Indexing libraries...")
- def index_library(lib_key: str) -> list:
+ def index_library(lib_key: LibraryLocatorV2) -> list:
docs = []
for component in lib_api.get_library_components(lib_key):
try:
@@ -396,7 +450,7 @@ def index_library(lib_key: str) -> list:
if docs:
try:
# Add all the docs in this library at once (usually faster than adding one at a time):
- _wait_for_meili_task(client.index(temp_index_name).add_documents(docs))
+ _wait_for_meili_task(client.index(index_name).add_documents(docs))
except (TypeError, KeyError, MeilisearchError) as err:
status_cb(f"Error indexing library {lib_key}: {err}")
return docs
@@ -416,7 +470,7 @@ def index_collection_batch(batch, num_done, library_key) -> int:
if docs:
try:
# Add docs in batch of 100 at once (usually faster than adding one at a time):
- _wait_for_meili_task(client.index(temp_index_name).add_documents(docs))
+ _wait_for_meili_task(client.index(index_name).add_documents(docs))
except (TypeError, KeyError, MeilisearchError) as err:
status_cb(f"Error indexing collection batch {p}: {err}")
return num_done
@@ -439,6 +493,8 @@ def index_collection_batch(batch, num_done, library_key) -> int:
num_collections_done,
lib_key,
)
+ if incremental:
+ IncrementalIndexCompleted.objects.get_or_create(context_key=lib_key)
status_cb(f"{num_collections_done}/{num_collections} collections indexed for library {lib_key}")
num_contexts_done += 1
@@ -464,7 +520,7 @@ def add_with_children(block):
if docs:
# Add all the docs in this course at once (usually faster than adding one at a time):
- _wait_for_meili_task(client.index(temp_index_name).add_documents(docs))
+ _wait_for_meili_task(client.index(index_name).add_documents(docs))
return docs
paginator = Paginator(CourseOverview.objects.only('id', 'display_name'), 1000)
@@ -473,10 +529,16 @@ def add_with_children(block):
status_cb(
f"{num_contexts_done + 1}/{num_contexts}. Now indexing course {course.display_name} ({course.id})"
)
+ if course.id in keys_indexed:
+ num_contexts_done += 1
+ continue
course_docs = index_course(course)
+ if incremental:
+ IncrementalIndexCompleted.objects.get_or_create(context_key=course.id)
num_contexts_done += 1
num_blocks_done += len(course_docs)
+ IncrementalIndexCompleted.objects.all().delete()
status_cb(f"Done! {num_blocks_done} blocks indexed across {num_contexts_done} courses, collections and libraries.")
diff --git a/openedx/core/djangoapps/content/search/documents.py b/openedx/core/djangoapps/content/search/documents.py
index 7e547ca4d889..40fe4529272b 100644
--- a/openedx/core/djangoapps/content/search/documents.py
+++ b/openedx/core/djangoapps/content/search/documents.py
@@ -80,6 +80,7 @@ class Fields:
published = "published"
published_display_name = "display_name"
published_description = "description"
+ published_num_children = "num_children"
# Note: new fields or values can be added at any time, but if they need to be indexed for filtering or keyword
# search, the index configuration will need to be changed, which is only done as part of the 'reindex_studio'
@@ -305,7 +306,10 @@ def _collections_for_content_object(object_id: UsageKey | LearningContextKey) ->
If the object is in no collections, returns:
{
- "collections": {},
+ "collections": {
+ "display_name": [],
+ "key": [],
+ },
}
"""
@@ -488,6 +492,15 @@ def searchable_doc_for_collection(
if collection:
assert collection.key == collection_key
+ draft_num_children = authoring_api.filter_publishable_entities(
+ collection.entities,
+ has_draft=True,
+ ).count()
+ published_num_children = authoring_api.filter_publishable_entities(
+ collection.entities,
+ has_published=True,
+ ).count()
+
doc.update({
Fields.context_key: str(library_key),
Fields.org: str(library_key.org),
@@ -498,7 +511,10 @@ def searchable_doc_for_collection(
Fields.description: collection.description,
Fields.created: collection.created.timestamp(),
Fields.modified: collection.modified.timestamp(),
- Fields.num_children: collection.entities.count(),
+ Fields.num_children: draft_num_children,
+ Fields.published: {
+ Fields.published_num_children: published_num_children,
+ },
Fields.access_id: _meili_access_id_from_context_key(library_key),
Fields.breadcrumbs: [{"display_name": collection.learning_package.title}],
})
diff --git a/openedx/core/djangoapps/content/search/index_config.py b/openedx/core/djangoapps/content/search/index_config.py
new file mode 100644
index 000000000000..9570956e425e
--- /dev/null
+++ b/openedx/core/djangoapps/content/search/index_config.py
@@ -0,0 +1,70 @@
+"""Configuration for the search index."""
+from .documents import Fields
+
+
+INDEX_DISTINCT_ATTRIBUTE = "usage_key"
+
+# Mark which attributes can be used for filtering/faceted search:
+INDEX_FILTERABLE_ATTRIBUTES = [
+ # Get specific block/collection using combination of block_id and context_key
+ Fields.block_id,
+ Fields.block_type,
+ Fields.context_key,
+ Fields.usage_key,
+ Fields.org,
+ Fields.tags,
+ Fields.tags + "." + Fields.tags_taxonomy,
+ Fields.tags + "." + Fields.tags_level0,
+ Fields.tags + "." + Fields.tags_level1,
+ Fields.tags + "." + Fields.tags_level2,
+ Fields.tags + "." + Fields.tags_level3,
+ Fields.collections,
+ Fields.collections + "." + Fields.collections_display_name,
+ Fields.collections + "." + Fields.collections_key,
+ Fields.type,
+ Fields.access_id,
+ Fields.last_published,
+ Fields.content + "." + Fields.problem_types,
+]
+
+# Mark which attributes are used for keyword search, in order of importance:
+INDEX_SEARCHABLE_ATTRIBUTES = [
+ # Keyword search does _not_ search the course name, course ID, breadcrumbs, block type, or other fields.
+ Fields.display_name,
+ Fields.block_id,
+ Fields.content,
+ Fields.description,
+ Fields.tags,
+ Fields.collections,
+ # If we don't list the following sub-fields _explicitly_, they're only sometimes searchable - that is, they
+ # are searchable only if at least one document in the index has a value. If we didn't list them here and,
+ # say, there were no tags.level3 tags in the index, the client would get an error if trying to search for
+ # these sub-fields: "Attribute `tags.level3` is not searchable."
+ Fields.tags + "." + Fields.tags_taxonomy,
+ Fields.tags + "." + Fields.tags_level0,
+ Fields.tags + "." + Fields.tags_level1,
+ Fields.tags + "." + Fields.tags_level2,
+ Fields.tags + "." + Fields.tags_level3,
+ Fields.collections + "." + Fields.collections_display_name,
+ Fields.collections + "." + Fields.collections_key,
+ Fields.published + "." + Fields.display_name,
+ Fields.published + "." + Fields.published_description,
+]
+
+# Mark which attributes can be used for sorting search results:
+INDEX_SORTABLE_ATTRIBUTES = [
+ Fields.display_name,
+ Fields.created,
+ Fields.modified,
+ Fields.last_published,
+]
+
+# Update the search ranking rules to let the (optional) "sort" parameter take precedence over keyword relevance.
+INDEX_RANKING_RULES = [
+ "sort",
+ "words",
+ "typo",
+ "proximity",
+ "attribute",
+ "exactness",
+]
diff --git a/openedx/core/djangoapps/content/search/management/commands/reindex_studio.py b/openedx/core/djangoapps/content/search/management/commands/reindex_studio.py
index 3767ebcba6c9..2d8bb29f7a1f 100644
--- a/openedx/core/djangoapps/content/search/management/commands/reindex_studio.py
+++ b/openedx/core/djangoapps/content/search/management/commands/reindex_studio.py
@@ -18,8 +18,11 @@ class Command(BaseCommand):
"""
def add_arguments(self, parser):
- parser.add_argument('--experimental', action='store_true')
- parser.set_defaults(experimental=False)
+ parser.add_argument("--experimental", action="store_true")
+ parser.add_argument("--reset", action="store_true")
+ parser.add_argument("--init", action="store_true")
+ parser.add_argument("--incremental", action="store_true")
+ parser.set_defaults(experimental=False, reset=False, init=False, incremental=False)
def handle(self, *args, **options):
"""
@@ -34,4 +37,11 @@ def handle(self, *args, **options):
"Use the --experimental argument to acknowledge and run it."
)
- api.rebuild_index(self.stdout.write)
+ if options["reset"]:
+ api.reset_index(self.stdout.write)
+ elif options["init"]:
+ api.init_index(self.stdout.write, self.stderr.write)
+ elif options["incremental"]:
+ api.rebuild_index(self.stdout.write, incremental=True)
+ else:
+ api.rebuild_index(self.stdout.write)
diff --git a/openedx/core/djangoapps/content/search/migrations/0002_incrementalindexcompleted.py b/openedx/core/djangoapps/content/search/migrations/0002_incrementalindexcompleted.py
new file mode 100644
index 000000000000..a316c35a7dfe
--- /dev/null
+++ b/openedx/core/djangoapps/content/search/migrations/0002_incrementalindexcompleted.py
@@ -0,0 +1,21 @@
+# Generated by Django 4.2.16 on 2024-11-15 12:40
+
+from django.db import migrations, models
+import opaque_keys.edx.django.models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('search', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='IncrementalIndexCompleted',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('context_key', opaque_keys.edx.django.models.LearningContextKeyField(max_length=255, unique=True)),
+ ],
+ ),
+ ]
diff --git a/openedx/core/djangoapps/content/search/models.py b/openedx/core/djangoapps/content/search/models.py
index 711c493ff895..6fa53ef17b34 100644
--- a/openedx/core/djangoapps/content/search/models.py
+++ b/openedx/core/djangoapps/content/search/models.py
@@ -65,3 +65,15 @@ def get_access_ids_for_request(request: Request, omit_orgs: list[str] = None) ->
course_clause | library_clause
).order_by('-id').values_list("id", flat=True)
)
+
+
+class IncrementalIndexCompleted(models.Model):
+ """
+ Stores the contex keys of aleady indexed courses and libraries for incremental indexing.
+ """
+
+ context_key = LearningContextKeyField(
+ max_length=255,
+ unique=True,
+ null=False,
+ )
diff --git a/openedx/core/djangoapps/content/search/tests/test_api.py b/openedx/core/djangoapps/content/search/tests/test_api.py
index 990226f343cf..c9c2b2589a31 100644
--- a/openedx/core/djangoapps/content/search/tests/test_api.py
+++ b/openedx/core/djangoapps/content/search/tests/test_api.py
@@ -10,8 +10,10 @@
from opaque_keys.edx.keys import UsageKey
import ddt
+import pytest
from django.test import override_settings
from freezegun import freeze_time
+from meilisearch.errors import MeilisearchApiError
from openedx_learning.api import authoring as authoring_api
from organizations.tests.factories import OrganizationFactory
@@ -26,7 +28,7 @@
try:
# This import errors in the lms because content.search is not an installed app there.
from .. import api
- from ..models import SearchAccess
+ from ..models import SearchAccess, IncrementalIndexCompleted
except RuntimeError:
SearchAccess = {}
@@ -198,6 +200,9 @@ def setUp(self):
"created": created_date.timestamp(),
"modified": created_date.timestamp(),
"access_id": lib_access.id,
+ "published": {
+ "num_children": 0
+ },
"breadcrumbs": [{"display_name": "Library"}],
}
@@ -236,6 +241,87 @@ def test_reindex_meilisearch(self, mock_meilisearch):
any_order=True,
)
+ @override_settings(MEILISEARCH_ENABLED=True)
+ def test_reindex_meilisearch_incremental(self, mock_meilisearch):
+
+ # Add tags field to doc, since reindex calls includes tags
+ doc_sequential = copy.deepcopy(self.doc_sequential)
+ doc_sequential["tags"] = {}
+ doc_vertical = copy.deepcopy(self.doc_vertical)
+ doc_vertical["tags"] = {}
+ doc_problem1 = copy.deepcopy(self.doc_problem1)
+ doc_problem1["tags"] = {}
+ doc_problem1["collections"] = {"display_name": [], "key": []}
+ doc_problem2 = copy.deepcopy(self.doc_problem2)
+ doc_problem2["tags"] = {}
+ doc_problem2["collections"] = {"display_name": [], "key": []}
+ doc_collection = copy.deepcopy(self.collection_dict)
+ doc_collection["tags"] = {}
+
+ api.rebuild_index(incremental=True)
+ assert mock_meilisearch.return_value.index.return_value.add_documents.call_count == 3
+ mock_meilisearch.return_value.index.return_value.add_documents.assert_has_calls(
+ [
+ call([doc_sequential, doc_vertical]),
+ call([doc_problem1, doc_problem2]),
+ call([doc_collection]),
+ ],
+ any_order=True,
+ )
+
+ # Now we simulate interruption by passing this function to the status_cb argument
+ def simulated_interruption(message):
+ # this exception prevents courses from being indexed
+ if "Indexing courses" in message:
+ raise Exception("Simulated interruption")
+
+ with pytest.raises(Exception, match="Simulated interruption"):
+ api.rebuild_index(simulated_interruption, incremental=True)
+
+ # two more calls due to collections
+ assert mock_meilisearch.return_value.index.return_value.add_documents.call_count == 5
+ assert IncrementalIndexCompleted.objects.all().count() == 1
+ api.rebuild_index(incremental=True)
+ assert IncrementalIndexCompleted.objects.all().count() == 0
+ # one missing course indexed
+ assert mock_meilisearch.return_value.index.return_value.add_documents.call_count == 6
+
+ @override_settings(MEILISEARCH_ENABLED=True)
+ def test_reset_meilisearch_index(self, mock_meilisearch):
+ api.reset_index()
+ mock_meilisearch.return_value.swap_indexes.assert_called_once()
+ mock_meilisearch.return_value.create_index.assert_called_once()
+ mock_meilisearch.return_value.delete_index.call_count = 2
+ api.reset_index()
+ mock_meilisearch.return_value.delete_index.call_count = 4
+
+ @override_settings(MEILISEARCH_ENABLED=True)
+ def test_init_meilisearch_index(self, mock_meilisearch):
+ # Test index already exists
+ api.init_index()
+ mock_meilisearch.return_value.swap_indexes.assert_not_called()
+ mock_meilisearch.return_value.create_index.assert_not_called()
+ mock_meilisearch.return_value.delete_index.assert_not_called()
+
+ # Test index already exists and has no documents
+ mock_meilisearch.return_value.get_stats.return_value = 0
+ api.init_index()
+ mock_meilisearch.return_value.swap_indexes.assert_not_called()
+ mock_meilisearch.return_value.create_index.assert_not_called()
+ mock_meilisearch.return_value.delete_index.assert_not_called()
+
+ mock_meilisearch.return_value.get_index.side_effect = [
+ MeilisearchApiError("Testing reindex", Mock(text='{"code":"index_not_found"}')),
+ MeilisearchApiError("Testing reindex", Mock(text='{"code":"index_not_found"}')),
+ Mock(created_at=1),
+ Mock(created_at=1),
+ Mock(created_at=1),
+ ]
+ api.init_index()
+ mock_meilisearch.return_value.swap_indexes.assert_called_once()
+ mock_meilisearch.return_value.create_index.assert_called_once()
+ mock_meilisearch.return_value.delete_index.call_count = 2
+
@override_settings(MEILISEARCH_ENABLED=True)
@patch(
"openedx.core.djangoapps.content.search.api.searchable_doc_for_collection",
@@ -472,6 +558,9 @@ def test_index_library_block_and_collections(self, mock_meilisearch):
"created": created_date.timestamp(),
"modified": created_date.timestamp(),
"access_id": lib_access.id,
+ "published": {
+ "num_children": 0
+ },
"breadcrumbs": [{"display_name": "Library"}],
}
doc_collection2_created = {
@@ -487,6 +576,9 @@ def test_index_library_block_and_collections(self, mock_meilisearch):
"created": created_date.timestamp(),
"modified": created_date.timestamp(),
"access_id": lib_access.id,
+ "published": {
+ "num_children": 0
+ },
"breadcrumbs": [{"display_name": "Library"}],
}
doc_collection2_updated = {
@@ -502,6 +594,9 @@ def test_index_library_block_and_collections(self, mock_meilisearch):
"created": created_date.timestamp(),
"modified": updated_date.timestamp(),
"access_id": lib_access.id,
+ "published": {
+ "num_children": 0
+ },
"breadcrumbs": [{"display_name": "Library"}],
}
doc_collection1_updated = {
@@ -517,6 +612,9 @@ def test_index_library_block_and_collections(self, mock_meilisearch):
"created": created_date.timestamp(),
"modified": updated_date.timestamp(),
"access_id": lib_access.id,
+ "published": {
+ "num_children": 0
+ },
"breadcrumbs": [{"display_name": "Library"}],
}
doc_problem_with_collection1 = {
diff --git a/openedx/core/djangoapps/content/search/tests/test_documents.py b/openedx/core/djangoapps/content/search/tests/test_documents.py
index e0a604c24feb..603cc8d92f5e 100644
--- a/openedx/core/djangoapps/content/search/tests/test_documents.py
+++ b/openedx/core/djangoapps/content/search/tests/test_documents.py
@@ -443,5 +443,37 @@ def test_collection_with_library(self):
'tags': {
'taxonomy': ['Difficulty'],
'level0': ['Difficulty > Normal']
+ },
+ "published": {
+ "num_children": 0
+ }
+ }
+
+ def test_collection_with_published_library(self):
+ library_api.publish_changes(self.library.key)
+
+ doc = searchable_doc_for_collection(self.library.key, self.collection.key)
+ doc.update(searchable_doc_tags_for_collection(self.library.key, self.collection.key))
+
+ assert doc == {
+ "id": "lib-collectionedx2012_falltoy_collection-d1d907a4",
+ "block_id": self.collection.key,
+ "usage_key": self.collection_usage_key,
+ "type": "collection",
+ "org": "edX",
+ "display_name": "Toy Collection",
+ "description": "my toy collection description",
+ "num_children": 1,
+ "context_key": "lib:edX:2012_Fall",
+ "access_id": self.library_access_id,
+ "breadcrumbs": [{"display_name": "some content_library"}],
+ "created": 1680674828.0,
+ "modified": 1680674828.0,
+ 'tags': {
+ 'taxonomy': ['Difficulty'],
+ 'level0': ['Difficulty > Normal']
+ },
+ "published": {
+ "num_children": 1
}
}
diff --git a/openedx/core/djangoapps/content/search/tests/test_handlers.py b/openedx/core/djangoapps/content/search/tests/test_handlers.py
index 3577cbfc5692..dc274d182696 100644
--- a/openedx/core/djangoapps/content/search/tests/test_handlers.py
+++ b/openedx/core/djangoapps/content/search/tests/test_handlers.py
@@ -185,3 +185,13 @@ def test_create_delete_library_block(self, meilisearch_client):
meilisearch_client.return_value.index.return_value.delete_document.assert_called_with(
"lborgalib_aproblemproblem1-ca3186e9"
)
+
+ # Restore the Library Block
+ library_api.restore_library_block(problem.usage_key)
+ meilisearch_client.return_value.index.return_value.update_documents.assert_any_call([doc_problem])
+ meilisearch_client.return_value.index.return_value.update_documents.assert_any_call(
+ [{'id': doc_problem['id'], 'collections': {'display_name': [], 'key': []}}]
+ )
+ meilisearch_client.return_value.index.return_value.update_documents.assert_any_call(
+ [{'id': doc_problem['id'], 'tags': {}}]
+ )
diff --git a/openedx/core/djangoapps/content_libraries/api.py b/openedx/core/djangoapps/content_libraries/api.py
index 3a4b9535bbba..c51c707fc470 100644
--- a/openedx/core/djangoapps/content_libraries/api.py
+++ b/openedx/core/djangoapps/content_libraries/api.py
@@ -83,6 +83,7 @@
ContentLibraryData,
LibraryBlockData,
LibraryCollectionData,
+ ContentObjectChangedData,
)
from openedx_events.content_authoring.signals import (
CONTENT_LIBRARY_CREATED,
@@ -92,6 +93,7 @@
LIBRARY_BLOCK_DELETED,
LIBRARY_BLOCK_UPDATED,
LIBRARY_COLLECTION_UPDATED,
+ CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
)
from openedx_learning.api import authoring as authoring_api
from openedx_learning.api.authoring_models import (
@@ -306,6 +308,13 @@ class LibraryXBlockType:
# ============
+def user_can_create_library(user: AbstractUser) -> bool:
+ """
+ Check if the user has permission to create a content library.
+ """
+ return user.has_perm(permissions.CAN_CREATE_CONTENT_LIBRARY)
+
+
def get_libraries_for_user(user, org=None, text_search=None, order=None):
"""
Return content libraries that the user has permission to view.
@@ -684,7 +693,11 @@ def _get_library_component_tags_count(library_key) -> dict:
return get_object_tag_counts(library_key_pattern, count_implicit=True)
-def get_library_components(library_key, text_search=None, block_types=None) -> QuerySet[Component]:
+def get_library_components(
+ library_key,
+ text_search=None,
+ block_types=None,
+) -> QuerySet[Component]:
"""
Get the library components and filter.
@@ -700,6 +713,7 @@ def get_library_components(library_key, text_search=None, block_types=None) -> Q
type_names=block_types,
draft_title=text_search,
)
+
return components
@@ -1093,15 +1107,71 @@ def delete_library_block(usage_key, remove_from_parent=True):
Delete the specified block from this library (soft delete).
"""
component = get_component_from_usage_key(usage_key)
+ library_key = usage_key.context_key
+ affected_collections = authoring_api.get_entity_collections(component.learning_package_id, component.key)
+
authoring_api.soft_delete_draft(component.pk)
LIBRARY_BLOCK_DELETED.send_event(
library_block=LibraryBlockData(
- library_key=usage_key.context_key,
+ library_key=library_key,
+ usage_key=usage_key
+ )
+ )
+
+ # For each collection, trigger LIBRARY_COLLECTION_UPDATED signal and set background=True to trigger
+ # collection indexing asynchronously.
+ #
+ # To delete the component on collections
+ for collection in affected_collections:
+ LIBRARY_COLLECTION_UPDATED.send_event(
+ library_collection=LibraryCollectionData(
+ library_key=library_key,
+ collection_key=collection.key,
+ background=True,
+ )
+ )
+
+
+def restore_library_block(usage_key):
+ """
+ Restore the specified library block.
+ """
+ component = get_component_from_usage_key(usage_key)
+ library_key = usage_key.context_key
+ affected_collections = authoring_api.get_entity_collections(component.learning_package_id, component.key)
+
+ # Set draft version back to the latest available component version id.
+ authoring_api.set_draft_version(component.pk, component.versioning.latest.pk)
+
+ LIBRARY_BLOCK_CREATED.send_event(
+ library_block=LibraryBlockData(
+ library_key=library_key,
usage_key=usage_key
)
)
+ # Add tags and collections back to index
+ CONTENT_OBJECT_ASSOCIATIONS_CHANGED.send_event(
+ content_object=ContentObjectChangedData(
+ object_id=str(usage_key),
+ changes=["collections", "tags"],
+ ),
+ )
+
+ # For each collection, trigger LIBRARY_COLLECTION_UPDATED signal and set background=True to trigger
+ # collection indexing asynchronously.
+ #
+ # To restore the component in the collections
+ for collection in affected_collections:
+ LIBRARY_COLLECTION_UPDATED.send_event(
+ library_collection=LibraryCollectionData(
+ library_key=library_key,
+ collection_key=collection.key,
+ background=True,
+ )
+ )
+
def get_library_block_static_asset_files(usage_key) -> list[LibraryXBlockStaticFile]:
"""
@@ -1318,6 +1388,39 @@ def revert_changes(library_key):
)
)
+ # For each collection, trigger LIBRARY_COLLECTION_UPDATED signal and set background=True to trigger
+ # collection indexing asynchronously.
+ #
+ # This is to update component counts in all library collections,
+ # because there may be components that have been discarded in the revert.
+ for collection in authoring_api.get_collections(learning_package.id):
+ LIBRARY_COLLECTION_UPDATED.send_event(
+ library_collection=LibraryCollectionData(
+ library_key=library_key,
+ collection_key=collection.key,
+ background=True,
+ )
+ )
+
+ # Reindex components that are in collections
+ #
+ # Use case: When a component that was within a collection has been deleted
+ # and the changes are reverted, the component should appear in the
+ # collection again.
+ components_in_collections = authoring_api.get_components(
+ learning_package.id, draft=True, namespace='xblock.v1',
+ ).filter(publishable_entity__collections__isnull=False)
+
+ for component in components_in_collections:
+ usage_key = library_component_usage_key(library_key, component)
+
+ CONTENT_OBJECT_ASSOCIATIONS_CHANGED.send_event(
+ content_object=ContentObjectChangedData(
+ object_id=str(usage_key),
+ changes=["collections"],
+ ),
+ )
+
def create_library_collection(
library_key: LibraryLocatorV2,
diff --git a/openedx/core/djangoapps/content_libraries/permissions.py b/openedx/core/djangoapps/content_libraries/permissions.py
index 17671b5659f8..4e72381986ed 100644
--- a/openedx/core/djangoapps/content_libraries/permissions.py
+++ b/openedx/core/djangoapps/content_libraries/permissions.py
@@ -48,6 +48,12 @@ def is_studio_request(_):
return settings.SERVICE_VARIANT == "cms"
+@blanket_rule
+def is_course_creator(user):
+ from cms.djangoapps.course_creators.views import get_course_creator_status
+
+ return get_course_creator_status(user) == 'granted'
+
########################### Permissions ###########################
# Is the user allowed to view XBlocks from the specified content library
@@ -68,7 +74,10 @@ def is_studio_request(_):
# Is the user allowed to create content libraries?
CAN_CREATE_CONTENT_LIBRARY = 'content_libraries.create_library'
-perms[CAN_CREATE_CONTENT_LIBRARY] = is_user_active
+if settings.FEATURES.get('ENABLE_CREATOR_GROUP', False):
+ perms[CAN_CREATE_CONTENT_LIBRARY] = is_global_staff | (is_user_active & is_course_creator)
+else:
+ perms[CAN_CREATE_CONTENT_LIBRARY] = is_global_staff
# Is the user allowed to view the specified content library in Studio,
# including to view the raw OLX and asset files?
@@ -76,8 +85,8 @@ def is_studio_request(_):
perms[CAN_VIEW_THIS_CONTENT_LIBRARY] = is_user_active & (
# Global staff can access any library
is_global_staff |
- # Some libraries allow anyone to view them in Studio:
- Attribute('allow_public_read', True) |
+ # Libraries with "public read" permissions can be accessed only by course creators
+ (Attribute('allow_public_read', True) & is_course_creator) |
# Otherwise the user must be part of the library's team
has_explicit_read_permission_for_library
)
diff --git a/openedx/core/djangoapps/content_libraries/tests/base.py b/openedx/core/djangoapps/content_libraries/tests/base.py
index b06565f9951e..ddf2e6e33658 100644
--- a/openedx/core/djangoapps/content_libraries/tests/base.py
+++ b/openedx/core/djangoapps/content_libraries/tests/base.py
@@ -71,7 +71,7 @@ class ContentLibrariesRestApiTest(APITransactionTestCase):
def setUp(self):
super().setUp()
- self.user = UserFactory.create(username="Bob", email="bob@example.com", password="edx")
+ self.user = UserFactory.create(username="Bob", email="bob@example.com", password="edx", is_staff=True)
# Create an organization
self.organization, _ = Organization.objects.get_or_create(
short_name="CL-TEST",
diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py
index c526e7b1a1f3..203cc7a9397a 100644
--- a/openedx/core/djangoapps/content_libraries/tests/test_api.py
+++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py
@@ -561,3 +561,184 @@ def test_set_library_component_collections(self):
},
collection_update_event_receiver.call_args_list[1].kwargs,
)
+
+ def test_delete_library_block(self):
+ api.update_library_collection_components(
+ self.lib1.library_key,
+ self.col1.key,
+ usage_keys=[
+ UsageKey.from_string(self.lib1_problem_block["id"]),
+ UsageKey.from_string(self.lib1_html_block["id"]),
+ ],
+ )
+
+ event_receiver = mock.Mock()
+ LIBRARY_COLLECTION_UPDATED.connect(event_receiver)
+
+ api.delete_library_block(UsageKey.from_string(self.lib1_problem_block["id"]))
+
+ assert event_receiver.call_count == 1
+ self.assertDictContainsSubset(
+ {
+ "signal": LIBRARY_COLLECTION_UPDATED,
+ "sender": None,
+ "library_collection": LibraryCollectionData(
+ self.lib1.library_key,
+ collection_key=self.col1.key,
+ background=True,
+ ),
+ },
+ event_receiver.call_args_list[0].kwargs,
+ )
+
+ def test_restore_library_block(self):
+ api.update_library_collection_components(
+ self.lib1.library_key,
+ self.col1.key,
+ usage_keys=[
+ UsageKey.from_string(self.lib1_problem_block["id"]),
+ UsageKey.from_string(self.lib1_html_block["id"]),
+ ],
+ )
+
+ event_receiver = mock.Mock()
+ LIBRARY_COLLECTION_UPDATED.connect(event_receiver)
+
+ api.restore_library_block(UsageKey.from_string(self.lib1_problem_block["id"]))
+
+ assert event_receiver.call_count == 1
+ self.assertDictContainsSubset(
+ {
+ "signal": LIBRARY_COLLECTION_UPDATED,
+ "sender": None,
+ "library_collection": LibraryCollectionData(
+ self.lib1.library_key,
+ collection_key=self.col1.key,
+ background=True,
+ ),
+ },
+ event_receiver.call_args_list[0].kwargs,
+ )
+
+ def test_add_component_and_revert(self):
+ # Add component and publish
+ api.update_library_collection_components(
+ self.lib1.library_key,
+ self.col1.key,
+ usage_keys=[
+ UsageKey.from_string(self.lib1_problem_block["id"]),
+ ],
+ )
+ api.publish_changes(self.lib1.library_key)
+
+ # Add component and revert
+ api.update_library_collection_components(
+ self.lib1.library_key,
+ self.col1.key,
+ usage_keys=[
+ UsageKey.from_string(self.lib1_html_block["id"]),
+ ],
+ )
+
+ event_receiver = mock.Mock()
+ CONTENT_OBJECT_ASSOCIATIONS_CHANGED.connect(event_receiver)
+ collection_update_event_receiver = mock.Mock()
+ LIBRARY_COLLECTION_UPDATED.connect(collection_update_event_receiver)
+
+ api.revert_changes(self.lib1.library_key)
+
+ assert collection_update_event_receiver.call_count == 1
+ assert event_receiver.call_count == 2
+ self.assertDictContainsSubset(
+ {
+ "signal": LIBRARY_COLLECTION_UPDATED,
+ "sender": None,
+ "library_collection": LibraryCollectionData(
+ self.lib1.library_key,
+ collection_key=self.col1.key,
+ background=True,
+ ),
+ },
+ collection_update_event_receiver.call_args_list[0].kwargs,
+ )
+ self.assertDictContainsSubset(
+ {
+ "signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
+ "sender": None,
+ "content_object": ContentObjectChangedData(
+ object_id=str(self.lib1_problem_block["id"]),
+ changes=["collections"],
+ ),
+ },
+ event_receiver.call_args_list[0].kwargs,
+ )
+ self.assertDictContainsSubset(
+ {
+ "signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
+ "sender": None,
+ "content_object": ContentObjectChangedData(
+ object_id=str(self.lib1_html_block["id"]),
+ changes=["collections"],
+ ),
+ },
+ event_receiver.call_args_list[1].kwargs,
+ )
+
+ def test_delete_component_and_revert(self):
+ # Add components and publish
+ api.update_library_collection_components(
+ self.lib1.library_key,
+ self.col1.key,
+ usage_keys=[
+ UsageKey.from_string(self.lib1_problem_block["id"]),
+ UsageKey.from_string(self.lib1_html_block["id"])
+ ],
+ )
+ api.publish_changes(self.lib1.library_key)
+
+ # Delete component and revert
+ api.delete_library_block(UsageKey.from_string(self.lib1_problem_block["id"]))
+
+ event_receiver = mock.Mock()
+ CONTENT_OBJECT_ASSOCIATIONS_CHANGED.connect(event_receiver)
+ collection_update_event_receiver = mock.Mock()
+ LIBRARY_COLLECTION_UPDATED.connect(collection_update_event_receiver)
+
+ api.revert_changes(self.lib1.library_key)
+
+ assert collection_update_event_receiver.call_count == 1
+ assert event_receiver.call_count == 2
+ self.assertDictContainsSubset(
+ {
+ "signal": LIBRARY_COLLECTION_UPDATED,
+ "sender": None,
+ "library_collection": LibraryCollectionData(
+ self.lib1.library_key,
+ collection_key=self.col1.key,
+ background=True,
+ ),
+ },
+ collection_update_event_receiver.call_args_list[0].kwargs,
+ )
+ self.assertDictContainsSubset(
+ {
+ "signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
+ "sender": None,
+ "content_object": ContentObjectChangedData(
+ object_id=str(self.lib1_problem_block["id"]),
+ changes=["collections"],
+ ),
+ },
+ event_receiver.call_args_list[0].kwargs,
+ )
+ self.assertDictContainsSubset(
+ {
+ "signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
+ "sender": None,
+ "content_object": ContentObjectChangedData(
+ object_id=str(self.lib1_html_block["id"]),
+ changes=["collections"],
+ ),
+ },
+ event_receiver.call_args_list[1].kwargs,
+ )
diff --git a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py
index 4fb1ecf76321..7152834d73e4 100644
--- a/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py
+++ b/openedx/core/djangoapps/content_libraries/tests/test_content_libraries.py
@@ -259,6 +259,8 @@ def test_library_blocks(self): # pylint: disable=too-many-statements
Tests with some non-ASCII chars in slugs, titles, descriptions.
"""
+ admin = UserFactory.create(username="Admin", email="admin@example.com", is_staff=True)
+
lib = self._create_library(slug="téstlꜟط", title="A Tést Lꜟطrary", description="Tésting XBlocks")
lib_id = lib["id"]
assert lib['has_unpublished_changes'] is False
@@ -531,7 +533,7 @@ def test_library_permissions(self): # pylint: disable=too-many-statements
Learning Core data models.
"""
# Create a few users to use for all of these tests:
- admin = UserFactory.create(username="Admin", email="admin@example.com")
+ admin = UserFactory.create(username="Admin", email="admin@example.com", is_staff=True)
author = UserFactory.create(username="Author", email="author@example.com")
reader = UserFactory.create(username="Reader", email="reader@example.com")
group = Group.objects.create(name="group1")
@@ -653,14 +655,15 @@ def test_library_permissions(self): # pylint: disable=too-many-statements
self._get_library_block_asset(block3_key, file_name="static/whatever.png", expect_response=403)
# Nor can they preview the block:
self._render_block_view(block3_key, view_name="student_view", expect_response=403)
- # But if we grant allow_public_read, then they can:
+ # Even if we grant allow_public_read, then they can't:
with self.as_user(admin):
self._update_library(lib_id, allow_public_read=True)
self._set_library_block_asset(block3_key, "static/whatever.png", b"data")
with self.as_user(random_user):
- self._get_library_block_olx(block3_key)
+ self._get_library_block_olx(block3_key, expect_response=403)
+ self._get_library_block_fields(block3_key, expect_response=403)
+ # But he can preview the block:
self._render_block_view(block3_key, view_name="student_view")
- f = self._get_library_block_fields(block3_key)
# self._get_library_block_assets(block3_key)
# self._get_library_block_asset(block3_key, file_name="whatever.png")
@@ -702,7 +705,7 @@ def test_no_lockout(self):
"""
Test that administrators cannot be removed if they are the only administrator granted access.
"""
- admin = UserFactory.create(username="Admin", email="admin@example.com")
+ admin = UserFactory.create(username="Admin", email="admin@example.com", is_staff=True)
successor = UserFactory.create(username="Successor", email="successor@example.com")
with self.as_user(admin):
lib = self._create_library(slug="permtest", title="Permission Test Library", description="Testing")
@@ -1026,7 +1029,7 @@ def test_library_paste_clipboard(self):
from openedx.core.djangoapps.content_staging.api import save_xblock_to_user_clipboard
# Create user to perform tests on
- author = UserFactory.create(username="Author", email="author@example.com")
+ author = UserFactory.create(username="Author", email="author@example.com", is_staff=True)
with self.as_user(author):
lib = self._create_library(
slug="test_lib_paste_clipboard",
diff --git a/openedx/core/djangoapps/content_libraries/urls.py b/openedx/core/djangoapps/content_libraries/urls.py
index 857126eef7c9..1272d79b3873 100644
--- a/openedx/core/djangoapps/content_libraries/urls.py
+++ b/openedx/core/djangoapps/content_libraries/urls.py
@@ -57,6 +57,7 @@
path('blocks/
/', include([
# Get metadata about a specific XBlock in this library, or delete the block:
path('', views.LibraryBlockView.as_view()),
+ path('restore/', views.LibraryBlockRestore.as_view()),
# Update collections for a given component
path('collections/', views.LibraryBlockCollectionsView.as_view(), name='update-collections'),
# Get the LTI URL of a specific XBlock
diff --git a/openedx/core/djangoapps/content_libraries/views.py b/openedx/core/djangoapps/content_libraries/views.py
index e30e58e75a26..94197f508775 100644
--- a/openedx/core/djangoapps/content_libraries/views.py
+++ b/openedx/core/djangoapps/content_libraries/views.py
@@ -644,6 +644,22 @@ def delete(self, request, usage_key_str): # pylint: disable=unused-argument
return Response({})
+@view_auth_classes()
+class LibraryBlockRestore(APIView):
+ """
+ View to restore soft-deleted library xblocks.
+ """
+ @convert_exceptions
+ def post(self, request, usage_key_str) -> Response:
+ """
+ Restores a soft-deleted library block that belongs to a Content Library
+ """
+ key = LibraryUsageLocatorV2.from_string(usage_key_str)
+ api.require_permission_for_library_key(key.lib_key, request.user, permissions.CAN_EDIT_THIS_CONTENT_LIBRARY)
+ api.restore_library_block(key)
+ return Response(None, status=status.HTTP_204_NO_CONTENT)
+
+
@method_decorator(non_atomic_requests, name="dispatch")
@view_auth_classes()
class LibraryBlockCollectionsView(APIView):
@@ -710,6 +726,9 @@ class LibraryBlockOlxView(APIView):
@convert_exceptions
def get(self, request, usage_key_str):
"""
+ DEPRECATED. Use get_block_olx_view() in xblock REST-API.
+ Can be removed post-Teak.
+
Get the block's OLX
"""
key = LibraryUsageLocatorV2.from_string(usage_key_str)
diff --git a/openedx/core/djangoapps/content_tagging/handlers.py b/openedx/core/djangoapps/content_tagging/handlers.py
index cc86f7e0dcd6..86cbb7167cbe 100644
--- a/openedx/core/djangoapps/content_tagging/handlers.py
+++ b/openedx/core/djangoapps/content_tagging/handlers.py
@@ -20,7 +20,6 @@
XBLOCK_DUPLICATED,
LIBRARY_BLOCK_CREATED,
LIBRARY_BLOCK_UPDATED,
- LIBRARY_BLOCK_DELETED,
)
from .api import copy_object_tags
@@ -30,7 +29,6 @@
update_course_tags,
update_xblock_tags,
update_library_block_tags,
- delete_library_block_tags,
)
from .toggles import CONTENT_TAGGING_AUTO
@@ -119,22 +117,6 @@ def auto_tag_library_block(**kwargs):
)
-@receiver(LIBRARY_BLOCK_DELETED)
-def delete_tag_library_block(**kwargs):
- """
- Delete tags associated with a Library XBlock whenever the block is deleted.
- """
- library_block_data = kwargs.get("library_block", None)
- if not library_block_data or not isinstance(library_block_data, LibraryBlockData):
- log.error("Received null or incorrect data for event")
- return
-
- try:
- delete_library_block_tags(str(library_block_data.usage_key))
- except Exception as err: # pylint: disable=broad-except
- log.error(f"Failed to delete library block tags: {err}")
-
-
@receiver(XBLOCK_DUPLICATED)
def duplicate_tags(**kwargs):
"""
diff --git a/openedx/core/djangoapps/content_tagging/rest_api/v1/tests/test_views.py b/openedx/core/djangoapps/content_tagging/rest_api/v1/tests/test_views.py
index 463ea42d08e9..5a99868ece66 100644
--- a/openedx/core/djangoapps/content_tagging/rest_api/v1/tests/test_views.py
+++ b/openedx/core/djangoapps/content_tagging/rest_api/v1/tests/test_views.py
@@ -13,6 +13,7 @@
import ddt
from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
+from edx_django_utils.cache import RequestCache
from opaque_keys.edx.locator import BlockUsageLocator, CourseLocator, LibraryCollectionLocator
from openedx_tagging.core.tagging.models import Tag, Taxonomy
from openedx_tagging.core.tagging.models.system_defined import SystemDefinedTaxonomy
@@ -34,7 +35,6 @@
from openedx.core.djangoapps.content_libraries.api import AccessLevel, create_library, set_library_user_permissions
from openedx.core.djangoapps.content_tagging import api as tagging_api
from openedx.core.djangoapps.content_tagging.models import TaxonomyOrg
-from openedx.core.djangoapps.content_tagging.utils import rules_cache
from openedx.core.djangolib.testing.utils import skip_unless_cms
from ....tests.test_objecttag_export_helpers import TaggedCourseMixin
@@ -289,8 +289,8 @@ def setUp(self):
self._setUp_taxonomies()
self._setUp_collection()
- # Clear the rules cache in between test runs to keep query counts consistent.
- rules_cache.clear()
+ # Clear all request caches in between test runs to keep query counts consistent.
+ RequestCache.clear_all_namespaces()
@skip_unless_cms
@@ -510,12 +510,12 @@ def test_create_taxonomy(self, user_attr: str, expected_status: int) -> None:
@ddt.data(
('staff', 11),
- ("content_creatorA", 16),
- ("library_staffA", 16),
- ("library_userA", 16),
- ("instructorA", 16),
- ("course_instructorA", 16),
- ("course_staffA", 16),
+ ("content_creatorA", 17),
+ ("library_staffA", 17),
+ ("library_userA", 17),
+ ("instructorA", 17),
+ ("course_instructorA", 17),
+ ("course_staffA", 17),
)
@ddt.unpack
def test_list_taxonomy_query_count(self, user_attr: str, expected_queries: int):
@@ -1879,16 +1879,16 @@ def test_get_copied_tags(self):
('staff', 'courseA', 8),
('staff', 'libraryA', 8),
('staff', 'collection_key', 8),
- ("content_creatorA", 'courseA', 11, False),
- ("content_creatorA", 'libraryA', 11, False),
- ("content_creatorA", 'collection_key', 11, False),
- ("library_staffA", 'libraryA', 11, False), # Library users can only view objecttags, not change them?
- ("library_staffA", 'collection_key', 11, False),
- ("library_userA", 'libraryA', 11, False),
- ("library_userA", 'collection_key', 11, False),
- ("instructorA", 'courseA', 11),
- ("course_instructorA", 'courseA', 11),
- ("course_staffA", 'courseA', 11),
+ ("content_creatorA", 'courseA', 12, False),
+ ("content_creatorA", 'libraryA', 12, False),
+ ("content_creatorA", 'collection_key', 12, False),
+ ("library_staffA", 'libraryA', 12, False), # Library users can only view objecttags, not change them?
+ ("library_staffA", 'collection_key', 12, False),
+ ("library_userA", 'libraryA', 12, False),
+ ("library_userA", 'collection_key', 12, False),
+ ("instructorA", 'courseA', 12),
+ ("course_instructorA", 'courseA', 12),
+ ("course_staffA", 'courseA', 12),
)
@ddt.unpack
def test_object_tags_query_count(
diff --git a/openedx/core/djangoapps/content_tagging/tests/test_tasks.py b/openedx/core/djangoapps/content_tagging/tests/test_tasks.py
index c14adfcce13a..d0e10ecfb7ae 100644
--- a/openedx/core/djangoapps/content_tagging/tests/test_tasks.py
+++ b/openedx/core/djangoapps/content_tagging/tests/test_tasks.py
@@ -14,7 +14,9 @@
from common.djangoapps.student.tests.factories import UserFactory
from openedx.core.djangolib.testing.utils import skip_unless_cms
from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, ModuleStoreTestCase
-from openedx.core.djangoapps.content_libraries.api import create_library, create_library_block, delete_library_block
+from openedx.core.djangoapps.content_libraries.api import (
+ create_library, create_library_block, delete_library_block, restore_library_block
+)
from .. import api
from ..models.base import TaxonomyOrg
@@ -267,7 +269,7 @@ def test_waffle_disabled_create_delete_xblock(self):
# Still no tags
assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, None)
- def test_create_delete_library_block(self):
+ def test_create_delete_restore_library_block(self):
# Create library
library = create_library(
org=self.orgA,
@@ -287,11 +289,17 @@ def test_create_delete_library_block(self):
# Check if the tags are created in the Library Block with the user's preferred language
assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, 'Português (Brasil)')
- # Delete the XBlock
+ # Soft delete the XBlock
delete_library_block(library_block.usage_key)
- # Check if the tags are deleted
- assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, None)
+ # Check that the tags are not deleted
+ assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, 'Português (Brasil)')
+
+ # Restore the XBlock
+ restore_library_block(library_block.usage_key)
+
+ # Check if the tags are still present in the Library Block with the user's preferred language
+ assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, 'Português (Brasil)')
@override_waffle_flag(CONTENT_TAGGING_AUTO, active=False)
def test_waffle_disabled_create_delete_library_block(self):
@@ -319,3 +327,10 @@ def test_waffle_disabled_create_delete_library_block(self):
# Still no tags
assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, None)
+
+ # Restore the XBlock
+ with patch('crum.get_current_request', return_value=fake_request):
+ restore_library_block(library_block.usage_key)
+
+ # Still no tags
+ assert self._check_tag(usage_key_str, LANGUAGE_TAXONOMY_ID, None)
diff --git a/openedx/core/djangoapps/discussions/config/waffle.py b/openedx/core/djangoapps/discussions/config/waffle.py
index 1d4c67e9e17b..eca6fc970856 100644
--- a/openedx/core/djangoapps/discussions/config/waffle.py
+++ b/openedx/core/djangoapps/discussions/config/waffle.py
@@ -2,6 +2,8 @@
This module contains various configuration settings via
waffle switches for the discussions app.
"""
+from django.conf import settings
+
from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag
WAFFLE_FLAG_NAMESPACE = "discussions"
@@ -43,3 +45,31 @@
ENABLE_NEW_STRUCTURE_DISCUSSIONS = CourseWaffleFlag(
f"{WAFFLE_FLAG_NAMESPACE}.enable_new_structure_discussions", __name__
)
+
+# .. toggle_name: discussions.enable_forum_v2
+# .. toggle_implementation: CourseWaffleFlag
+# .. toggle_default: False
+# .. toggle_description: Waffle flag to use the forum v2 instead of v1(cs_comment_service)
+# .. toggle_use_cases: temporary, open_edx
+# .. toggle_creation_date: 2024-9-26
+# .. toggle_target_removal_date: 2025-12-05
+ENABLE_FORUM_V2 = CourseWaffleFlag(f"{WAFFLE_FLAG_NAMESPACE}.enable_forum_v2", __name__)
+
+
+def is_forum_v2_enabled(course_key):
+ """
+ Returns whether forum V2 is enabled on the course. This is a 2-step check:
+
+ 1. Check value of settings.DISABLE_FORUM_V2: if it exists and is true, this setting overrides any course flag.
+ 2. Else, check the value of the corresponding course waffle flag.
+ """
+ if is_forum_v2_disabled_globally():
+ return False
+ return ENABLE_FORUM_V2.is_enabled(course_key)
+
+
+def is_forum_v2_disabled_globally() -> bool:
+ """
+ Return True if DISABLE_FORUM_V2 is defined and true-ish.
+ """
+ return getattr(settings, "DISABLE_FORUM_V2", False)
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/comment.py b/openedx/core/djangoapps/django_comment_common/comment_client/comment.py
index c86f7eb40515..ba95c620496d 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/comment.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/comment.py
@@ -4,7 +4,9 @@
from openedx.core.djangoapps.django_comment_common.comment_client import models, settings
from .thread import Thread, _url_for_flag_abuse_thread, _url_for_unflag_abuse_thread
-from .utils import CommentClientRequestError, perform_request
+from .utils import CommentClientRequestError, get_course_key, perform_request
+from forum import api as forum_api
+from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
class Comment(models.Model):
@@ -68,14 +70,21 @@ def flagAbuse(self, user, voteable):
url = _url_for_flag_abuse_comment(voteable.id)
else:
raise CommentClientRequestError("Can only flag/unflag threads or comments")
- params = {'user_id': user.id}
- response = perform_request(
- 'put',
- url,
- params,
- metric_tags=self._metric_tags,
- metric_action='comment.abuse.flagged'
- )
+ course_key = get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ if voteable.type == 'thread':
+ response = forum_api.update_thread_flag(voteable.id, "flag", user.id, str(course_key))
+ else:
+ response = forum_api.update_comment_flag(voteable.id, "flag", user.id, str(course_key))
+ else:
+ params = {'user_id': user.id}
+ response = perform_request(
+ 'put',
+ url,
+ params,
+ metric_tags=self._metric_tags,
+ metric_action='comment.abuse.flagged'
+ )
voteable._update_from_response(response)
def unFlagAbuse(self, user, voteable, removeAll):
@@ -85,18 +94,37 @@ def unFlagAbuse(self, user, voteable, removeAll):
url = _url_for_unflag_abuse_comment(voteable.id)
else:
raise CommentClientRequestError("Can flag/unflag for threads or comments")
- params = {'user_id': user.id}
-
- if removeAll:
- params['all'] = True
-
- response = perform_request(
- 'put',
- url,
- params,
- metric_tags=self._metric_tags,
- metric_action='comment.abuse.unflagged'
- )
+ course_key = get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ if voteable.type == "thread":
+ response = forum_api.update_thread_flag(
+ thread_id=voteable.id,
+ action="unflag",
+ user_id=user.id,
+ update_all=bool(removeAll),
+ course_id=str(course_key)
+ )
+ else:
+ response = forum_api.update_comment_flag(
+ comment_id=voteable.id,
+ action="unflag",
+ user_id=user.id,
+ update_all=bool(removeAll),
+ course_id=str(course_key)
+ )
+ else:
+ params = {'user_id': user.id}
+
+ if removeAll:
+ params['all'] = True
+
+ response = perform_request(
+ 'put',
+ url,
+ params,
+ metric_tags=self._metric_tags,
+ metric_action='comment.abuse.unflagged'
+ )
voteable._update_from_response(response)
@property
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/course.py b/openedx/core/djangoapps/django_comment_common/comment_client/course.py
index 67d7efd22838..8cbb580e7831 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/course.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/course.py
@@ -7,8 +7,10 @@
from edx_django_utils.monitoring import function_trace
from opaque_keys.edx.keys import CourseKey
+from forum import api as forum_api
from openedx.core.djangoapps.django_comment_common.comment_client import settings
from openedx.core.djangoapps.django_comment_common.comment_client.utils import perform_request
+from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
def get_course_commentable_counts(course_key: CourseKey) -> Dict[str, Dict[str, int]]:
@@ -29,17 +31,20 @@ def get_course_commentable_counts(course_key: CourseKey) -> Dict[str, Dict[str,
}
"""
- url = f"{settings.PREFIX}/commentables/{course_key}/counts"
- response = perform_request(
- 'get',
- url,
- metric_tags=[
- f"course_key:{course_key}",
- "function:get_course_commentable_counts",
- ],
- metric_action='commentable_stats.retrieve',
- )
- return response
+ if is_forum_v2_enabled(course_key):
+ commentable_stats = forum_api.get_commentables_stats(str(course_key))
+ else:
+ url = f"{settings.PREFIX}/commentables/{course_key}/counts"
+ commentable_stats = perform_request(
+ 'get',
+ url,
+ metric_tags=[
+ f"course_key:{course_key}",
+ "function:get_course_commentable_counts",
+ ],
+ metric_action='commentable_stats.retrieve',
+ )
+ return commentable_stats
@function_trace("get_course_user_stats")
@@ -76,17 +81,21 @@ def get_course_user_stats(course_key: CourseKey, params: Optional[Dict] = None)
"""
if params is None:
params = {}
- url = f"{settings.PREFIX}/users/{course_key}/stats"
- return perform_request(
- 'get',
- url,
- params,
- metric_action='user.course_stats',
- metric_tags=[
- f"course_key:{course_key}",
- "function:get_course_user_stats",
- ],
- )
+ if is_forum_v2_enabled(course_key):
+ course_stats = forum_api.get_user_course_stats(str(course_key), **params)
+ else:
+ url = f"{settings.PREFIX}/users/{course_key}/stats"
+ course_stats = perform_request(
+ 'get',
+ url,
+ params,
+ metric_action='user.course_stats',
+ metric_tags=[
+ f"course_key:{course_key}",
+ "function:get_course_user_stats",
+ ],
+ )
+ return course_stats
@function_trace("update_course_users_stats")
@@ -100,13 +109,17 @@ def update_course_users_stats(course_key: CourseKey) -> Dict:
Returns:
dict: data returned by API. Contains count of users updated.
"""
- url = f"{settings.PREFIX}/users/{course_key}/update_stats"
- return perform_request(
- 'post',
- url,
- metric_action='user.update_course_stats',
- metric_tags=[
- f"course_key:{course_key}",
- "function:update_course_users_stats",
- ],
- )
+ if is_forum_v2_enabled(course_key):
+ course_stats = forum_api.update_users_in_course(str(course_key))
+ else:
+ url = f"{settings.PREFIX}/users/{course_key}/update_stats"
+ course_stats = perform_request(
+ 'post',
+ url,
+ metric_action='user.update_course_stats',
+ metric_tags=[
+ f"course_key:{course_key}",
+ "function:update_course_users_stats",
+ ],
+ )
+ return course_stats
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/models.py b/openedx/core/djangoapps/django_comment_common/comment_client/models.py
index 4e602809c82a..9b6c9ca03f3d 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/models.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/models.py
@@ -2,8 +2,11 @@
import logging
+import typing as t
-from .utils import CommentClientRequestError, extract, perform_request
+from .utils import CommentClientRequestError, extract, perform_request, get_course_key
+from forum import api as forum_api
+from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled, is_forum_v2_disabled_globally
log = logging.getLogger(__name__)
@@ -69,14 +72,27 @@ def retrieve(self, *args, **kwargs):
return self
def _retrieve(self, *args, **kwargs):
- url = self.url(action='get', params=self.attributes)
- response = perform_request(
- 'get',
- url,
- self.default_retrieve_params,
- metric_tags=self._metric_tags,
- metric_action='model.retrieve'
- )
+ course_id = self.attributes.get("course_id") or kwargs.get("course_id")
+ if course_id:
+ course_key = get_course_key(course_id)
+ use_forumv2 = is_forum_v2_enabled(course_key)
+ else:
+ use_forumv2, course_id = is_forum_v2_enabled_for_comment(self.id)
+ response = None
+ if use_forumv2:
+ if self.type == "comment":
+ response = forum_api.get_parent_comment(comment_id=self.attributes["id"], course_id=course_id)
+ if response is None:
+ raise CommentClientRequestError("Forum v2 API call is missing")
+ else:
+ url = self.url(action='get', params=self.attributes)
+ response = perform_request(
+ 'get',
+ url,
+ self.default_retrieve_params,
+ metric_tags=self._metric_tags,
+ metric_action='model.retrieve'
+ )
self._update_from_response(response)
@property
@@ -151,33 +167,27 @@ def save(self, params=None):
"""
self.before_save(self)
if self.id: # if we have id already, treat this as an update
- request_params = self.updatable_attributes()
- if params:
- request_params.update(params)
- url = self.url(action='put', params=self.attributes)
- response = perform_request(
- 'put',
- url,
- request_params,
- metric_tags=self._metric_tags,
- metric_action='model.update'
- )
- else: # otherwise, treat this as an insert
- url = self.url(action='post', params=self.attributes)
- response = perform_request(
- 'post',
- url,
- self.initializable_attributes(),
- metric_tags=self._metric_tags,
- metric_action='model.insert'
- )
+ response = self.handle_update(params)
+ else: # otherwise, treat this as an insert
+ response = self.handle_create(params)
+
self.retrieved = True
self._update_from_response(response)
self.after_save(self)
def delete(self):
- url = self.url(action='delete', params=self.attributes)
- response = perform_request('delete', url, metric_tags=self._metric_tags, metric_action='model.delete')
+ course_key = get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ response = None
+ if self.type == "comment":
+ response = forum_api.delete_comment(comment_id=self.attributes["id"], course_id=str(course_key))
+ elif self.type == "thread":
+ response = forum_api.delete_thread(thread_id=self.attributes["id"], course_id=str(course_key))
+ if response is None:
+ raise CommentClientRequestError("Forum v2 API call is missing")
+ else:
+ url = self.url(action='delete', params=self.attributes)
+ response = perform_request('delete', url, metric_tags=self._metric_tags, metric_action='model.delete')
self.retrieved = True
self._update_from_response(response)
@@ -208,3 +218,176 @@ def url(cls, action, params=None):
raise CommentClientRequestError(f"Cannot perform action {action} without id") # lint-amnesty, pylint: disable=raise-missing-from
else: # action must be in DEFAULT_ACTIONS_WITHOUT_ID now
return cls.url_without_id()
+
+ def handle_update(self, params=None):
+ request_params = self.updatable_attributes()
+ if params:
+ request_params.update(params)
+ course_id = self.attributes.get("course_id") or request_params.get("course_id")
+ course_key = get_course_key(course_id)
+ if is_forum_v2_enabled(course_key):
+ response = None
+ if self.type == "comment":
+ response = self.handle_update_comment(request_params, str(course_key))
+ elif self.type == "thread":
+ response = self.handle_update_thread(request_params, str(course_key))
+ elif self.type == "user":
+ response = self.handle_update_user(request_params, str(course_key))
+ if response is None:
+ raise CommentClientRequestError("Forum v2 API call is missing")
+ else:
+ response = self.perform_http_put_request(request_params)
+ return response
+
+ def handle_update_user(self, request_params, course_id):
+ try:
+ username = request_params["username"]
+ external_id = str(request_params["external_id"])
+ except KeyError as e:
+ raise e
+ response = forum_api.update_user(
+ external_id,
+ username=username,
+ course_id=course_id,
+ )
+ return response
+
+ def handle_update_comment(self, request_params, course_id):
+ request_data = {
+ "comment_id": self.attributes["id"],
+ "body": request_params.get("body"),
+ "course_id": request_params.get("course_id"),
+ "user_id": request_params.get("user_id"),
+ "anonymous": request_params.get("anonymous"),
+ "anonymous_to_peers": request_params.get("anonymous_to_peers"),
+ "endorsed": request_params.get("endorsed"),
+ "closed": request_params.get("closed"),
+ "editing_user_id": request_params.get("editing_user_id"),
+ "edit_reason_code": request_params.get("edit_reason_code"),
+ "endorsement_user_id": request_params.get("endorsement_user_id"),
+ "course_key": course_id
+ }
+ request_data = {k: v for k, v in request_data.items() if v is not None}
+ response = forum_api.update_comment(**request_data)
+ return response
+
+ def handle_update_thread(self, request_params, course_id):
+ request_data = {
+ "thread_id": self.attributes["id"],
+ "title": request_params.get("title"),
+ "body": request_params.get("body"),
+ "course_id": request_params.get("course_id"),
+ "anonymous": request_params.get("anonymous"),
+ "anonymous_to_peers": request_params.get("anonymous_to_peers"),
+ "closed": request_params.get("closed"),
+ "commentable_id": request_params.get("commentable_id"),
+ "user_id": request_params.get("user_id"),
+ "editing_user_id": request_params.get("editing_user_id"),
+ "pinned": request_params.get("pinned"),
+ "thread_type": request_params.get("thread_type"),
+ "edit_reason_code": request_params.get("edit_reason_code"),
+ "close_reason_code": request_params.get("close_reason_code"),
+ "closing_user_id": request_params.get("closing_user_id"),
+ "endorsed": request_params.get("endorsed"),
+ "course_key": course_id
+ }
+ request_data = {k: v for k, v in request_data.items() if v is not None}
+ response = forum_api.update_thread(**request_data)
+ return response
+
+ def perform_http_put_request(self, request_params):
+ url = self.url(action="put", params=self.attributes)
+ response = perform_request(
+ "put",
+ url,
+ request_params,
+ metric_tags=self._metric_tags,
+ metric_action="model.update",
+ )
+ return response
+
+ def perform_http_post_request(self):
+ url = self.url(action="post", params=self.attributes)
+ response = perform_request(
+ "post",
+ url,
+ self.initializable_attributes(),
+ metric_tags=self._metric_tags,
+ metric_action="model.insert",
+ )
+ return response
+
+ def handle_create(self, params=None):
+ course_id = self.attributes.get("course_id") or params.get("course_id")
+ course_key = get_course_key(course_id)
+ if is_forum_v2_enabled(course_key):
+ response = None
+ if self.type == "comment":
+ response = self.handle_create_comment(str(course_key))
+ elif self.type == "thread":
+ response = self.handle_create_thread(str(course_key))
+ if response is None:
+ raise CommentClientRequestError("Forum v2 API call is missing")
+ else:
+ response = self.perform_http_post_request()
+ return response
+
+ def handle_create_comment(self, course_id):
+ request_data = self.initializable_attributes()
+ body = request_data["body"]
+ user_id = request_data["user_id"]
+ course_id = course_id or str(request_data["course_id"])
+ if parent_id := self.attributes.get("parent_id"):
+ response = forum_api.create_child_comment(
+ parent_id,
+ body,
+ user_id,
+ course_id,
+ request_data.get("anonymous", False),
+ request_data.get("anonymous_to_peers", False),
+ )
+ else:
+ response = forum_api.create_parent_comment(
+ self.attributes["thread_id"],
+ body,
+ user_id,
+ course_id,
+ request_data.get("anonymous", False),
+ request_data.get("anonymous_to_peers", False),
+ )
+ return response
+
+ def handle_create_thread(self, course_id):
+ request_data = self.initializable_attributes()
+ response = forum_api.create_thread(
+ title=request_data["title"],
+ body=request_data["body"],
+ course_id=course_id or str(request_data["course_id"]),
+ user_id=str(request_data["user_id"]),
+ anonymous=request_data.get("anonymous", False),
+ anonymous_to_peers=request_data.get("anonymous_to_peers", False),
+ commentable_id=request_data.get("commentable_id", "course"),
+ thread_type=request_data.get("thread_type", "discussion"),
+ group_id=request_data.get("group_id", None),
+ context=request_data.get("context", None),
+ )
+ return response
+
+
+def is_forum_v2_enabled_for_comment(comment_id: str) -> tuple[bool, t.Optional[str]]:
+ """
+ Figure out whether we use forum v2 for a given comment.
+
+ See is_forum_v2_enabled_for_thread.
+
+ Return:
+
+ enabled (bool)
+ course_id (str or None)
+ """
+ if is_forum_v2_disabled_globally():
+ return False, None
+
+ course_id = forum_api.get_course_id_by_comment(comment_id)
+ course_key = get_course_key(course_id)
+ return is_forum_v2_enabled(course_key), course_id
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/subscriptions.py b/openedx/core/djangoapps/django_comment_common/comment_client/subscriptions.py
index 545948a092cc..2130dfc56be6 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/subscriptions.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/subscriptions.py
@@ -4,6 +4,8 @@
import logging
from . import models, settings, utils
+from forum import api as forum_api
+from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
log = logging.getLogger(__name__)
@@ -21,7 +23,7 @@ class Subscription(models.Model):
base_url = f"{settings.PREFIX}/threads"
@classmethod
- def fetch(cls, thread_id, query_params):
+ def fetch(cls, thread_id, course_id, query_params):
"""
Fetches the subscriptions for a given thread_id
"""
@@ -33,14 +35,23 @@ def fetch(cls, thread_id, query_params):
params.update(
utils.strip_blank(utils.strip_none(query_params))
)
- response = utils.perform_request(
- 'get',
- cls.url(action='get', params=params) + "/subscriptions",
- params,
- metric_tags=[],
- metric_action='subscription.get',
- paged_results=True
- )
+ course_key = utils.get_course_key(course_id)
+ if is_forum_v2_enabled(course_key):
+ response = forum_api.get_thread_subscriptions(
+ thread_id=thread_id,
+ page=params["page"],
+ per_page=params["per_page"],
+ course_id=str(course_key)
+ )
+ else:
+ response = utils.perform_request(
+ 'get',
+ cls.url(action='get', params=params) + "/subscriptions",
+ params,
+ metric_tags=[],
+ metric_action='subscription.get',
+ paged_results=True
+ )
return utils.SubscriptionsPaginatedResult(
collection=response.get('collection', []),
page=response.get('page', 1),
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/thread.py b/openedx/core/djangoapps/django_comment_common/comment_client/thread.py
index ef5accbad25d..ecf420cfae56 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/thread.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/thread.py
@@ -2,10 +2,13 @@
import logging
+import typing as t
from eventtracking import tracker
from . import models, settings, utils
+from forum import api as forum_api
+from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled, is_forum_v2_disabled_globally
log = logging.getLogger(__name__)
@@ -59,14 +62,35 @@ def search(cls, query_params):
url = cls.url(action='get_all', params=utils.extract(params, 'commentable_id'))
if params.get('commentable_id'):
del params['commentable_id']
- response = utils.perform_request(
- 'get',
- url,
- params,
- metric_tags=['course_id:{}'.format(query_params['course_id'])],
- metric_action='thread.search',
- paged_results=True
- )
+
+ if is_forum_v2_enabled(utils.get_course_key(query_params['course_id'])):
+ if query_params.get('text'):
+ search_params = utils.strip_none(params)
+ if user_id := search_params.get('user_id'):
+ search_params['user_id'] = str(user_id)
+ if group_ids := search_params.get('group_ids'):
+ search_params['group_ids'] = [int(group_id) for group_id in group_ids.split(',')]
+ elif group_id := search_params.get('group_id'):
+ search_params['group_ids'] = [int(group_id)]
+ search_params.pop('group_id', None)
+ if commentable_ids := search_params.get('commentable_ids'):
+ search_params['commentable_ids'] = commentable_ids.split(',')
+ elif commentable_id := search_params.get('commentable_id'):
+ search_params['commentable_ids'] = [commentable_id]
+ search_params.pop('commentable_id', None)
+ response = forum_api.search_threads(**search_params)
+ else:
+ response = forum_api.get_user_threads(**params)
+ else:
+ response = utils.perform_request(
+ 'get',
+ url,
+ params,
+ metric_tags=['course_id:{}'.format(query_params['course_id'])],
+ metric_action='thread.search',
+ paged_results=True
+ )
+
if query_params.get('text'):
search_query = query_params['text']
course_id = query_params['course_id']
@@ -148,14 +172,28 @@ def _retrieve(self, *args, **kwargs):
'merge_question_type_responses': kwargs.get('merge_question_type_responses', False)
}
request_params = utils.strip_none(request_params)
-
- response = utils.perform_request(
- 'get',
- url,
- request_params,
- metric_action='model.retrieve',
- metric_tags=self._metric_tags
- )
+ course_id = kwargs.get("course_id")
+ if course_id:
+ course_key = utils.get_course_key(course_id)
+ use_forumv2 = is_forum_v2_enabled(course_key)
+ else:
+ use_forumv2, course_id = is_forum_v2_enabled_for_thread(self.id)
+ if use_forumv2:
+ if user_id := request_params.get('user_id'):
+ request_params['user_id'] = str(user_id)
+ response = forum_api.get_thread(
+ thread_id=self.id,
+ params=request_params,
+ course_id=course_id,
+ )
+ else:
+ response = utils.perform_request(
+ 'get',
+ url,
+ request_params,
+ metric_action='model.retrieve',
+ metric_tags=self._metric_tags
+ )
self._update_from_response(response)
def flagAbuse(self, user, voteable):
@@ -163,14 +201,18 @@ def flagAbuse(self, user, voteable):
url = _url_for_flag_abuse_thread(voteable.id)
else:
raise utils.CommentClientRequestError("Can only flag/unflag threads or comments")
- params = {'user_id': user.id}
- response = utils.perform_request(
- 'put',
- url,
- params,
- metric_action='thread.abuse.flagged',
- metric_tags=self._metric_tags
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ response = forum_api.update_thread_flag(voteable.id, "flag", user.id, str(course_key))
+ else:
+ params = {'user_id': user.id}
+ response = utils.perform_request(
+ 'put',
+ url,
+ params,
+ metric_action='thread.abuse.flagged',
+ metric_tags=self._metric_tags
+ )
voteable._update_from_response(response)
def unFlagAbuse(self, user, voteable, removeAll):
@@ -178,42 +220,68 @@ def unFlagAbuse(self, user, voteable, removeAll):
url = _url_for_unflag_abuse_thread(voteable.id)
else:
raise utils.CommentClientRequestError("Can only flag/unflag for threads or comments")
- params = {'user_id': user.id}
- #if you're an admin, when you unflag, remove ALL flags
- if removeAll:
- params['all'] = True
-
- response = utils.perform_request(
- 'put',
- url,
- params,
- metric_tags=self._metric_tags,
- metric_action='thread.abuse.unflagged'
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ response = forum_api.update_thread_flag(
+ thread_id=voteable.id,
+ action="unflag",
+ user_id=user.id,
+ update_all=bool(removeAll),
+ course_id=str(course_key)
+ )
+ else:
+ params = {'user_id': user.id}
+ #if you're an admin, when you unflag, remove ALL flags
+ if removeAll:
+ params['all'] = True
+
+ response = utils.perform_request(
+ 'put',
+ url,
+ params,
+ metric_tags=self._metric_tags,
+ metric_action='thread.abuse.unflagged'
+ )
voteable._update_from_response(response)
def pin(self, user, thread_id):
- url = _url_for_pin_thread(thread_id)
- params = {'user_id': user.id}
- response = utils.perform_request(
- 'put',
- url,
- params,
- metric_tags=self._metric_tags,
- metric_action='thread.pin'
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ response = forum_api.pin_thread(
+ user_id=user.id,
+ thread_id=thread_id,
+ course_id=str(course_key)
+ )
+ else:
+ url = _url_for_pin_thread(thread_id)
+ params = {'user_id': user.id}
+ response = utils.perform_request(
+ 'put',
+ url,
+ params,
+ metric_tags=self._metric_tags,
+ metric_action='thread.pin'
+ )
self._update_from_response(response)
def un_pin(self, user, thread_id):
- url = _url_for_un_pin_thread(thread_id)
- params = {'user_id': user.id}
- response = utils.perform_request(
- 'put',
- url,
- params,
- metric_tags=self._metric_tags,
- metric_action='thread.unpin'
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ response = forum_api.unpin_thread(
+ user_id=user.id,
+ thread_id=thread_id,
+ course_id=str(course_key)
+ )
+ else:
+ url = _url_for_un_pin_thread(thread_id)
+ params = {'user_id': user.id}
+ response = utils.perform_request(
+ 'put',
+ url,
+ params,
+ metric_tags=self._metric_tags,
+ metric_action='thread.unpin'
+ )
self._update_from_response(response)
@@ -231,3 +299,28 @@ def _url_for_pin_thread(thread_id):
def _url_for_un_pin_thread(thread_id):
return f"{settings.PREFIX}/threads/{thread_id}/unpin"
+
+
+def is_forum_v2_enabled_for_thread(thread_id: str) -> tuple[bool, t.Optional[str]]:
+ """
+ Figure out whether we use forum v2 for a given thread.
+
+ This is a complex affair... First, we check the value of the DISABLE_FORUM_V2
+ setting, which overrides everything. If this setting does not exist, then we need to
+ find the course ID that corresponds to the thread ID. Then, we return the value of
+ the course waffle flag for this course ID.
+
+ Note that to fetch the course ID associated to a thread ID, we need to connect both
+ to mongodb and mysql. As a consequence, when forum v2 needs adequate connection
+ strings for both backends.
+
+ Return:
+
+ enabled (bool)
+ course_id (str or None)
+ """
+ if is_forum_v2_disabled_globally():
+ return False, None
+ course_id = forum_api.get_course_id_by_thread(thread_id)
+ course_key = utils.get_course_key(course_id)
+ return is_forum_v2_enabled(course_key), course_id
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/user.py b/openedx/core/djangoapps/django_comment_common/comment_client/user.py
index 684469c9e787..2de4fbbfa95a 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/user.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/user.py
@@ -1,8 +1,10 @@
# pylint: disable=missing-docstring,protected-access
""" User model wrapper for comment service"""
-
from . import models, settings, utils
+from forum import api as forum_api
+from forum.utils import ForumV2RequestError, str_to_bool
+from openedx.core.djangoapps.discussions.config.waffle import is_forum_v2_enabled
class User(models.Model):
@@ -34,34 +36,55 @@ def read(self, source):
"""
Calls cs_comments_service to mark thread as read for the user
"""
- params = {'source_type': source.type, 'source_id': source.id}
- utils.perform_request(
- 'post',
- _url_for_read(self.id),
- params,
- metric_action='user.read',
- metric_tags=self._metric_tags + [f'target.type:{source.type}'],
- )
+ course_id = self.attributes.get("course_id")
+ course_key = utils.get_course_key(course_id)
+ if is_forum_v2_enabled(course_key):
+ forum_api.mark_thread_as_read(self.id, source.id, course_id=str(course_id))
+ else:
+ params = {'source_type': source.type, 'source_id': source.id}
+ utils.perform_request(
+ 'post',
+ _url_for_read(self.id),
+ params,
+ metric_action='user.read',
+ metric_tags=self._metric_tags + [f'target.type:{source.type}'],
+ )
def follow(self, source):
- params = {'source_type': source.type, 'source_id': source.id}
- utils.perform_request(
- 'post',
- _url_for_subscription(self.id),
- params,
- metric_action='user.follow',
- metric_tags=self._metric_tags + [f'target.type:{source.type}'],
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ forum_api.create_subscription(
+ user_id=self.id,
+ source_id=source.id,
+ course_id=str(course_key)
+ )
+ else:
+ params = {'source_type': source.type, 'source_id': source.id}
+ utils.perform_request(
+ 'post',
+ _url_for_subscription(self.id),
+ params,
+ metric_action='user.follow',
+ metric_tags=self._metric_tags + [f'target.type:{source.type}'],
+ )
def unfollow(self, source):
- params = {'source_type': source.type, 'source_id': source.id}
- utils.perform_request(
- 'delete',
- _url_for_subscription(self.id),
- params,
- metric_action='user.unfollow',
- metric_tags=self._metric_tags + [f'target.type:{source.type}'],
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ forum_api.delete_subscription(
+ user_id=self.id,
+ source_id=source.id,
+ course_id=str(course_key)
+ )
+ else:
+ params = {'source_type': source.type, 'source_id': source.id}
+ utils.perform_request(
+ 'delete',
+ _url_for_subscription(self.id),
+ params,
+ metric_action='user.unfollow',
+ metric_tags=self._metric_tags + [f'target.type:{source.type}'],
+ )
def vote(self, voteable, value):
if voteable.type == 'thread':
@@ -70,14 +93,31 @@ def vote(self, voteable, value):
url = _url_for_vote_comment(voteable.id)
else:
raise utils.CommentClientRequestError("Can only vote / unvote for threads or comments")
- params = {'user_id': self.id, 'value': value}
- response = utils.perform_request(
- 'put',
- url,
- params,
- metric_action='user.vote',
- metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ if voteable.type == 'thread':
+ response = forum_api.update_thread_votes(
+ thread_id=voteable.id,
+ user_id=self.id,
+ value=value,
+ course_id=str(course_key)
+ )
+ else:
+ response = forum_api.update_comment_votes(
+ comment_id=voteable.id,
+ user_id=self.id,
+ value=value,
+ course_id=str(course_key)
+ )
+ else:
+ params = {'user_id': self.id, 'value': value}
+ response = utils.perform_request(
+ 'put',
+ url,
+ params,
+ metric_action='user.vote',
+ metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
+ )
voteable._update_from_response(response)
def unvote(self, voteable):
@@ -87,14 +127,29 @@ def unvote(self, voteable):
url = _url_for_vote_comment(voteable.id)
else:
raise utils.CommentClientRequestError("Can only vote / unvote for threads or comments")
- params = {'user_id': self.id}
- response = utils.perform_request(
- 'delete',
- url,
- params,
- metric_action='user.unvote',
- metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ if voteable.type == 'thread':
+ response = forum_api.delete_thread_vote(
+ thread_id=voteable.id,
+ user_id=self.id,
+ course_id=str(course_key)
+ )
+ else:
+ response = forum_api.delete_comment_vote(
+ comment_id=voteable.id,
+ user_id=self.id,
+ course_id=str(course_key)
+ )
+ else:
+ params = {'user_id': self.id}
+ response = utils.perform_request(
+ 'delete',
+ url,
+ params,
+ metric_action='user.unvote',
+ metric_tags=self._metric_tags + [f'target.type:{voteable.type}'],
+ )
voteable._update_from_response(response)
def active_threads(self, query_params=None):
@@ -105,14 +160,28 @@ def active_threads(self, query_params=None):
url = _url_for_user_active_threads(self.id)
params = {'course_id': str(self.course_id)}
params.update(query_params)
- response = utils.perform_request(
- 'get',
- url,
- params,
- metric_action='user.active_threads',
- metric_tags=self._metric_tags,
- paged_results=True,
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ if user_id := params.get("user_id"):
+ params["user_id"] = str(user_id)
+ if page := params.get("page"):
+ params["page"] = int(page)
+ if per_page := params.get("per_page"):
+ params["per_page"] = int(per_page)
+ if count_flagged := params.get("count_flagged", False):
+ params["count_flagged"] = str_to_bool(count_flagged)
+ if not params.get("course_id"):
+ params["course_id"] = str(course_key)
+ response = forum_api.get_user_active_threads(**params)
+ else:
+ response = utils.perform_request(
+ 'get',
+ url,
+ params,
+ metric_action='user.active_threads',
+ metric_tags=self._metric_tags,
+ paged_results=True,
+ )
return response.get('collection', []), response.get('page', 1), response.get('num_pages', 1)
def subscribed_threads(self, query_params=None):
@@ -125,14 +194,28 @@ def subscribed_threads(self, query_params=None):
url = _url_for_user_subscribed_threads(self.id)
params = {'course_id': str(self.course_id)}
params.update(query_params)
- response = utils.perform_request(
- 'get',
- url,
- params,
- metric_action='user.subscribed_threads',
- metric_tags=self._metric_tags,
- paged_results=True
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ if user_id := params.get("user_id"):
+ params["user_id"] = str(user_id)
+ if page := params.get("page"):
+ params["page"] = int(page)
+ if per_page := params.get("per_page"):
+ params["per_page"] = int(per_page)
+ if count_flagged := params.get("count_flagged", False):
+ params["count_flagged"] = str_to_bool(count_flagged)
+ if not params.get("course_id"):
+ params["course_id"] = str(course_key)
+ response = forum_api.get_user_threads(**params)
+ else:
+ response = utils.perform_request(
+ 'get',
+ url,
+ params,
+ metric_action='user.subscribed_threads',
+ metric_tags=self._metric_tags,
+ paged_results=True
+ )
return utils.CommentClientPaginatedResult(
collection=response.get('collection', []),
page=response.get('page', 1),
@@ -144,23 +227,39 @@ def _retrieve(self, *args, **kwargs):
url = self.url(action='get', params=self.attributes)
retrieve_params = self.default_retrieve_params.copy()
retrieve_params.update(kwargs)
+
if self.attributes.get('course_id'):
retrieve_params['course_id'] = str(self.course_id)
if self.attributes.get('group_id'):
retrieve_params['group_id'] = self.group_id
- try:
- response = utils.perform_request(
- 'get',
- url,
- retrieve_params,
- metric_action='model.retrieve',
- metric_tags=self._metric_tags,
- )
- except utils.CommentClientRequestError as e:
- if e.status_code == 404:
- # attempt to gracefully recover from a previous failure
- # to sync this user to the comments service.
- self.save()
+
+ # course key -> id conversation
+ course_id = retrieve_params.get('course_id')
+ if course_id:
+ course_id = str(course_id)
+ retrieve_params['course_id'] = course_id
+ course_key = utils.get_course_key(course_id)
+
+ if is_forum_v2_enabled(course_key):
+ group_ids = [retrieve_params['group_id']] if 'group_id' in retrieve_params else []
+ is_complete = retrieve_params['complete']
+ try:
+ response = forum_api.get_user(
+ self.attributes["id"],
+ group_ids=group_ids,
+ course_id=course_id,
+ complete=is_complete
+ )
+ except ForumV2RequestError as e:
+ self.save({"course_id": course_id})
+ response = forum_api.get_user(
+ self.attributes["id"],
+ group_ids=group_ids,
+ course_id=course_id,
+ complete=is_complete
+ )
+ else:
+ try:
response = utils.perform_request(
'get',
url,
@@ -168,33 +267,52 @@ def _retrieve(self, *args, **kwargs):
metric_action='model.retrieve',
metric_tags=self._metric_tags,
)
- else:
- raise
+ except utils.CommentClientRequestError as e:
+ if e.status_code == 404:
+ # attempt to gracefully recover from a previous failure
+ # to sync this user to the comments service.
+ self.save()
+ response = utils.perform_request(
+ 'get',
+ url,
+ retrieve_params,
+ metric_action='model.retrieve',
+ metric_tags=self._metric_tags,
+ )
+ else:
+ raise
self._update_from_response(response)
def retire(self, retired_username):
- url = _url_for_retire(self.id)
- params = {'retired_username': retired_username}
-
- utils.perform_request(
- 'post',
- url,
- params,
- raw=True,
- metric_action='user.retire',
- metric_tags=self._metric_tags
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ forum_api.retire_user(user_id=self.id, retired_username=retired_username, course_id=str(course_key))
+ else:
+ url = _url_for_retire(self.id)
+ params = {'retired_username': retired_username}
+ utils.perform_request(
+ 'post',
+ url,
+ params,
+ raw=True,
+ metric_action='user.retire',
+ metric_tags=self._metric_tags
+ )
def replace_username(self, new_username):
- url = _url_for_username_replacement(self.id)
- params = {"new_username": new_username}
-
- utils.perform_request(
- 'post',
- url,
- params,
- raw=True,
- )
+ course_key = utils.get_course_key(self.attributes.get("course_id"))
+ if is_forum_v2_enabled(course_key):
+ forum_api.update_username(user_id=self.id, new_username=new_username, course_id=str(course_key))
+ else:
+ url = _url_for_username_replacement(self.id)
+ params = {"new_username": new_username}
+
+ utils.perform_request(
+ 'post',
+ url,
+ params,
+ raw=True,
+ )
def _url_for_vote_comment(comment_id):
diff --git a/openedx/core/djangoapps/django_comment_common/comment_client/utils.py b/openedx/core/djangoapps/django_comment_common/comment_client/utils.py
index a67cdbdbc483..e77f39e6277d 100644
--- a/openedx/core/djangoapps/django_comment_common/comment_client/utils.py
+++ b/openedx/core/djangoapps/django_comment_common/comment_client/utils.py
@@ -7,6 +7,7 @@
import requests
from django.utils.translation import get_language
+from opaque_keys.edx.keys import CourseKey
from .settings import SERVICE_HOST as COMMENTS_SERVICE
@@ -167,3 +168,19 @@ def check_forum_heartbeat():
return 'forum', False, res.get('check', 'Forum heartbeat failed')
except Exception as fail:
return 'forum', False, str(fail)
+
+
+def get_course_key(course_id: CourseKey | str | None) -> CourseKey | None:
+ """
+ Returns a CourseKey if the provided course_id is a valid string representation of a CourseKey.
+ If course_id is None or already a CourseKey object, it returns the course_id as is.
+ Args:
+ course_id (CourseKey | str | None): The course ID to be converted.
+ Returns:
+ CourseKey | None: The corresponding CourseKey object or None if the input is None.
+ Raises:
+ KeyError: If course_id is not a valid string representation of a CourseKey.
+ """
+ if course_id and isinstance(course_id, str):
+ course_id = CourseKey.from_string(course_id)
+ return course_id
diff --git a/openedx/core/djangoapps/notifications/email/events.py b/openedx/core/djangoapps/notifications/email/events.py
index 165539a018cb..a575d78eaeb5 100644
--- a/openedx/core/djangoapps/notifications/email/events.py
+++ b/openedx/core/djangoapps/notifications/email/events.py
@@ -12,19 +12,29 @@
EMAIL_DIGEST_SENT = "edx.notifications.email_digest"
-def send_user_email_digest_sent_event(user, cadence_type, notifications):
+def send_user_email_digest_sent_event(user, cadence_type, notifications, message_context):
"""
Sends tracker and segment email for user email digest
"""
notification_breakdown = {key: 0 for key in COURSE_NOTIFICATION_APPS.keys()}
for notification in notifications:
notification_breakdown[notification.app_name] += 1
+
+ truncated_count = {}
+ email_content = message_context.get("email_content", [])
+ for app in email_content:
+ truncated_count[app.get("title", "")] = {
+ "total": app.get("total", -1),
+ "remaining_count": app.get("remaining_count", -1),
+ }
+
event_data = {
"username": user.username,
"email": user.email,
"cadence_type": cadence_type,
"total_notifications_count": len(notifications),
"count_breakdown": notification_breakdown,
+ "truncated_count": truncated_count,
"notification_ids": [notification.id for notification in notifications],
"send_at": str(datetime.datetime.now())
}
diff --git a/openedx/core/djangoapps/notifications/email/tasks.py b/openedx/core/djangoapps/notifications/email/tasks.py
index 0d450fe9a917..c2e0a2fa375d 100644
--- a/openedx/core/djangoapps/notifications/email/tasks.py
+++ b/openedx/core/djangoapps/notifications/email/tasks.py
@@ -103,7 +103,7 @@ def send_digest_email_to_user(user, cadence_type, start_date, end_date, course_l
).personalize(recipient, course_language, message_context)
message = add_headers_to_email_message(message, message_context)
ace.send(message)
- send_user_email_digest_sent_event(user, cadence_type, notifications)
+ send_user_email_digest_sent_event(user, cadence_type, notifications, message_context)
logger.info(f' Email sent to {user.username} ==Temp Log==')
diff --git a/openedx/core/djangoapps/notifications/email/tests/test_utils.py b/openedx/core/djangoapps/notifications/email/tests/test_utils.py
index 1f3da983a020..6c7f5b7144cf 100644
--- a/openedx/core/djangoapps/notifications/email/tests/test_utils.py
+++ b/openedx/core/djangoapps/notifications/email/tests/test_utils.py
@@ -148,8 +148,18 @@ def test_email_digest_context(self, digest_frequency):
{'title': 'Updates', 'count': 1},
]
expected_email_content = [
- {'title': 'Discussion', 'help_text': '', 'help_text_url': '', 'notifications': [discussion_notification]},
- {'title': 'Updates', 'help_text': '', 'help_text_url': '', 'notifications': [update_notification]}
+ {
+ 'title': 'Discussion', 'help_text': '', 'help_text_url': '',
+ 'notifications': [discussion_notification],
+ 'total': 1, 'show_remaining_count': False, 'remaining_count': 0,
+ 'url': 'http://learner-home-mfe/?showNotifications=true&app=discussion'
+ },
+ {
+ 'title': 'Updates', 'help_text': '', 'help_text_url': '',
+ 'notifications': [update_notification],
+ 'total': 1, 'show_remaining_count': False, 'remaining_count': 0,
+ 'url': 'http://learner-home-mfe/?showNotifications=true&app=updates'
+ }
]
assert context['start_date'] == expected_start_date
assert context['end_date'] == 'Sunday, Mar 24'
diff --git a/openedx/core/djangoapps/notifications/email/utils.py b/openedx/core/djangoapps/notifications/email/utils.py
index d855494012ea..9fd761785e5a 100644
--- a/openedx/core/djangoapps/notifications/email/utils.py
+++ b/openedx/core/djangoapps/notifications/email/utils.py
@@ -130,17 +130,29 @@ def create_email_digest_context(app_notifications_dict, username, start_date, en
}
for key, value in app_notifications_dict.items()
])
- email_content = [
- {
+
+ email_content = []
+ notifications_in_app = 5
+ for key, value in app_notifications_dict.items():
+ total = value['count']
+ app_content = {
'title': value['title'],
'help_text': value.get('help_text', ''),
'help_text_url': value.get('help_text_url', ''),
'notifications': add_additional_attributes_to_notifications(
value.get('notifications', []), courses_data=courses_data
- )
+ ),
+ 'total': total,
+ 'show_remaining_count': False,
+ 'remaining_count': 0,
+ 'url': f'{settings.LEARNER_HOME_MICROFRONTEND_URL}/?showNotifications=true&app={key}'
}
- for key, value in app_notifications_dict.items()
- ]
+ if total > notifications_in_app:
+ app_content['notifications'] = app_content['notifications'][:notifications_in_app]
+ app_content['show_remaining_count'] = True
+ app_content['remaining_count'] = total - notifications_in_app
+ email_content.append(app_content)
+
context.update({
"start_date": start_date_str,
"end_date": end_date_str,
@@ -295,6 +307,7 @@ def filter_notification_with_email_enabled_preferences(notifications, preference
for notification in notifications:
if notification.notification_type in enabled_course_prefs[notification.course_id]:
filtered_notifications.append(notification)
+ filtered_notifications.sort(key=lambda elem: elem.created, reverse=True)
return filtered_notifications
diff --git a/openedx/core/djangoapps/notifications/templates/notifications/digest_content.html b/openedx/core/djangoapps/notifications/templates/notifications/digest_content.html
index d482cd0c4408..51966f96f574 100644
--- a/openedx/core/djangoapps/notifications/templates/notifications/digest_content.html
+++ b/openedx/core/djangoapps/notifications/templates/notifications/digest_content.html
@@ -56,5 +56,13 @@
+
+ {% if notification_app.show_remaining_count %}
+
+
+ + {{ notification_app.remaining_count }} more
+
+
+ {% endif %}
+
{% endfor %}
diff --git a/openedx/core/djangoapps/user_authn/views/login.py b/openedx/core/djangoapps/user_authn/views/login.py
index 6c7390406be1..042ef90c9a40 100644
--- a/openedx/core/djangoapps/user_authn/views/login.py
+++ b/openedx/core/djangoapps/user_authn/views/login.py
@@ -354,6 +354,11 @@ def _track_user_login(user, request):
# .. pii: Username and email are sent to Segment here. Retired directly through Segment API call in Tubular.
# .. pii_types: email_address, username
# .. pii_retirement: third_party
+ anonymous_id = ""
+ try:
+ anonymous_id = request.COOKIES.get('ajs_anonymous_id', "")
+ except: # pylint: disable=bare-except
+ pass
segment.identify(
user.id,
{"email": user.email, "username": user.username},
@@ -367,7 +372,12 @@ def _track_user_login(user, request):
segment.track(
user.id,
"edx.bi.user.account.authenticated",
- {"category": "conversion", "label": request.POST.get("course_id"), "provider": None},
+ {
+ "category": "conversion",
+ "label": request.POST.get("course_id"),
+ "provider": None,
+ "anonymous_id": anonymous_id,
+ },
)
diff --git a/openedx/core/djangoapps/user_authn/views/register.py b/openedx/core/djangoapps/user_authn/views/register.py
index ab57687d2cd4..defeeb76f2e5 100644
--- a/openedx/core/djangoapps/user_authn/views/register.py
+++ b/openedx/core/djangoapps/user_authn/views/register.py
@@ -231,7 +231,7 @@ def create_account_with_params(request, params): # pylint: disable=too-many-sta
log.exception('Error while setting is_marketable attribute.')
is_marketable = None
- _track_user_registration(user, profile, params, third_party_provider, registration, is_marketable)
+ _track_user_registration(user, profile, params, third_party_provider, registration, is_marketable, request=request)
# Sites using multiple languages need to record the language used during registration.
# If not, compose_and_send_activation_email will be sent in site's default language only.
@@ -356,9 +356,14 @@ def _link_user_to_third_party_provider(
return third_party_provider, running_pipeline
-def _track_user_registration(user, profile, params, third_party_provider, registration, is_marketable):
+def _track_user_registration(user, profile, params, third_party_provider, registration, is_marketable, request=None):
""" Track the user's registration. """
if hasattr(settings, 'LMS_SEGMENT_KEY') and settings.LMS_SEGMENT_KEY:
+ anonymous_id = ""
+ try:
+ anonymous_id = request.COOKIES.get('ajs_anonymous_id', "")
+ except: # pylint: disable=bare-except
+ pass
traits = {
'email': user.email,
'username': user.username,
@@ -370,7 +375,8 @@ def _track_user_registration(user, profile, params, third_party_provider, regist
'address': profile.mailing_address,
'gender': profile.gender_display,
'country': str(profile.country),
- 'is_marketable': is_marketable
+ 'is_marketable': is_marketable,
+ 'anonymous_id': anonymous_id
}
if settings.MARKETING_EMAILS_OPT_IN and params.get('marketing_emails_opt_in'):
email_subscribe = 'subscribed' if is_marketable else 'unsubscribed'
@@ -397,6 +403,7 @@ def _track_user_registration(user, profile, params, third_party_provider, regist
'host': params.get('host', ''),
'app_name': params.get('app_name', ''),
'utm_campaign': params.get('utm_campaign', ''),
+ 'anonymous_id': anonymous_id
}
# VAN-738 - added below properties to experiment marketing emails opt in/out events on Braze.
if params.get('marketing_emails_opt_in') and settings.MARKETING_EMAILS_OPT_IN:
diff --git a/openedx/core/djangoapps/user_authn/views/tests/test_login.py b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
index 1e8a4c3ed510..aa34a076d403 100644
--- a/openedx/core/djangoapps/user_authn/views/tests/test_login.py
+++ b/openedx/core/djangoapps/user_authn/views/tests/test_login.py
@@ -1145,7 +1145,7 @@ def test_login(self, include_analytics, mock_segment):
mock_segment.track.assert_called_once_with(
expected_user_id,
'edx.bi.user.account.authenticated',
- {'category': 'conversion', 'provider': None, 'label': track_label}
+ {'category': 'conversion', 'provider': None, 'label': track_label, 'anonymous_id': ''}
)
def test_login_with_username(self):
diff --git a/openedx/core/djangoapps/xblock/api.py b/openedx/core/djangoapps/xblock/api.py
index 00bb8bc356a6..35c05cd7b407 100644
--- a/openedx/core/djangoapps/xblock/api.py
+++ b/openedx/core/djangoapps/xblock/api.py
@@ -33,7 +33,12 @@
LearningCoreXBlockRuntime,
)
from .data import CheckPerm, LatestVersion
-from .utils import get_secure_token_for_xblock_handler, get_xblock_id_for_anonymous_user
+from .rest_api.url_converters import VersionConverter
+from .utils import (
+ get_secure_token_for_xblock_handler,
+ get_xblock_id_for_anonymous_user,
+ get_auto_latest_version,
+)
from .runtime.learning_core_runtime import LearningCoreXBlockRuntime
@@ -208,13 +213,26 @@ def get_component_from_usage_key(usage_key: UsageKeyV2) -> Component:
)
-def get_block_draft_olx(usage_key: UsageKeyV2) -> str:
+def get_block_olx(
+ usage_key: UsageKeyV2,
+ *,
+ version: int | LatestVersion = LatestVersion.AUTO
+) -> str:
"""
- Get the OLX source of the draft version of the given Learning-Core-backed XBlock.
+ Get the OLX source of the of the given Learning-Core-backed XBlock and a version.
"""
- # Inefficient but simple approach. Optimize later if needed.
component = get_component_from_usage_key(usage_key)
- component_version = component.versioning.draft
+ version = get_auto_latest_version(version)
+
+ if version == LatestVersion.DRAFT:
+ component_version = component.versioning.draft
+ elif version == LatestVersion.PUBLISHED:
+ component_version = component.versioning.published
+ else:
+ assert isinstance(version, int)
+ component_version = component.versioning.version_num(version)
+ if component_version is None:
+ raise NoSuchUsage(usage_key)
# TODO: we should probably make a method on ComponentVersion that returns
# a content based on the name. Accessing by componentversioncontent__key is
@@ -224,6 +242,11 @@ def get_block_draft_olx(usage_key: UsageKeyV2) -> str:
return content.text
+def get_block_draft_olx(usage_key: UsageKeyV2) -> str:
+ """ DEPRECATED. Use get_block_olx(). Can be removed post-Teak. """
+ return get_block_olx(usage_key, version=LatestVersion.DRAFT)
+
+
def render_block_view(block, view_name, user): # pylint: disable=unused-argument
"""
Get the HTML, JS, and CSS needed to render the given XBlock view.
diff --git a/openedx/core/djangoapps/xblock/rest_api/serializers.py b/openedx/core/djangoapps/xblock/rest_api/serializers.py
new file mode 100644
index 000000000000..bb4dd1da229f
--- /dev/null
+++ b/openedx/core/djangoapps/xblock/rest_api/serializers.py
@@ -0,0 +1,11 @@
+"""
+Serializers for the xblock REST API
+"""
+from rest_framework import serializers
+
+
+class XBlockOlxSerializer(serializers.Serializer):
+ """
+ Serializer for representing an XBlock's OLX
+ """
+ olx = serializers.CharField()
diff --git a/openedx/core/djangoapps/xblock/rest_api/urls.py b/openedx/core/djangoapps/xblock/rest_api/urls.py
index ee41b43f5b39..a83d5104e570 100644
--- a/openedx/core/djangoapps/xblock/rest_api/urls.py
+++ b/openedx/core/djangoapps/xblock/rest_api/urls.py
@@ -19,6 +19,8 @@
path('', views.block_metadata),
# get/post full json fields of an XBlock:
path('fields/', views.BlockFieldsView.as_view()),
+ # Get the OLX source code of the specified block
+ path('olx/', views.get_block_olx_view),
# render one of this XBlock's views (e.g. student_view)
path('view//', views.render_block_view),
# get the URL needed to call this XBlock's handlers
diff --git a/openedx/core/djangoapps/xblock/rest_api/views.py b/openedx/core/djangoapps/xblock/rest_api/views.py
index d69edcbfd51c..edcbf22e0d3d 100644
--- a/openedx/core/djangoapps/xblock/rest_api/views.py
+++ b/openedx/core/djangoapps/xblock/rest_api/views.py
@@ -33,9 +33,11 @@
get_handler_url as _get_handler_url,
load_block,
render_block_view as _render_block_view,
+ get_block_olx,
)
from ..utils import validate_secure_token_for_xblock_handler
from .url_converters import VersionConverter
+from .serializers import XBlockOlxSerializer
User = get_user_model()
@@ -213,6 +215,23 @@ def xblock_handler(
return response
+@api_view(['GET'])
+@view_auth_classes(is_authenticated=False)
+def get_block_olx_view(
+ request,
+ usage_key: UsageKeyV2,
+ version: LatestVersion | int = LatestVersion.AUTO,
+):
+ """
+ Get the OLX (XML serialization) of the specified XBlock
+ """
+ context_impl = get_learning_context_impl(usage_key)
+ if not context_impl.can_view_block_for_editing(request.user, usage_key):
+ raise PermissionDenied(f"You don't have permission to access the OLX of component '{usage_key}'.")
+ olx = get_block_olx(usage_key, version=version)
+ return Response(XBlockOlxSerializer({"olx": olx}).data)
+
+
def cors_allow_xblock_handler(sender, request, **kwargs): # lint-amnesty, pylint: disable=unused-argument
"""
Sandboxed XBlocks need to be able to call XBlock handlers via POST,
diff --git a/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py b/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py
index fd2e867a3a8f..dde2084e54cd 100644
--- a/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py
+++ b/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py
@@ -24,6 +24,7 @@
from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_learning_core
from openedx.core.lib.xblock_serializer.data import StaticFile
from ..data import AuthoredDataMode, LatestVersion
+from ..utils import get_auto_latest_version
from ..learning_context.manager import get_learning_context_impl
from .runtime import XBlockRuntime
@@ -178,11 +179,7 @@ def get_block(self, usage_key, for_parent=None, *, version: int | LatestVersion
# just get it the easy way.
component = self._get_component_from_usage_key(usage_key)
- if version == LatestVersion.AUTO:
- if self.authored_data_mode == AuthoredDataMode.DEFAULT_DRAFT:
- version = LatestVersion.DRAFT
- else:
- version = LatestVersion.PUBLISHED
+ version = get_auto_latest_version(version)
if self.authored_data_mode == AuthoredDataMode.STRICTLY_PUBLISHED and version != LatestVersion.PUBLISHED:
raise ValidationError("This runtime only allows accessing the published version of components")
if version == LatestVersion.DRAFT:
diff --git a/openedx/core/djangoapps/xblock/utils.py b/openedx/core/djangoapps/xblock/utils.py
index 375bb9d21450..b4ae054cf498 100644
--- a/openedx/core/djangoapps/xblock/utils.py
+++ b/openedx/core/djangoapps/xblock/utils.py
@@ -11,6 +11,10 @@
import crum
from django.conf import settings
+from openedx.core.djangoapps.xblock.apps import get_xblock_app_config
+
+from .data import AuthoredDataMode, LatestVersion
+
def get_secure_token_for_xblock_handler(user_id, block_key_str, time_idx=0):
"""
@@ -167,3 +171,18 @@ def get_xblock_id_for_anonymous_user(user):
return current_request.session["xblock_id_for_anonymous_user"]
else:
raise RuntimeError("Cannot get a user ID for an anonymous user outside of an HTTP request context.")
+
+
+def get_auto_latest_version(version: int | LatestVersion) -> int | LatestVersion:
+ """
+ Gets the actual LatestVersion if is `LatestVersion.AUTO`;
+ otherwise, returns the same value.
+ """
+ if version == LatestVersion.AUTO:
+ authored_data_mode = get_xblock_app_config().get_runtime_params()["authored_data_mode"]
+ version = (
+ LatestVersion.DRAFT
+ if authored_data_mode == AuthoredDataMode.DEFAULT_DRAFT
+ else LatestVersion.PUBLISHED
+ )
+ return version
diff --git a/openedx/features/announcements/apps.py b/openedx/features/announcements/apps.py
deleted file mode 100644
index 4bf964cae51b..000000000000
--- a/openedx/features/announcements/apps.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""
-Announcements Application Configuration
-"""
-
-
-from django.apps import AppConfig
-from edx_django_utils.plugins import PluginURLs, PluginSettings
-
-from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType
-
-
-class AnnouncementsConfig(AppConfig):
- """
- Application Configuration for Announcements
- """
- name = 'openedx.features.announcements'
-
- plugin_app = {
- PluginURLs.CONFIG: {
- ProjectType.LMS: {
- PluginURLs.NAMESPACE: 'announcements',
- PluginURLs.REGEX: '^announcements/',
- PluginURLs.RELATIVE_PATH: 'urls',
- }
- },
- PluginSettings.CONFIG: {
- ProjectType.LMS: {
- SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: 'settings.common'},
- SettingsType.TEST: {PluginSettings.RELATIVE_PATH: 'settings.test'},
- }
- }
- }
diff --git a/openedx/features/announcements/forms.py b/openedx/features/announcements/forms.py
deleted file mode 100644
index 879101ca37d0..000000000000
--- a/openedx/features/announcements/forms.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Forms for the Announcement Editor
-"""
-
-
-from django import forms
-
-from .models import Announcement
-
-
-class AnnouncementForm(forms.ModelForm):
- """
- Form for editing Announcements
- """
- content = forms.CharField(widget=forms.Textarea, label='', required=False)
- active = forms.BooleanField(initial=True, required=False)
-
- class Meta:
- model = Announcement
- fields = ['content', 'active']
diff --git a/openedx/features/announcements/models.py b/openedx/features/announcements/models.py
deleted file mode 100644
index f58f61165db6..000000000000
--- a/openedx/features/announcements/models.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Models for Announcements
-"""
-
-
-from django.db import models
-
-
-class Announcement(models.Model):
- """
- Site-wide announcements to be displayed on the dashboard
-
- .. no_pii:
- """
- class Meta:
- app_label = 'announcements'
-
- content = models.CharField(max_length=1000, null=False, default="lorem ipsum")
- active = models.BooleanField(default=True)
-
- def __str__(self):
- return self.content
diff --git a/openedx/features/announcements/settings/__init__.py b/openedx/features/announcements/settings/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/openedx/features/announcements/settings/common.py b/openedx/features/announcements/settings/common.py
deleted file mode 100644
index 1a1a5ca497ab..000000000000
--- a/openedx/features/announcements/settings/common.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""Common settings for Announcements"""
-
-
-def plugin_settings(settings):
- """
- Common settings for Announcements
- .. toggle_name: FEATURES['ENABLE_ANNOUNCEMENTS']
- .. toggle_implementation: SettingDictToggle
- .. toggle_default: False
- .. toggle_description: This feature can be enabled to show system wide announcements
- on the sidebar of the learner dashboard. Announcements can be created by Global Staff
- users on maintenance dashboard of studio. Maintenance dashboard can accessed at
- https://{studio.domain}/maintenance
- .. toggle_warning: TinyMCE is needed to show an editor in the studio.
- .. toggle_use_cases: open_edx
- .. toggle_creation_date: 2017-11-08
- .. toggle_tickets: https://github.com/openedx/edx-platform/pull/16496
- """
- settings.FEATURES['ENABLE_ANNOUNCEMENTS'] = False
- # Configure number of announcements to show per page
- settings.FEATURES['ANNOUNCEMENTS_PER_PAGE'] = 5
diff --git a/openedx/features/announcements/settings/test.py b/openedx/features/announcements/settings/test.py
deleted file mode 100644
index 47d57ca3dcbf..000000000000
--- a/openedx/features/announcements/settings/test.py
+++ /dev/null
@@ -1,8 +0,0 @@
-"""Test settings for Announcements"""
-
-
-def plugin_settings(settings):
- """
- Test settings for Announcements
- """
- settings.FEATURES['ENABLE_ANNOUNCEMENTS'] = True
diff --git a/openedx/features/announcements/static/announcements/jsx/Announcements.jsx b/openedx/features/announcements/static/announcements/jsx/Announcements.jsx
deleted file mode 100644
index 9d370883352c..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/Announcements.jsx
+++ /dev/null
@@ -1,141 +0,0 @@
-// eslint-disable-next-line max-classes-per-file
-import React from 'react';
-import ReactDOM from 'react-dom';
-import PropTypes from 'prop-types';
-import {Button} from '@edx/paragon';
-import $ from 'jquery';
-
-class AnnouncementSkipLink extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- count: 0
- };
- $.get('/announcements/page/1')
- .then(data => {
- this.setState({
- count: data.count
- });
- });
- }
-
- render() {
- return ({'Skip to list of ' + this.state.count + ' announcements'}
);
- }
-}
-
-// eslint-disable-next-line react/prefer-stateless-function
-class Announcement extends React.Component {
- render() {
- return (
-
- );
- }
-}
-
-Announcement.propTypes = {
- content: PropTypes.string.isRequired,
-};
-
-class AnnouncementList extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- page: 1,
- announcements: [],
- // eslint-disable-next-line react/no-unused-state
- num_pages: 0,
- has_prev: false,
- has_next: false,
- start_index: 0,
- end_index: 0,
- };
- }
-
- retrievePage(page) {
- $.get('/announcements/page/' + page)
- .then(data => {
- this.setState({
- announcements: data.announcements,
- has_next: data.next,
- has_prev: data.prev,
- // eslint-disable-next-line react/no-unused-state
- num_pages: data.num_pages,
- count: data.count,
- start_index: data.start_index,
- end_index: data.end_index,
- page: page
- });
- });
- }
-
- renderPrevPage() {
- this.retrievePage(this.state.page - 1);
- }
-
- renderNextPage() {
- this.retrievePage(this.state.page + 1);
- }
-
- // eslint-disable-next-line react/no-deprecated, react/sort-comp
- componentWillMount() {
- this.retrievePage(this.state.page);
- }
-
- render() {
- var children = this.state.announcements.map(
- // eslint-disable-next-line react/no-array-index-key
- (announcement, index) =>
- );
- if (this.state.has_prev) {
- var prev_button = (
-
- this.renderPrevPage()}
- label="← previous"
- />
- {this.state.start_index + ' - ' + this.state.end_index + ') of ' + this.state.count}
-
- );
- }
- if (this.state.has_next) {
- var next_button = (
-
- this.renderNextPage()}
- label="next →"
- />
- {this.state.start_index + ' - ' + this.state.end_index + ') of ' + this.state.count}
-
- );
- }
- return (
-
- {children}
- {prev_button}
- {next_button}
-
- );
- }
-}
-
-export default class AnnouncementsView {
- constructor() {
- ReactDOM.render(
- ,
- document.getElementById('announcements'),
- );
- ReactDOM.render(
- ,
- document.getElementById('announcements-skip'),
- );
- }
-}
-
-export {AnnouncementsView, AnnouncementList, AnnouncementSkipLink};
diff --git a/openedx/features/announcements/static/announcements/jsx/Announcements.test.jsx b/openedx/features/announcements/static/announcements/jsx/Announcements.test.jsx
deleted file mode 100644
index 3ec55f392889..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/Announcements.test.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import renderer from 'react-test-renderer';
-import testAnnouncements from './test-announcements.json';
-
-import {AnnouncementSkipLink, AnnouncementList} from './Announcements';
-
-describe('Announcements component', () => {
- test('render skip link', () => {
- const component = renderer.create(
- ,
- );
- component.root.instance.setState({count: 10});
- const tree = component.toJSON();
- expect(tree).toMatchSnapshot();
- });
-
- test('render test announcements', () => {
- const component = renderer.create(
- ,
- );
- component.root.instance.setState(testAnnouncements);
- const tree = component.toJSON();
- expect(tree).toMatchSnapshot();
- });
-});
diff --git a/openedx/features/announcements/static/announcements/jsx/__snapshots__/Announcements.test.jsx.snap b/openedx/features/announcements/static/announcements/jsx/__snapshots__/Announcements.test.jsx.snap
deleted file mode 100644
index 70eb30a812d7..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/__snapshots__/Announcements.test.jsx.snap
+++ /dev/null
@@ -1,78 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Announcements component render skip link 1`] = `
-
- Skip to list of 10 announcements
-
-`;
-
-exports[`Announcements component render test announcements 1`] = `
-
-
-
Announcement 2",
- }
- }
- />
-
-
-
-
-
-
- next →
-
-
- 1 - 5) of 6
-
-
-
-`;
diff --git a/openedx/features/announcements/static/announcements/jsx/test-announcements.json b/openedx/features/announcements/static/announcements/jsx/test-announcements.json
deleted file mode 100644
index d23d39303020..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/test-announcements.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "announcements": [
- {"content": "Test Announcement 1"},
- {"content": "Bold
Announcement 2 "},
- {"content": "Test Announcement 3"},
- {"content": "Test Announcement 4"},
- {"content": "Test Announcement 5"},
- {"content": "Test Announcement 6"}
- ],
- "has_next": true,
- "has_prev": false,
- "num_pages": 2,
- "count": 6,
- "start_index": 1,
- "end_index": 5,
- "page": 1
-}
diff --git a/openedx/features/announcements/tests/__init__.py b/openedx/features/announcements/tests/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/openedx/features/announcements/tests/test_announcements.py b/openedx/features/announcements/tests/test_announcements.py
deleted file mode 100644
index 10c608b4a6cd..000000000000
--- a/openedx/features/announcements/tests/test_announcements.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-Unit tests for the announcements feature.
-"""
-
-import json
-from unittest.mock import patch
-
-from django.conf import settings
-from django.test import TestCase
-from django.test.client import Client
-from django.urls import reverse
-
-from common.djangoapps.student.tests.factories import AdminFactory
-from openedx.core.djangolib.testing.utils import skip_unless_lms
-from openedx.features.announcements.models import Announcement
-
-TEST_ANNOUNCEMENTS = [
- ("Active Announcement", True),
- ("Inactive Announcement", False),
- ("Another Test Announcement", True),
- ("
Formatted Announcement ", True),
- ("
Other Formatted Announcement ", True),
-]
-
-
-@skip_unless_lms
-class TestGlobalAnnouncements(TestCase):
- """
- Test Announcements in LMS
- """
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- Announcement.objects.bulk_create([
- Announcement(content=content, active=active)
- for content, active in TEST_ANNOUNCEMENTS
- ])
-
- def setUp(self):
- super().setUp()
- self.client = Client()
- self.admin = AdminFactory.create(
- email='staff@edx.org',
- username='admin',
- password='pass'
- )
- self.client.login(username=self.admin.username, password='pass')
-
- @patch.dict(settings.FEATURES, {'ENABLE_ANNOUNCEMENTS': False})
- def test_feature_flag_disabled(self):
- """Ensures that the default settings effectively disables the feature"""
- response = self.client.get('/dashboard')
- self.assertNotContains(response, 'AnnouncementsView')
- self.assertNotContains(response, '
Formatted Announcement")
diff --git a/openedx/features/announcements/urls.py b/openedx/features/announcements/urls.py
deleted file mode 100644
index 0f0ad3a33960..000000000000
--- a/openedx/features/announcements/urls.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""
-Defines URLs for announcements in the LMS.
-"""
-from django.contrib.auth.decorators import login_required
-from django.urls import path
-
-from .views import AnnouncementsJSONView
-
-urlpatterns = [
- path('page/
', login_required(AnnouncementsJSONView.as_view()),
- name='page',
- ),
-]
diff --git a/openedx/features/announcements/views.py b/openedx/features/announcements/views.py
deleted file mode 100644
index b6657c29cc12..000000000000
--- a/openedx/features/announcements/views.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""
-Views to show announcements.
-"""
-
-
-from django.conf import settings
-from django.http import JsonResponse
-from django.views.generic.list import ListView
-
-from .models import Announcement
-
-
-class AnnouncementsJSONView(ListView):
- """
- View returning a page of announcements for the dashboard
- """
- model = Announcement
- object_list = Announcement.objects.filter(active=True)
- paginate_by = settings.FEATURES.get('ANNOUNCEMENTS_PER_PAGE', 5)
-
- def get(self, request, *args, **kwargs):
- """
- Return active announcements as json
- """
- context = self.get_context_data()
-
- announcements = [{"content": announcement.content} for announcement in context['object_list']]
- result = {
- "announcements": announcements,
- "next": context['page_obj'].has_next(),
- "prev": context['page_obj'].has_previous(),
- "start_index": context['page_obj'].start_index(),
- "end_index": context['page_obj'].end_index(),
- "count": context['paginator'].count,
- "num_pages": context['paginator'].num_pages,
- }
- return JsonResponse(result)
diff --git a/openedx/features/course_bookmarks/static/course_bookmarks/js/models/bookmark.js b/openedx/features/course_bookmarks/static/course_bookmarks/js/models/bookmark.js
index 13671bddf56a..9ad45a5422ce 100644
--- a/openedx/features/course_bookmarks/static/course_bookmarks/js/models/bookmark.js
+++ b/openedx/features/course_bookmarks/static/course_bookmarks/js/models/bookmark.js
@@ -1,20 +1,37 @@
(function(define) {
- 'use strict';
+ 'use strict';
- define(['backbone'], function(Backbone) {
- return Backbone.Model.extend({
- idAttribute: 'id',
- defaults: {
- course_id: '',
- usage_id: '',
- display_name: '',
- path: [],
- created: ''
- },
+ define(['backbone'], function(Backbone) {
+ return Backbone.Model.extend({
+ idAttribute: 'id',
+ defaults: {
+ course_id: '',
+ usage_id: '',
+ display_name: '',
+ path: [],
+ created: ''
+ },
- blockUrl: function() {
- return '/courses/' + this.get('course_id') + '/jump_to/' + this.get('usage_id');
- }
- });
+ blockUrl: function() {
+ var path = this.get('path');
+ var url = '/courses/' + this.get('course_id') + '/jump_to/' + this.get('usage_id');
+ var params = new URLSearchParams();
+ var usage_id = this.get('usage_id');
+ // Confirm that current usage_id does not correspond to current unit
+ // path contains an array of parent blocks to the bookmarked block.
+ // Units only have two parents i.e. section and subsections.
+ // Below condition is only satisfied if a block lower than unit is bookmarked.
+ if (path.length > 2 && usage_id !== path[path.length - 1]) {
+ params.append('jumpToId', usage_id);
+ }
+ if (params.size > 0) {
+ // Pass nested block details via query parameters for it to be passed to learning mfe
+ // The learning mfe should pass it back to unit xblock via iframe url params.
+ // This would allow us to scroll to the child xblock.
+ url = url + '?' + params.toString();
+ }
+ return url;
+ }
});
+ });
}(define || RequireJS.define));
diff --git a/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmark_button.js b/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmark_button.js
index 838f631868dc..3612038842c5 100644
--- a/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmark_button.js
+++ b/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmark_button.js
@@ -20,6 +20,12 @@
this.bookmarkId = options.bookmarkId;
this.bookmarked = options.bookmarked;
this.usageId = options.usageId;
+ if (options.bookmarkedText) {
+ this.bookmarkedText = options.bookmarkedText;
+ }
+ if (options.bookmarkText) {
+ this.bookmarkText = options.bookmarkText;
+ }
this.setBookmarkState(this.bookmarked);
},
diff --git a/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmarks_list.js b/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmarks_list.js
index 52f5fbd74c1e..55dd1bd58ae5 100644
--- a/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmarks_list.js
+++ b/openedx/features/course_bookmarks/static/course_bookmarks/js/views/bookmarks_list.js
@@ -78,9 +78,7 @@
component_type: componentType,
component_usage_id: componentUsageId
}
- ).always(function() {
- window.location.href = event.currentTarget.pathname;
- });
+ );
},
/**
diff --git a/package-lock.json b/package-lock.json
index eff698e27a8b..16232c97f71f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,7 +13,7 @@
"@babel/plugin-proposal-object-rest-spread": "^7.18.9",
"@babel/plugin-transform-object-assign": "^7.18.6",
"@babel/preset-env": "^7.19.0",
- "@babel/preset-react": "7.25.9",
+ "@babel/preset-react": "7.26.3",
"@edx/brand-edx.org": "^2.0.7",
"@edx/edx-bootstrap": "1.0.4",
"@edx/edx-proctoring": "^4.18.1",
@@ -37,16 +37,16 @@
"exports-loader": "0.6.4",
"file-loader": "^6.2.0",
"font-awesome": "4.7.0",
- "hls.js": "1.5.17",
+ "hls.js": "0.14.17",
"imports-loader": "0.8.0",
- "jest-environment-jsdom": "^26.0.0",
+ "jest-environment-jsdom": "^29.0.0",
"jquery": "2.2.4",
"jquery-migrate": "1.4.1",
"jquery.scrollto": "2.1.3",
"js-cookie": "3.0.5",
"moment": "2.30.1",
"moment-timezone": "0.5.46",
- "node-gyp": "10.2.0",
+ "node-gyp": "10.3.1",
"picturefill": "3.0.3",
"popper.js": "1.16.1",
"prop-types": "15.8.1",
@@ -54,15 +54,15 @@
"react": "16.14.0",
"react-dom": "16.14.0",
"react-focus-lock": "^1.19.1",
- "react-redux": "5.0.7",
- "react-router-dom": "5.1.2",
+ "react-redux": "5.1.2",
+ "react-router-dom": "5.3.4",
"react-slick": "0.30.2",
"redux": "3.7.2",
"redux-thunk": "2.2.0",
"requirejs": "2.3.7",
"rtlcss": "4.3.0",
"sass": "^1.54.8",
- "sass-loader": "^14.1.1",
+ "sass-loader": "^16.0.0",
"scriptjs": "2.5.9",
"style-loader": "4.0.0",
"svg-inline-loader": "0.8.2",
@@ -79,30 +79,30 @@
"@edx/eslint-config": "^4.0.0",
"@edx/mockprock": "github:openedx/mockprock#d70b05231bd46b0122616c24e209c890ef2633c0",
"@edx/stylelint-config-edx": "2.3.3",
- "babel-jest": "26.6.3",
+ "babel-jest": "29.7.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.8",
"eslint-import-resolver-webpack": "0.13.9",
"jasmine-core": "2.6.4",
"jasmine-jquery": "git+https://git@github.com/velesin/jasmine-jquery.git#ebad463d592d3fea00c69f26ea18a930e09c7b58",
- "jest": "26.6.3",
- "jest-enzyme": "6.1.2",
+ "jest": "29.7.0",
+ "jest-enzyme": "7.1.2",
"karma": "0.13.22",
- "karma-chrome-launcher": "0.2.3",
- "karma-coverage": "0.5.5",
- "karma-firefox-launcher": "0.1.7",
+ "karma-chrome-launcher": "3.2.0",
+ "karma-coverage": "2.2.1",
+ "karma-firefox-launcher": "2.1.3",
"karma-jasmine": "0.3.8",
"karma-jasmine-html-reporter": "0.2.2",
- "karma-junit-reporter": "1.2.0",
- "karma-requirejs": "0.2.6",
+ "karma-junit-reporter": "2.0.1",
+ "karma-requirejs": "1.1.0",
"karma-selenium-webdriver-launcher": "github:openedx/karma-selenium-webdriver-launcher#0.0.4-openedx.0",
"karma-sourcemap-loader": "0.4.0",
- "karma-spec-reporter": "0.0.36",
+ "karma-spec-reporter": "0.0.20",
"karma-webpack": "^5.0.1",
"plato": "1.7.0",
"react-test-renderer": "16.14.0",
- "selenium-webdriver": "4.26.0",
- "sinon": "2.4.1",
+ "selenium-webdriver": "4.27.0",
+ "sinon": "19.0.2",
"squirejs": "0.1.0",
"string-replace-loader": "^3.1.0",
"stylelint-formatter-pretty": "4.0.1",
@@ -794,6 +794,22 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "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.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
@@ -1785,9 +1801,9 @@
}
},
"node_modules/@babel/preset-react": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz",
- "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==",
+ "version": "7.26.3",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.26.3.tgz",
+ "integrity": "sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==",
"license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.25.9",
@@ -1876,7 +1892,8 @@
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
"integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@cnakazawa/watch": {
"version": "1.0.4",
@@ -3266,20 +3283,21 @@
}
},
"node_modules/@jest/console": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.6.2.tgz",
- "integrity": "sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
- "jest-message-util": "^26.6.2",
- "jest-util": "^26.6.2",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
"slash": "^3.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/console/node_modules/ansi-styles": {
@@ -3287,6 +3305,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -3302,6 +3321,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -3318,6 +3338,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -3329,13 +3350,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@jest/console/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -3345,6 +3368,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -3353,42 +3377,51 @@
}
},
"node_modules/@jest/core": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.6.3.tgz",
- "integrity": "sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/console": "^26.6.2",
- "@jest/reporters": "^26.6.2",
- "@jest/test-result": "^26.6.2",
- "@jest/transform": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@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.4",
- "jest-changed-files": "^26.6.2",
- "jest-config": "^26.6.3",
- "jest-haste-map": "^26.6.2",
- "jest-message-util": "^26.6.2",
- "jest-regex-util": "^26.0.0",
- "jest-resolve": "^26.6.2",
- "jest-resolve-dependencies": "^26.6.3",
- "jest-runner": "^26.6.3",
- "jest-runtime": "^26.6.3",
- "jest-snapshot": "^26.6.2",
- "jest-util": "^26.6.2",
- "jest-validate": "^26.6.2",
- "jest-watcher": "^26.6.2",
- "micromatch": "^4.0.2",
- "p-each-series": "^2.1.0",
- "rimraf": "^3.0.0",
+ "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": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
"node_modules/@jest/core/node_modules/ansi-styles": {
@@ -3396,6 +3429,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -3411,6 +3445,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -3422,11 +3457,28 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/@jest/core/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/@jest/core/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==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -3438,13 +3490,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@jest/core/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -3454,6 +3508,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -3462,85 +3517,122 @@
}
},
"node_modules/@jest/environment": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.6.2.tgz",
- "integrity": "sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "license": "MIT",
"dependencies": {
- "@jest/fake-timers": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-mock": "^26.6.2"
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/fake-timers": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.6.2.tgz",
- "integrity": "sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "@sinonjs/fake-timers": "^6.0.1",
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
"@types/node": "*",
- "jest-message-util": "^26.6.2",
- "jest-mock": "^26.6.2",
- "jest-util": "^26.6.2"
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/globals": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.6.2.tgz",
- "integrity": "sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/environment": "^26.6.2",
- "@jest/types": "^26.6.2",
- "expect": "^26.6.2"
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/reporters": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.6.2.tgz",
- "integrity": "sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "^26.6.2",
- "@jest/test-result": "^26.6.2",
- "@jest/transform": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@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.2",
- "graceful-fs": "^4.2.4",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
"istanbul-lib-coverage": "^3.0.0",
- "istanbul-lib-instrument": "^4.0.3",
+ "istanbul-lib-instrument": "^6.0.0",
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^4.0.0",
- "istanbul-reports": "^3.0.2",
- "jest-haste-map": "^26.6.2",
- "jest-resolve": "^26.6.2",
- "jest-util": "^26.6.2",
- "jest-worker": "^26.6.2",
+ "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",
- "source-map": "^0.6.0",
"string-length": "^4.0.1",
- "terminal-link": "^2.0.0",
- "v8-to-istanbul": "^7.0.0"
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
- "optionalDependencies": {
- "node-notifier": "^8.0.0"
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
"node_modules/@jest/reporters/node_modules/ansi-styles": {
@@ -3548,6 +3640,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -3563,6 +3656,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -3579,6 +3673,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -3590,30 +3685,47 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@jest/reporters/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
- "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@babel/core": "^7.7.5",
- "@istanbuljs/schema": "^0.1.2",
- "istanbul-lib-coverage": "^3.0.0",
- "semver": "^6.3.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": ">=8"
+ "node": ">=10"
+ }
+ },
+ "node_modules/@jest/reporters/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/@jest/reporters/node_modules/supports-color": {
@@ -3621,6 +3733,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -3628,75 +3741,90 @@
"node": ">=8"
}
},
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
"node_modules/@jest/source-map": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.6.2.tgz",
- "integrity": "sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
"callsites": "^3.0.0",
- "graceful-fs": "^4.2.4",
- "source-map": "^0.6.0"
+ "graceful-fs": "^4.2.9"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/test-result": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.6.2.tgz",
- "integrity": "sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/console": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@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.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/test-sequencer": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz",
- "integrity": "sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/test-result": "^26.6.2",
- "graceful-fs": "^4.2.4",
- "jest-haste-map": "^26.6.2",
- "jest-runner": "^26.6.3",
- "jest-runtime": "^26.6.3"
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/transform": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.6.2.tgz",
- "integrity": "sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/core": "^7.1.0",
- "@jest/types": "^26.6.2",
- "babel-plugin-istanbul": "^6.0.0",
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
"chalk": "^4.0.0",
- "convert-source-map": "^1.4.0",
- "fast-json-stable-stringify": "^2.0.0",
- "graceful-fs": "^4.2.4",
- "jest-haste-map": "^26.6.2",
- "jest-regex-util": "^26.0.0",
- "jest-util": "^26.6.2",
- "micromatch": "^4.0.2",
- "pirates": "^4.0.1",
+ "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",
- "source-map": "^0.6.1",
- "write-file-atomic": "^3.0.0"
+ "write-file-atomic": "^4.0.2"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/transform/node_modules/ansi-styles": {
@@ -3704,6 +3832,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -3719,6 +3848,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -3735,6 +3865,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -3746,13 +3877,22 @@
"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
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@jest/transform/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@jest/transform/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -3762,6 +3902,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -3770,24 +3911,27 @@
}
},
"node_modules/@jest/types": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz",
- "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "license": "MIT",
"dependencies": {
+ "@jest/schemas": "^29.6.3",
"@types/istanbul-lib-coverage": "^2.0.0",
"@types/istanbul-reports": "^3.0.0",
"@types/node": "*",
- "@types/yargs": "^15.0.0",
+ "@types/yargs": "^17.0.8",
"chalk": "^4.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jest/types/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==",
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -3802,6 +3946,7 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -3817,6 +3962,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -3827,12 +3973,14 @@
"node_modules/@jest/types/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=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/@jest/types/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==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -3841,6 +3989,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -4367,28 +4516,86 @@
"react": ">=16.8.0"
}
},
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "license": "MIT"
+ },
"node_modules/@sinonjs/commons": {
- "version": "1.8.6",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
- "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "license": "BSD-3-Clause",
"dependencies": {
"type-detect": "4.0.8"
}
},
"node_modules/@sinonjs/fake-timers": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
- "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==",
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@sinonjs/samsam": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz",
+ "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@sinonjs/commons": "^1.7.0"
+ "@sinonjs/commons": "^3.0.1",
+ "lodash.get": "^4.4.2",
+ "type-detect": "^4.1.0"
+ }
+ },
+ "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons/node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
}
},
+ "node_modules/@sinonjs/samsam/node_modules/type-detect": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz",
+ "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@sinonjs/text-encoding": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz",
+ "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==",
+ "dev": true,
+ "license": "(Unlicense OR Apache-2.0)"
+ },
"node_modules/@tootallnate/once": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
- "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
+ "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
+ "license": "MIT",
"engines": {
- "node": ">= 6"
+ "node": ">= 10"
}
},
"node_modules/@types/babel__core": {
@@ -4477,6 +4684,7 @@
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
"integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*"
}
@@ -4507,6 +4715,17 @@
"@types/istanbul-lib-report": "*"
}
},
+ "node_modules/@types/jsdom": {
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
+ "integrity": "sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/tough-cookie": "*",
+ "parse5": "^7.0.0"
+ }
+ },
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -4539,12 +4758,6 @@
"integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
"dev": true
},
- "node_modules/@types/prettier": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
- "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
- "dev": true
- },
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
@@ -4578,7 +4791,14 @@
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/tough-cookie": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
+ "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
+ "license": "MIT"
},
"node_modules/@types/warning": {
"version": "3.0.3",
@@ -4586,9 +4806,10 @@
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q=="
},
"node_modules/@types/yargs": {
- "version": "15.0.19",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz",
- "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==",
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "license": "MIT",
"dependencies": {
"@types/yargs-parser": "*"
}
@@ -4878,133 +5099,148 @@
"peer": true
},
"node_modules/@webassemblyjs/ast": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
- "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/helper-numbers": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
}
},
"node_modules/@webassemblyjs/floating-point-hex-parser": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
- "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/helper-api-error": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
- "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/helper-buffer": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
- "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw=="
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/helper-numbers": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
- "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/floating-point-hex-parser": "1.11.6",
- "@webassemblyjs/helper-api-error": "1.11.6",
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
- "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/helper-wasm-section": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
- "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.12.1",
- "@webassemblyjs/helper-buffer": "1.12.1",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/wasm-gen": "1.12.1"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
}
},
"node_modules/@webassemblyjs/ieee754": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
- "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "license": "MIT",
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
},
"node_modules/@webassemblyjs/leb128": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
- "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+ "license": "Apache-2.0",
"dependencies": {
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/utf8": {
- "version": "1.11.6",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
- "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/wasm-edit": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
- "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.12.1",
- "@webassemblyjs/helper-buffer": "1.12.1",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/helper-wasm-section": "1.12.1",
- "@webassemblyjs/wasm-gen": "1.12.1",
- "@webassemblyjs/wasm-opt": "1.12.1",
- "@webassemblyjs/wasm-parser": "1.12.1",
- "@webassemblyjs/wast-printer": "1.12.1"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
- "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.12.1",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wasm-opt": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
- "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.12.1",
- "@webassemblyjs/helper-buffer": "1.12.1",
- "@webassemblyjs/wasm-gen": "1.12.1",
- "@webassemblyjs/wasm-parser": "1.12.1"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
- "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.12.1",
- "@webassemblyjs/helper-api-error": "1.11.6",
- "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
- "@webassemblyjs/ieee754": "1.11.6",
- "@webassemblyjs/leb128": "1.11.6",
- "@webassemblyjs/utf8": "1.11.6"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wast-printer": {
- "version": "1.12.1",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
- "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.12.1",
+ "@webassemblyjs/ast": "1.14.1",
"@xtuc/long": "4.2.2"
}
},
@@ -5055,12 +5291,14 @@
"node_modules/@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
- "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+ "license": "BSD-3-Clause"
},
"node_modules/@xtuc/long": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
- "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+ "license": "Apache-2.0"
},
"node_modules/abab": {
"version": "2.0.6",
@@ -5069,10 +5307,13 @@
"deprecated": "Use your platform's native atob() and btoa() methods instead"
},
"node_modules/abbrev": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz",
- "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==",
- "dev": true
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
+ "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
+ "license": "ISC",
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+ }
},
"node_modules/accepts": {
"version": "1.3.3",
@@ -5109,23 +5350,13 @@
}
},
"node_modules/acorn-globals": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz",
- "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+ "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+ "license": "MIT",
"dependencies": {
- "acorn": "^7.1.1",
- "acorn-walk": "^7.1.1"
- }
- },
- "node_modules/acorn-globals/node_modules/acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
+ "acorn": "^8.1.0",
+ "acorn-walk": "^8.0.2"
}
},
"node_modules/acorn-jsx": {
@@ -5139,9 +5370,13 @@
}
},
"node_modules/acorn-walk": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
- "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
"engines": {
"node": ">=0.4.0"
}
@@ -5293,16 +5528,6 @@
"resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
"integrity": "sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ=="
},
- "node_modules/amdefine": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
- "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==",
- "dev": true,
- "optional": true,
- "engines": {
- "node": ">=0.4.2"
- }
- },
"node_modules/ansi-colors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
@@ -5387,6 +5612,7 @@
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -5473,19 +5699,11 @@
"resolved": "https://registry.npmjs.org/array-equal/-/array-equal-1.0.2.tgz",
"integrity": "sha512-gUHx76KtnhEgB3HOuFYiCm3FIdEs6ocM2asHvNTkfu/Y09qQVrrVVaOKENmS2KkSaGoxgXNqC+ZVtR/n0MOkSA==",
"dev": true,
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/array-find-index": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
- "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/array-includes": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
@@ -5651,6 +5869,28 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/array.prototype.reduce": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.7.tgz",
+ "integrity": "sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-array-method-boxes-properly": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/array.prototype.toreversed": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz",
@@ -5719,6 +5959,7 @@
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"safer-buffer": "~2.1.0"
}
@@ -5733,6 +5974,7 @@
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.8"
}
@@ -5762,10 +6004,9 @@
}
},
"node_modules/async": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
- "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==",
- "dev": true
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
},
"node_modules/async-each": {
"version": "1.0.6",
@@ -5783,7 +6024,8 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/asynckit": {
"version": "0.4.0",
@@ -5858,15 +6100,17 @@
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": "*"
}
},
"node_modules/aws4": {
- "version": "1.12.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz",
- "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==",
- "dev": true
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
+ "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/axe-core": {
"version": "4.7.0",
@@ -6010,26 +6254,25 @@
"integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA=="
},
"node_modules/babel-jest": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz",
- "integrity": "sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@jest/transform": "^26.6.2",
- "@jest/types": "^26.6.2",
- "@types/babel__core": "^7.1.7",
- "babel-plugin-istanbul": "^6.0.0",
- "babel-preset-jest": "^26.6.2",
+ "@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.4",
+ "graceful-fs": "^4.2.9",
"slash": "^3.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@babel/core": "^7.8.0"
}
},
"node_modules/babel-jest/node_modules/ansi-styles": {
@@ -6150,18 +6393,19 @@
}
},
"node_modules/babel-plugin-jest-hoist": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz",
- "integrity": "sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/template": "^7.3.3",
"@babel/types": "^7.3.3",
- "@types/babel__core": "^7.0.0",
+ "@types/babel__core": "^7.1.14",
"@types/babel__traverse": "^7.0.6"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/babel-plugin-minify-builtins": {
@@ -6400,16 +6644,17 @@
}
},
"node_modules/babel-preset-jest": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz",
- "integrity": "sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "babel-plugin-jest-hoist": "^26.6.2",
+ "babel-plugin-jest-hoist": "^29.6.3",
"babel-preset-current-node-syntax": "^1.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
@@ -6641,6 +6886,7 @@
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"tweetnacl": "^0.14.3"
}
@@ -6679,6 +6925,7 @@
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
+ "license": "MIT",
"optional": true,
"dependencies": {
"file-uri-to-path": "1.0.0"
@@ -6777,7 +7024,8 @@
"node_modules/browser-process-hrtime": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz",
- "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow=="
+ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==",
+ "dev": true
},
"node_modules/browserslist": {
"version": "4.24.2",
@@ -7098,7 +7346,8 @@
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
- "dev": true
+ "dev": true,
+ "license": "Apache-2.0"
},
"node_modules/cast-array": {
"version": "1.0.1",
@@ -7138,6 +7387,7 @@
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
}
@@ -7236,25 +7486,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/chokidar/node_modules/fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "deprecated": "The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "dependencies": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
"node_modules/chokidar/node_modules/glob-parent": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
@@ -7352,7 +7583,8 @@
"node_modules/ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
- "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="
+ "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+ "dev": true
},
"node_modules/circular-json": {
"version": "0.3.3",
@@ -7368,10 +7600,11 @@
"dev": true
},
"node_modules/cjs-module-lexer": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz",
- "integrity": "sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw==",
- "dev": true
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz",
+ "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/clap": {
"version": "1.2.3",
@@ -7529,14 +7762,18 @@
"dev": true
},
"node_modules/cliui": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
- "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^6.2.0"
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/clone": {
@@ -7625,7 +7862,8 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
"integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/collection-visit": {
"version": "1.0.0",
@@ -7960,6 +8198,104 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "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/create-jest/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,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/create-jest/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,
+ "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/create-jest/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==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/create-jest/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/create-jest/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/create-jest/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",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -8145,9 +8481,10 @@
}
},
"node_modules/cssom": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz",
- "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw=="
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz",
+ "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==",
+ "license": "MIT"
},
"node_modules/cssstyle": {
"version": "2.3.0",
@@ -8170,18 +8507,6 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
- "node_modules/currently-unhandled": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
- "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==",
- "dev": true,
- "dependencies": {
- "array-find-index": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/custom-event": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
@@ -8218,6 +8543,7 @@
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0"
},
@@ -8226,16 +8552,26 @@
}
},
"node_modules/data-urls": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz",
- "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz",
+ "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==",
+ "license": "MIT",
"dependencies": {
- "abab": "^2.0.3",
- "whatwg-mimetype": "^2.3.0",
- "whatwg-url": "^8.0.0"
+ "abab": "^2.0.6",
+ "whatwg-mimetype": "^3.0.0",
+ "whatwg-url": "^11.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=12"
+ }
+ },
+ "node_modules/data-urls/node_modules/whatwg-mimetype": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/data-view-buffer": {
@@ -8383,6 +8719,21 @@
"node": ">=0.10"
}
},
+ "node_modules/dedent": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
"node_modules/deep-equal-ident": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal-ident/-/deep-equal-ident-1.1.1.tgz",
@@ -8421,6 +8772,7 @@
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -8540,6 +8892,7 @@
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
"integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -8556,21 +8909,23 @@
"dev": true
},
"node_modules/diff": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
- "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
+ "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
"dev": true,
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/diff-sequences": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.6.2.tgz",
- "integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/dir-glob": {
@@ -8650,23 +9005,16 @@
]
},
"node_modules/domexception": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz",
- "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
+ "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==",
"deprecated": "Use your platform's native DOMException instead",
+ "license": "MIT",
"dependencies": {
- "webidl-conversions": "^5.0.0"
+ "webidl-conversions": "^7.0.0"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/domexception/node_modules/webidl-conversions": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz",
- "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==",
- "engines": {
- "node": ">=8"
+ "node": ">=12"
}
},
"node_modules/domhandler": {
@@ -8708,6 +9056,7 @@
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
@@ -8717,7 +9066,8 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/edx-proctoring-proctortrack": {
"version": "1.1.1",
@@ -8838,12 +9188,13 @@
}
},
"node_modules/emittery": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.2.tgz",
- "integrity": "sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ==",
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">=12"
},
"funding": {
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
@@ -9028,7 +9379,6 @@
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "dev": true,
"engines": {
"node": ">=0.12"
},
@@ -9160,16 +9510,17 @@
}
},
"node_modules/enzyme-matchers": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-6.1.2.tgz",
- "integrity": "sha512-cP9p+HMOZ1ZXQ+k2H4dCkxmTZzIvpEy5zv0ZjgoBl6D0U43v+bJGH5IeWHdIovCzgJ0dVcMCKJ6lNu83lYUCAA==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/enzyme-matchers/-/enzyme-matchers-7.1.2.tgz",
+ "integrity": "sha512-03WqAg2XDl7id9rARIO97HQ1JIw9F2heJ3R4meGu/13hx0ULTDEgl0E67MGl2Uq1jq1DyRnJfto1/VSzskdV5A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"circular-json-es6": "^2.0.1",
"deep-equal-ident": "^1.1.1"
},
"peerDependencies": {
- "enzyme": "3.x"
+ "enzyme": ">=3.4.0"
}
},
"node_modules/enzyme-shallow-equal": {
@@ -10289,8 +10640,7 @@
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
- "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "dev": true
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
},
"node_modules/events": {
"version": "3.3.0",
@@ -10307,19 +10657,20 @@
"dev": true
},
"node_modules/execa": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
- "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cross-spawn": "^7.0.0",
- "get-stream": "^5.0.0",
- "human-signals": "^1.1.1",
+ "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.0",
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
},
"engines": {
@@ -10387,55 +10738,22 @@
}
},
"node_modules/expect": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz",
- "integrity": "sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "ansi-styles": "^4.0.0",
- "jest-get-type": "^26.3.0",
- "jest-matcher-utils": "^26.6.2",
- "jest-message-util": "^26.6.2",
- "jest-regex-util": "^26.0.0"
+ "@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": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/expect/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,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/expect/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==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/expect/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
- },
"node_modules/exponential-backoff": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz",
@@ -10543,7 +10861,8 @@
"dev": true,
"engines": [
"node >=0.6.0"
- ]
+ ],
+ "license": "MIT"
},
"node_modules/fancy-log": {
"version": "1.3.3",
@@ -10716,6 +11035,7 @@
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
+ "license": "MIT",
"optional": true
},
"node_modules/filename-regex": {
@@ -10984,18 +11304,24 @@
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": "*"
}
},
- "node_modules/formatio": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz",
- "integrity": "sha512-YAF05v8+XCxAyHOdiiAmHdgCVPrWO8X744fYIPtBciIorh5LndWfi1gjeJ16sTbJhzek9kd+j3YByhohtz5Wmg==",
- "deprecated": "This package is unmaintained. Use @sinonjs/formatio instead",
+ "node_modules/form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "samsam": "1.x"
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
}
},
"node_modules/fragment-cache": {
@@ -11010,18 +11336,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/fs-access": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
- "integrity": "sha512-05cXDIwNbFaoFWaz5gNHlUTbH5whiss/hr/ibzPd4MH3cR4w0ZKeIPiVdbyJurg3O5r/Bjpvn9KOb1/rPMf3nA==",
- "dev": true,
- "dependencies": {
- "null-check": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/fs-extra": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
@@ -11063,6 +11377,26 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
+ "node_modules/fsevents": {
+ "version": "1.2.13",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
+ "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "nan": "^2.12.1"
+ },
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -11127,6 +11461,7 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -11179,25 +11514,14 @@
"node": ">=8.0.0"
}
},
- "node_modules/get-stdin": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
- "integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
"dev": true,
- "dependencies": {
- "pump": "^3.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -11233,6 +11557,7 @@
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0"
}
@@ -11431,7 +11756,8 @@
"resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz",
"integrity": "sha512-+xGQY0YyAWCnqy7Cd++hc2JqMYzlm0dG30Jd0beaA64sROr8C4nt8Yc9V5Ro3avlSUDTN0ulqP/VBKi1/lLygw==",
"dev": true,
- "optional": true
+ "optional": true,
+ "peer": true
},
"node_modules/gulp-shell": {
"version": "0.8.0",
@@ -11523,45 +11849,12 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"license": "0BSD"
},
- "node_modules/handlebars": {
- "version": "4.7.8",
- "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
- "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
- "dev": true,
- "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/uglify-js": {
- "version": "3.17.4",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
- "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
- "dev": true,
- "optional": true,
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": ">=4"
}
@@ -11572,6 +11865,7 @@
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"deprecated": "this library is no longer supported",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
@@ -11791,10 +12085,13 @@
}
},
"node_modules/hls.js": {
- "version": "1.5.17",
- "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.17.tgz",
- "integrity": "sha512-wA66nnYFvQa1o4DO/BFgLNRKnBTVXpNeldGRBJ2Y0SvFtdwvFKCbqa9zhHoZLoxHhZ+jYsj3aIBkWQQCPNOhMw==",
- "license": "Apache-2.0"
+ "version": "0.14.17",
+ "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-0.14.17.tgz",
+ "integrity": "sha512-25A7+m6qqp6UVkuzUQ//VVh2EEOPYlOBg32ypr34bcPO7liBMOkKFvbjbCBfiPAOTA/7BSx1Dujft3Th57WyFg==",
+ "dependencies": {
+ "eventemitter3": "^4.0.3",
+ "url-toolkit": "^2.1.6"
+ }
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
@@ -11829,21 +12126,47 @@
}
},
"node_modules/html-encoding-sniffer": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
- "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
+ "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==",
+ "license": "MIT",
"dependencies": {
- "whatwg-encoding": "^1.0.5"
+ "whatwg-encoding": "^2.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=12"
+ }
+ },
+ "node_modules/html-encoding-sniffer/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/html-encoding-sniffer/node_modules/whatwg-encoding": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+ "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/html-tags": {
"version": "3.3.1",
@@ -11921,11 +12244,12 @@
}
},
"node_modules/http-proxy-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
- "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
+ "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
+ "license": "MIT",
"dependencies": {
- "@tootallnate/once": "1",
+ "@tootallnate/once": "2",
"agent-base": "6",
"debug": "4"
},
@@ -11938,6 +12262,7 @@
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
@@ -11961,12 +12286,13 @@
}
},
"node_modules/human-signals": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
- "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=8.12.0"
+ "node": ">=10.17.0"
}
},
"node_modules/hyphenate-style-name": {
@@ -11978,6 +12304,7 @@
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -12469,6 +12796,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
"integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
+ "dev": true,
"dependencies": {
"ci-info": "^2.0.0"
},
@@ -12545,7 +12873,6 @@
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
"dev": true,
- "optional": true,
"bin": {
"is-docker": "cli.js"
},
@@ -12608,18 +12935,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-finite": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
- "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
@@ -12633,6 +12948,7 @@
"resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
"integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -12845,6 +13161,7 @@
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
},
@@ -12930,12 +13247,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-utf8": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
- "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==",
- "dev": true
- },
"node_modules/is-weakmap": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -12982,7 +13293,6 @@
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true,
- "optional": true,
"dependencies": {
"is-docker": "^2.0.0"
},
@@ -13034,33 +13344,8 @@
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
- "dev": true
- },
- "node_modules/istanbul": {
- "version": "0.4.5",
- "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz",
- "integrity": "sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==",
- "deprecated": "This module is no longer maintained, try this instead:\n npm i nyc\nVisit https://istanbul.js.org/integrations for other alternatives.",
- "dev": true,
- "dependencies": {
- "abbrev": "1.0.x",
- "async": "1.x",
- "escodegen": "1.8.x",
- "esprima": "2.7.x",
- "glob": "^5.0.15",
- "handlebars": "^4.0.1",
- "js-yaml": "3.x",
- "mkdirp": "0.5.x",
- "nopt": "3.x",
- "once": "1.x",
- "resolve": "1.1.x",
- "supports-color": "^3.1.0",
- "which": "^1.1.1",
- "wordwrap": "^1.0.0"
- },
- "bin": {
- "istanbul": "lib/cli.js"
- }
+ "dev": true,
+ "license": "MIT"
},
"node_modules/istanbul-lib-coverage": {
"version": "3.2.2",
@@ -13092,6 +13377,7 @@
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"istanbul-lib-coverage": "^3.0.0",
"make-dir": "^4.0.0",
@@ -13106,6 +13392,7 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -13115,6 +13402,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -13127,6 +13415,7 @@
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
"integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0",
@@ -13141,6 +13430,7 @@
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
"integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"html-escaper": "^2.0.0",
"istanbul-lib-report": "^3.0.0"
@@ -13149,270 +13439,264 @@
"node": ">=8"
}
},
- "node_modules/istanbul/node_modules/escodegen": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
- "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==",
+ "node_modules/iterator.prototype": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
+ "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
"dev": true,
+ "peer": true,
"dependencies": {
- "esprima": "^2.7.1",
- "estraverse": "^1.9.1",
- "esutils": "^2.0.2",
- "optionator": "^0.8.1"
- },
- "bin": {
- "escodegen": "bin/escodegen.js",
- "esgenerate": "bin/esgenerate.js"
+ "define-properties": "^1.2.1",
+ "get-intrinsic": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "reflect.getprototypeof": "^1.0.4",
+ "set-function-name": "^2.0.1"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
+ "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
},
"engines": {
- "node": ">=0.12.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
- "source-map": "~0.2.0"
+ "@pkgjs/parseargs": "^0.11.0"
}
},
- "node_modules/istanbul/node_modules/esprima": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
- "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==",
+ "node_modules/jasmine-core": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.6.4.tgz",
+ "integrity": "sha512-HUYBYi/hlSnCIr8QH9xuDBJUAzSHS0El3HxTomovIQcNxtbNhoOtKwpEZaB/jq3sfW/qyhqwW/VDUtoB2RZ4Tg==",
+ "dev": true
+ },
+ "node_modules/jasmine-jquery": {
+ "version": "2.1.1",
+ "resolved": "git+https://git@github.com/velesin/jasmine-jquery.git#ebad463d592d3fea00c69f26ea18a930e09c7b58",
+ "integrity": "sha512-sWMb40chzlUOKrHZCGpZoUrVnGm6khfL/fAMKO8vLtUR8yOmWIVVN7MRmep3/DSFhy1Hilon6qAH+UbLZgGG0w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
"bin": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
+ "jest": "bin/jest.js"
},
"engines": {
- "node": ">=0.10.0"
+ "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/istanbul/node_modules/estraverse": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
- "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==",
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/istanbul/node_modules/glob": {
- "version": "5.0.15",
- "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
- "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==",
+ "node_modules/jest-changed-files/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": {
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "2 || 3",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "yocto-queue": "^0.1.0"
},
"engines": {
- "node": "*"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/istanbul/node_modules/has-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
- "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/istanbul/node_modules/levn": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
- "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2"
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/istanbul/node_modules/optionator": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
- "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "node_modules/jest-circus/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,
+ "license": "MIT",
"dependencies": {
- "deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.6",
- "levn": "~0.3.0",
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2",
- "word-wrap": "~1.2.3"
+ "color-convert": "^2.0.1"
},
"engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/istanbul/node_modules/prelude-ls": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
- "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
- "dev": true,
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/istanbul/node_modules/resolve": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
- "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==",
- "dev": true
- },
- "node_modules/istanbul/node_modules/source-map": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
- "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "amdefine": ">=0.0.4"
+ "node": ">=8"
},
- "engines": {
- "node": ">=0.8.0"
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/istanbul/node_modules/supports-color": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
- "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==",
+ "node_modules/jest-circus/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,
+ "license": "MIT",
"dependencies": {
- "has-flag": "^1.0.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=0.8.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/istanbul/node_modules/type-check": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
- "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "node_modules/jest-circus/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==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "prelude-ls": "~1.1.2"
+ "color-name": "~1.1.4"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=7.0.0"
}
},
- "node_modules/istanbul/node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "node_modules/jest-circus/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,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
+ "license": "MIT"
},
- "node_modules/iterator.prototype": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
- "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "node_modules/jest-circus/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==",
"dev": true,
- "peer": true,
- "dependencies": {
- "define-properties": "^1.2.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "reflect.getprototypeof": "^1.0.4",
- "set-function-name": "^2.0.1"
- }
- },
- "node_modules/jackspeak": {
- "version": "2.3.6",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
- "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
+ "license": "MIT",
"engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
+ "node": ">=8"
}
},
- "node_modules/jasmine-core": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.6.4.tgz",
- "integrity": "sha512-HUYBYi/hlSnCIr8QH9xuDBJUAzSHS0El3HxTomovIQcNxtbNhoOtKwpEZaB/jq3sfW/qyhqwW/VDUtoB2RZ4Tg==",
- "dev": true
- },
- "node_modules/jasmine-jquery": {
- "version": "2.1.1",
- "resolved": "git+https://git@github.com/velesin/jasmine-jquery.git#ebad463d592d3fea00c69f26ea18a930e09c7b58",
- "integrity": "sha512-sWMb40chzlUOKrHZCGpZoUrVnGm6khfL/fAMKO8vLtUR8yOmWIVVN7MRmep3/DSFhy1Hilon6qAH+UbLZgGG0w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/jest": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest/-/jest-26.6.3.tgz",
- "integrity": "sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==",
+ "node_modules/jest-circus/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": {
- "@jest/core": "^26.6.3",
- "import-local": "^3.0.2",
- "jest-cli": "^26.6.3"
- },
- "bin": {
- "jest": "bin/jest.js"
+ "yocto-queue": "^0.1.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-changed-files": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.6.2.tgz",
- "integrity": "sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ==",
+ "node_modules/jest-circus/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",
"dependencies": {
- "@jest/types": "^26.6.2",
- "execa": "^4.0.0",
- "throat": "^5.0.0"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": ">=8"
}
},
"node_modules/jest-cli": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.6.3.tgz",
- "integrity": "sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/core": "^26.6.3",
- "@jest/test-result": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@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",
- "graceful-fs": "^4.2.4",
"import-local": "^3.0.2",
- "is-ci": "^2.0.0",
- "jest-config": "^26.6.3",
- "jest-util": "^26.6.2",
- "jest-validate": "^26.6.2",
- "prompts": "^2.0.1",
- "yargs": "^15.4.1"
+ "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": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
}
},
"node_modules/jest-cli/node_modules/ansi-styles": {
@@ -13486,37 +13770,46 @@
}
},
"node_modules/jest-config": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.6.3.tgz",
- "integrity": "sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/core": "^7.1.0",
- "@jest/test-sequencer": "^26.6.3",
- "@jest/types": "^26.6.2",
- "babel-jest": "^26.6.3",
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
"chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
"deepmerge": "^4.2.2",
- "glob": "^7.1.1",
- "graceful-fs": "^4.2.4",
- "jest-environment-jsdom": "^26.6.2",
- "jest-environment-node": "^26.6.2",
- "jest-get-type": "^26.3.0",
- "jest-jasmine2": "^26.6.3",
- "jest-regex-util": "^26.0.0",
- "jest-resolve": "^26.6.2",
- "jest-util": "^26.6.2",
- "jest-validate": "^26.6.2",
- "micromatch": "^4.0.2",
- "pretty-format": "^26.6.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": ">= 10.14.2"
+ "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
}
@@ -13527,6 +13820,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -13542,6 +13836,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -13553,11 +13848,28 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/jest-config/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/jest-config/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==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -13569,13 +13881,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-config/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -13585,6 +13899,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -13593,18 +13908,19 @@
}
},
"node_modules/jest-diff": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.6.2.tgz",
- "integrity": "sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"chalk": "^4.0.0",
- "diff-sequences": "^26.6.2",
- "jest-get-type": "^26.3.0",
- "pretty-format": "^26.6.2"
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-diff/node_modules/ansi-styles": {
@@ -13612,6 +13928,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -13627,6 +13944,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -13643,6 +13961,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -13654,13 +13973,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-diff/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -13670,6 +13991,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -13678,31 +14000,33 @@
}
},
"node_modules/jest-docblock": {
- "version": "26.0.0",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz",
- "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"detect-newline": "^3.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-each": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.6.2.tgz",
- "integrity": "sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
+ "@jest/types": "^29.6.3",
"chalk": "^4.0.0",
- "jest-get-type": "^26.3.0",
- "jest-util": "^26.6.2",
- "pretty-format": "^26.6.2"
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-each/node_modules/ansi-styles": {
@@ -13710,6 +14034,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -13725,6 +14050,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -13741,6 +14067,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -13752,13 +14079,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-each/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -13768,6 +14097,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -13776,12 +14106,13 @@
}
},
"node_modules/jest-environment-enzyme": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-6.1.2.tgz",
- "integrity": "sha512-WHeBKgBYOdryuOTEoK55lJwjg7Raery1OgXHLwukI3mSYgOkm2UrCDDT+vneqVgy7F8KuRHyStfD+TC/m2b7Kg==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/jest-environment-enzyme/-/jest-environment-enzyme-7.1.2.tgz",
+ "integrity": "sha512-3tfaYAzO7qZSRrv+srQnfK16Vu5XwH/pHi8FpoqSHjKKngbHzXf7aBCBuWh8y3w0OtknHRfDMFrC60Khj+g1hA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "jest-environment-jsdom": "^22.4.1"
+ "jest-environment-jsdom": "^24.0.0"
},
"peerDependencies": {
"enzyme": "3.x",
@@ -13789,89 +14120,295 @@
"react": "^0.13.0 || ^0.14.0 || ^15.0.0 || >=16.x"
}
},
- "node_modules/jest-environment-enzyme/node_modules/acorn": {
- "version": "5.7.4",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
- "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",
+ "node_modules/jest-environment-enzyme/node_modules/@jest/console": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz",
+ "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==",
"dev": true,
- "bin": {
- "acorn": "bin/acorn"
+ "license": "MIT",
+ "dependencies": {
+ "@jest/source-map": "^24.9.0",
+ "chalk": "^2.0.1",
+ "slash": "^2.0.0"
},
"engines": {
- "node": ">=0.4.0"
+ "node": ">= 6"
}
},
- "node_modules/jest-environment-enzyme/node_modules/acorn-globals": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
- "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
+ "node_modules/jest-environment-enzyme/node_modules/@jest/environment": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz",
+ "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "acorn": "^6.0.1",
- "acorn-walk": "^6.0.1"
- }
- },
- "node_modules/jest-environment-enzyme/node_modules/acorn-globals/node_modules/acorn": {
- "version": "6.4.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
- "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/transform": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "jest-mock": "^24.9.0"
},
"engines": {
- "node": ">=0.4.0"
+ "node": ">= 6"
}
},
- "node_modules/jest-environment-enzyme/node_modules/acorn-walk": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
- "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
+ "node_modules/jest-environment-enzyme/node_modules/@jest/fake-timers": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz",
+ "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^24.9.0",
+ "jest-message-util": "^24.9.0",
+ "jest-mock": "^24.9.0"
+ },
"engines": {
- "node": ">=0.4.0"
+ "node": ">= 6"
}
},
- "node_modules/jest-environment-enzyme/node_modules/braces": {
- "version": "1.8.5",
- "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
- "integrity": "sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==",
+ "node_modules/jest-environment-enzyme/node_modules/@jest/source-map": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz",
+ "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "expand-range": "^1.8.1",
- "preserve": "^0.2.0",
- "repeat-element": "^1.1.2"
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.1.15",
+ "source-map": "^0.6.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/@jest/test-result": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz",
+ "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/console": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/istanbul-lib-coverage": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/@jest/transform": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz",
+ "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.1.0",
+ "@jest/types": "^24.9.0",
+ "babel-plugin-istanbul": "^5.1.0",
+ "chalk": "^2.0.1",
+ "convert-source-map": "^1.4.0",
+ "fast-json-stable-stringify": "^2.0.0",
+ "graceful-fs": "^4.1.15",
+ "jest-haste-map": "^24.9.0",
+ "jest-regex-util": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "pirates": "^4.0.1",
+ "realpath-native": "^1.1.0",
+ "slash": "^2.0.0",
+ "source-map": "^0.6.1",
+ "write-file-atomic": "2.4.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/@jest/types": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz",
+ "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^1.1.1",
+ "@types/yargs": "^13.0.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/@types/istanbul-reports": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz",
+ "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*",
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/@types/stack-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
+ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-environment-enzyme/node_modules/@types/yargs": {
+ "version": "13.0.12",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz",
+ "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/acorn": {
+ "version": "5.7.4",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz",
+ "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/acorn-globals": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-4.3.4.tgz",
+ "integrity": "sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^6.0.1",
+ "acorn-walk": "^6.0.1"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/acorn-globals/node_modules/acorn": {
+ "version": "6.4.2",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
+ "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/acorn-walk": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
+ "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/callsites": {
+ "node_modules/jest-environment-enzyme/node_modules/anymatch": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
- "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "micromatch": "^3.1.4",
+ "normalize-path": "^2.1.1"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/arr-diff": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+ "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=0.10.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/ci-info": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
- "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
- "dev": true
+ "node_modules/jest-environment-enzyme/node_modules/array-unique": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+ "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/babel-plugin-istanbul": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz",
+ "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "find-up": "^3.0.0",
+ "istanbul-lib-instrument": "^3.3.0",
+ "test-exclude": "^5.2.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/braces": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+ "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "arr-flatten": "^1.1.0",
+ "array-unique": "^0.3.2",
+ "extend-shallow": "^2.0.1",
+ "fill-range": "^4.0.0",
+ "isobject": "^3.0.1",
+ "repeat-element": "^1.1.2",
+ "snapdragon": "^0.8.1",
+ "snapdragon-node": "^2.0.1",
+ "split-string": "^3.0.2",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/braces/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
"node_modules/jest-environment-enzyme/node_modules/cssom": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz",
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-environment-enzyme/node_modules/cssstyle": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz",
"integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"cssom": "0.3.x"
}
@@ -13881,6 +14418,7 @@
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-1.1.0.tgz",
"integrity": "sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"abab": "^2.0.0",
"whatwg-mimetype": "^2.2.0",
@@ -13892,18 +14430,30 @@
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz",
"integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"lodash.sortby": "^4.7.0",
"tr46": "^1.0.1",
"webidl-conversions": "^4.0.2"
}
},
+ "node_modules/jest-environment-enzyme/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
"node_modules/jest-environment-enzyme/node_modules/domexception": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
"integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
"deprecated": "Use your platform's native DOMException instead",
"dev": true,
+ "license": "MIT",
"dependencies": {
"webidl-conversions": "^4.0.2"
}
@@ -13913,6 +14463,7 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -13922,6 +14473,7 @@
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
"integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^4.2.0",
@@ -13944,107 +14496,366 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/expand-range": {
- "version": "1.8.2",
- "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
- "integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==",
+ "node_modules/jest-environment-enzyme/node_modules/expand-brackets": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+ "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "fill-range": "^2.1.0"
+ "debug": "^2.3.3",
+ "define-property": "^0.2.5",
+ "extend-shallow": "^2.0.1",
+ "posix-character-classes": "^0.1.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/html-encoding-sniffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
- "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
- "dev": true,
- "dependencies": {
- "whatwg-encoding": "^1.0.1"
- }
- },
- "node_modules/jest-environment-enzyme/node_modules/is-ci": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
- "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
+ "node_modules/jest-environment-enzyme/node_modules/expand-brackets/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ci-info": "^1.5.0"
+ "is-descriptor": "^0.1.0"
},
- "bin": {
- "is-ci": "bin.js"
- }
- },
- "node_modules/jest-environment-enzyme/node_modules/is-extglob": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
- "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/is-glob": {
+ "node_modules/jest-environment-enzyme/node_modules/expand-brackets/node_modules/extend-shallow": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
- "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-extglob": "^1.0.0"
+ "is-extendable": "^0.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/jest-environment-jsdom": {
- "version": "22.4.3",
- "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-22.4.3.tgz",
- "integrity": "sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w==",
+ "node_modules/jest-environment-enzyme/node_modules/expand-brackets/node_modules/is-descriptor": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.7.tgz",
+ "integrity": "sha512-C3grZTvObeN1xud4cRWl366OMXZTj0+HGyk4hvfpx4ZHt1Pb60ANSXqCK7pdOTeUQpRzECBSTphqvD7U+l22Eg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "jest-mock": "^22.4.3",
- "jest-util": "^22.4.3",
- "jsdom": "^11.5.1"
+ "is-accessor-descriptor": "^1.0.1",
+ "is-data-descriptor": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/jest-environment-enzyme/node_modules/jest-message-util": {
- "version": "22.4.3",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-22.4.3.tgz",
- "integrity": "sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA==",
+ "node_modules/jest-environment-enzyme/node_modules/extglob": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+ "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.0.0-beta.35",
+ "array-unique": "^0.3.2",
+ "define-property": "^1.0.0",
+ "expand-brackets": "^2.1.4",
+ "extend-shallow": "^2.0.1",
+ "fragment-cache": "^0.2.1",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/extglob/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/extglob/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/fill-range": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+ "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "extend-shallow": "^2.0.1",
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1",
+ "to-regex-range": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/fill-range/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/html-encoding-sniffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz",
+ "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "whatwg-encoding": "^1.0.1"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "kind-of": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/is-number/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/istanbul-lib-coverage": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+ "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/istanbul-lib-instrument": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+ "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@babel/generator": "^7.4.0",
+ "@babel/parser": "^7.4.3",
+ "@babel/template": "^7.4.0",
+ "@babel/traverse": "^7.4.3",
+ "@babel/types": "^7.4.0",
+ "istanbul-lib-coverage": "^2.0.5",
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/jest-environment-jsdom": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz",
+ "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^24.9.0",
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "jest-mock": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jsdom": "^11.5.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/jest-haste-map": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz",
+ "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^24.9.0",
+ "anymatch": "^2.0.0",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.1.15",
+ "invariant": "^2.2.4",
+ "jest-serializer": "^24.9.0",
+ "jest-util": "^24.9.0",
+ "jest-worker": "^24.9.0",
+ "micromatch": "^3.1.10",
+ "sane": "^4.0.3",
+ "walker": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "optionalDependencies": {
+ "fsevents": "^1.2.7"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/jest-message-util": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz",
+ "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "@types/stack-utils": "^1.0.1",
"chalk": "^2.0.1",
- "micromatch": "^2.3.11",
- "slash": "^1.0.0",
+ "micromatch": "^3.1.10",
+ "slash": "^2.0.0",
"stack-utils": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/jest-environment-enzyme/node_modules/jest-mock": {
- "version": "22.4.3",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-22.4.3.tgz",
- "integrity": "sha512-+4R6mH5M1G4NK16CKg9N1DtCaFmuxhcIqF4lQK/Q1CIotqMs/XBemfpDPeVZBFow6iyUNu6EBT9ugdNOTT5o5Q==",
- "dev": true
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz",
+ "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^24.9.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/jest-regex-util": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz",
+ "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/jest-serializer": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz",
+ "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
},
"node_modules/jest-environment-enzyme/node_modules/jest-util": {
- "version": "22.4.3",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-22.4.3.tgz",
- "integrity": "sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ==",
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz",
+ "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "callsites": "^2.0.0",
+ "@jest/console": "^24.9.0",
+ "@jest/fake-timers": "^24.9.0",
+ "@jest/source-map": "^24.9.0",
+ "@jest/test-result": "^24.9.0",
+ "@jest/types": "^24.9.0",
+ "callsites": "^3.0.0",
"chalk": "^2.0.1",
- "graceful-fs": "^4.1.11",
- "is-ci": "^1.0.10",
- "jest-message-util": "^22.4.3",
+ "graceful-fs": "^4.1.15",
+ "is-ci": "^2.0.0",
"mkdirp": "^0.5.1",
+ "slash": "^2.0.0",
"source-map": "^0.6.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/jest-worker": {
+ "version": "24.9.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz",
+ "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "merge-stream": "^2.0.0",
+ "supports-color": "^6.1.0"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/jest-environment-enzyme/node_modules/jsdom": {
@@ -14052,6 +14863,7 @@
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz",
"integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"abab": "^2.0.0",
"acorn": "^5.5.3",
@@ -14081,23 +14893,12 @@
"xml-name-validator": "^3.0.0"
}
},
- "node_modules/jest-environment-enzyme/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/jest-environment-enzyme/node_modules/levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2"
@@ -14106,102 +14907,288 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/jest-environment-enzyme/node_modules/load-json-file": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
+ "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "parse-json": "^4.0.0",
+ "pify": "^3.0.0",
+ "strip-bom": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/jest-environment-enzyme/node_modules/micromatch": {
- "version": "2.3.11",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
- "integrity": "sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==",
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
+ "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "arr-diff": "^2.0.0",
- "array-unique": "^0.2.1",
- "braces": "^1.8.2",
- "expand-brackets": "^0.1.4",
- "extglob": "^0.3.1",
- "filename-regex": "^2.0.0",
- "is-extglob": "^1.0.0",
- "is-glob": "^2.0.1",
- "kind-of": "^3.0.2",
- "normalize-path": "^2.0.1",
- "object.omit": "^2.0.0",
- "parse-glob": "^3.0.4",
- "regex-cache": "^0.4.2"
+ "arr-diff": "^4.0.0",
+ "array-unique": "^0.3.2",
+ "braces": "^2.3.1",
+ "define-property": "^2.0.2",
+ "extend-shallow": "^3.0.2",
+ "extglob": "^2.0.4",
+ "fragment-cache": "^0.2.1",
+ "kind-of": "^6.0.2",
+ "nanomatch": "^1.2.9",
+ "object.pick": "^1.3.0",
+ "regex-not": "^1.0.0",
+ "snapdragon": "^0.8.1",
+ "to-regex": "^3.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/jest-environment-enzyme/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/jest-environment-enzyme/node_modules/normalize-path": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"remove-trailing-separator": "^1.0.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/optionator": {
+ "version": "0.8.3",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
+ "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "~0.1.3",
+ "fast-levenshtein": "~2.0.6",
+ "levn": "~0.3.0",
+ "prelude-ls": "~1.1.2",
+ "type-check": "~0.3.2",
+ "word-wrap": "~1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/parse5": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
+ "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/jest-environment-enzyme/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/path-type": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/pify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+ "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/prelude-ls": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
+ "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/read-pkg": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
+ "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "load-json-file": "^4.0.0",
+ "normalize-package-data": "^2.3.2",
+ "path-type": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/read-pkg-up": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz",
+ "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^3.0.0",
+ "read-pkg": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/jest-environment-enzyme/node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
}
},
- "node_modules/jest-environment-enzyme/node_modules/optionator": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
- "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
+ "node_modules/jest-environment-enzyme/node_modules/stack-utils": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz",
+ "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.6",
- "levn": "~0.3.0",
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2",
- "word-wrap": "~1.2.3"
+ "escape-string-regexp": "^2.0.0"
},
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=8"
}
},
- "node_modules/jest-environment-enzyme/node_modules/parse5": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz",
- "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==",
- "dev": true
- },
- "node_modules/jest-environment-enzyme/node_modules/prelude-ls": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
- "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
+ "node_modules/jest-environment-enzyme/node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=4"
}
},
- "node_modules/jest-environment-enzyme/node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "node_modules/jest-environment-enzyme/node_modules/supports-color": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+ "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
"engines": {
"node": ">=6"
}
},
- "node_modules/jest-environment-enzyme/node_modules/slash": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
- "integrity": "sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
+ "node_modules/jest-environment-enzyme/node_modules/test-exclude": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz",
+ "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==",
"dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3",
+ "minimatch": "^3.0.4",
+ "read-pkg-up": "^4.0.0",
+ "require-main-filename": "^2.0.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6"
}
},
- "node_modules/jest-environment-enzyme/node_modules/stack-utils": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz",
- "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==",
+ "node_modules/jest-environment-enzyme/node_modules/to-regex-range": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
+ "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "escape-string-regexp": "^2.0.0"
+ "is-number": "^3.0.0",
+ "repeat-string": "^1.6.1"
},
"engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
"node_modules/jest-environment-enzyme/node_modules/tough-cookie": {
@@ -14209,6 +15196,7 @@
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
@@ -14222,6 +15210,7 @@
"resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz",
"integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"punycode": "^2.1.0"
}
@@ -14231,6 +15220,7 @@
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"prelude-ls": "~1.1.2"
},
@@ -14242,239 +15232,183 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
"integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==",
- "dev": true
+ "dev": true,
+ "license": "BSD-2-Clause"
},
"node_modules/jest-environment-enzyme/node_modules/whatwg-url": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz",
"integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"lodash.sortby": "^4.7.0",
"tr46": "^1.0.1",
"webidl-conversions": "^4.0.2"
}
},
+ "node_modules/jest-environment-enzyme/node_modules/write-file-atomic": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz",
+ "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
"node_modules/jest-environment-enzyme/node_modules/ws": {
- "version": "5.2.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.3.tgz",
- "integrity": "sha512-jZArVERrMsKUatIdnLzqvcfydI85dvd/Fp1u/VOpfdDWQ4c9qWXe+VIeAbQ5FrDwciAkr+lzofXLz3Kuf26AOA==",
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.4.tgz",
+ "integrity": "sha512-fFCejsuC8f9kOSu9FYaOw8CdO68O3h5v0lg4p74o8JqWpwTf9tniOD+nOB78aWoVSS6WptVUmDrp/KPsMVBWFQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"async-limiter": "~1.0.0"
}
},
"node_modules/jest-environment-jsdom": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz",
- "integrity": "sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz",
+ "integrity": "sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==",
+ "license": "MIT",
"dependencies": {
- "@jest/environment": "^26.6.2",
- "@jest/fake-timers": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@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": "^26.6.2",
- "jest-util": "^26.6.2",
- "jsdom": "^16.4.0"
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jsdom": "^20.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "canvas": "^2.5.0"
+ },
+ "peerDependenciesMeta": {
+ "canvas": {
+ "optional": true
+ }
}
},
"node_modules/jest-environment-node": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.6.2.tgz",
- "integrity": "sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/environment": "^26.6.2",
- "@jest/fake-timers": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
- "jest-mock": "^26.6.2",
- "jest-util": "^26.6.2"
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-enzyme": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-6.1.2.tgz",
- "integrity": "sha512-+ds7r2ru3QkNJxelQ2tnC6d33pjUSsZHPD3v4TlnHlNMuGX3UKdxm5C46yZBvJICYBvIF+RFKBhLMM4evNM95Q==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-7.1.2.tgz",
+ "integrity": "sha512-j+jkph3t5hGBS12eOldpfsnERYRCHi4c/0KWPMnqRPoJJXvCpLIc5th1MHl0xDznQDXVU0AHUXg3rqMrf8vGpA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "enzyme-matchers": "^6.1.2",
+ "enzyme-matchers": "^7.1.2",
"enzyme-to-json": "^3.3.0",
- "jest-environment-enzyme": "^6.1.2"
+ "jest-environment-enzyme": "^7.1.2"
},
"peerDependencies": {
- "enzyme": "3.x",
+ "enzyme": ">=3.4.0",
"jest": ">=22.0.0"
}
},
"node_modules/jest-get-type": {
- "version": "26.3.0",
- "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz",
- "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-haste-map": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.6.2.tgz",
- "integrity": "sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "@types/graceful-fs": "^4.1.2",
+ "@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.4",
- "jest-regex-util": "^26.0.0",
- "jest-serializer": "^26.6.2",
- "jest-util": "^26.6.2",
- "jest-worker": "^26.6.2",
- "micromatch": "^4.0.2",
- "sane": "^4.0.3",
- "walker": "^1.0.7"
+ "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.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
},
"optionalDependencies": {
- "fsevents": "^2.1.2"
- }
- },
- "node_modules/jest-jasmine2": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz",
- "integrity": "sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==",
- "dev": true,
- "dependencies": {
- "@babel/traverse": "^7.1.0",
- "@jest/environment": "^26.6.2",
- "@jest/source-map": "^26.6.2",
- "@jest/test-result": "^26.6.2",
- "@jest/types": "^26.6.2",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "co": "^4.6.0",
- "expect": "^26.6.2",
- "is-generator-fn": "^2.0.0",
- "jest-each": "^26.6.2",
- "jest-matcher-utils": "^26.6.2",
- "jest-message-util": "^26.6.2",
- "jest-runtime": "^26.6.3",
- "jest-snapshot": "^26.6.2",
- "jest-util": "^26.6.2",
- "pretty-format": "^26.6.2",
- "throat": "^5.0.0"
- },
- "engines": {
- "node": ">= 10.14.2"
- }
- },
- "node_modules/jest-jasmine2/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,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/jest-jasmine2/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,
- "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/jest-jasmine2/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==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/jest-jasmine2/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
- },
- "node_modules/jest-jasmine2/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==",
- "dev": true,
- "engines": {
- "node": ">=8"
+ "fsevents": "^2.3.2"
}
},
- "node_modules/jest-jasmine2/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==",
+ "node_modules/jest-haste-map/node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
"engines": {
- "node": ">=8"
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/jest-leak-detector": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz",
- "integrity": "sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "jest-get-type": "^26.3.0",
- "pretty-format": "^26.6.2"
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-matcher-utils": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz",
- "integrity": "sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"chalk": "^4.0.0",
- "jest-diff": "^26.6.2",
- "jest-get-type": "^26.3.0",
- "pretty-format": "^26.6.2"
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-matcher-utils/node_modules/ansi-styles": {
@@ -14482,6 +15416,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -14497,6 +15432,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -14513,6 +15449,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -14524,13 +15461,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-matcher-utils/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -14540,6 +15479,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -14548,28 +15488,30 @@
}
},
"node_modules/jest-message-util": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.6.2.tgz",
- "integrity": "sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.0.0",
- "@jest/types": "^26.6.2",
+ "@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.4",
- "micromatch": "^4.0.2",
- "pretty-format": "^26.6.2",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
"slash": "^3.0.0",
- "stack-utils": "^2.0.2"
+ "stack-utils": "^2.0.3"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-message-util/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==",
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -14584,6 +15526,7 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -14599,6 +15542,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -14609,12 +15553,14 @@
"node_modules/jest-message-util/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=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/jest-message-util/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==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -14623,6 +15569,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -14631,15 +15578,17 @@
}
},
"node_modules/jest-mock": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.6.2.tgz",
- "integrity": "sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "@types/node": "*"
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-pnp-resolver": {
@@ -14647,6 +15596,7 @@
"resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
"integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
},
@@ -14660,45 +15610,48 @@
}
},
"node_modules/jest-regex-util": {
- "version": "26.0.0",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz",
- "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==",
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-resolve": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.6.2.tgz",
- "integrity": "sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
"chalk": "^4.0.0",
- "graceful-fs": "^4.2.4",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
"jest-pnp-resolver": "^1.2.2",
- "jest-util": "^26.6.2",
- "read-pkg-up": "^7.0.1",
- "resolve": "^1.18.1",
+ "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": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-resolve-dependencies": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz",
- "integrity": "sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "jest-regex-util": "^26.0.0",
- "jest-snapshot": "^26.6.2"
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-resolve/node_modules/ansi-styles": {
@@ -14706,6 +15659,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -14721,6 +15675,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -14737,6 +15692,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -14748,13 +15704,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-resolve/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -14764,6 +15722,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -14772,34 +15731,36 @@
}
},
"node_modules/jest-runner": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.6.3.tgz",
- "integrity": "sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/console": "^26.6.2",
- "@jest/environment": "^26.6.2",
- "@jest/test-result": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@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.7.1",
- "exit": "^0.1.2",
- "graceful-fs": "^4.2.4",
- "jest-config": "^26.6.3",
- "jest-docblock": "^26.0.0",
- "jest-haste-map": "^26.6.2",
- "jest-leak-detector": "^26.6.2",
- "jest-message-util": "^26.6.2",
- "jest-resolve": "^26.6.2",
- "jest-runtime": "^26.6.3",
- "jest-util": "^26.6.2",
- "jest-worker": "^26.6.2",
- "source-map-support": "^0.5.6",
- "throat": "^5.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": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-runner/node_modules/ansi-styles": {
@@ -14807,6 +15768,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -14822,6 +15784,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -14838,6 +15801,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -14849,22 +15813,52 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-runner/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
+ "node_modules/jest-runner/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": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/jest-runner/node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
"node_modules/jest-runner/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",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -14873,44 +15867,37 @@
}
},
"node_modules/jest-runtime": {
- "version": "26.6.3",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.6.3.tgz",
- "integrity": "sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==",
- "dev": true,
- "dependencies": {
- "@jest/console": "^26.6.2",
- "@jest/environment": "^26.6.2",
- "@jest/fake-timers": "^26.6.2",
- "@jest/globals": "^26.6.2",
- "@jest/source-map": "^26.6.2",
- "@jest/test-result": "^26.6.2",
- "@jest/transform": "^26.6.2",
- "@jest/types": "^26.6.2",
- "@types/yargs": "^15.0.0",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
"chalk": "^4.0.0",
- "cjs-module-lexer": "^0.6.0",
+ "cjs-module-lexer": "^1.0.0",
"collect-v8-coverage": "^1.0.0",
- "exit": "^0.1.2",
"glob": "^7.1.3",
- "graceful-fs": "^4.2.4",
- "jest-config": "^26.6.3",
- "jest-haste-map": "^26.6.2",
- "jest-message-util": "^26.6.2",
- "jest-mock": "^26.6.2",
- "jest-regex-util": "^26.0.0",
- "jest-resolve": "^26.6.2",
- "jest-snapshot": "^26.6.2",
- "jest-util": "^26.6.2",
- "jest-validate": "^26.6.2",
+ "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",
- "yargs": "^15.4.1"
- },
- "bin": {
- "jest-runtime": "bin/jest-runtime.js"
+ "strip-bom": "^4.0.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-runtime/node_modules/ansi-styles": {
@@ -14918,6 +15905,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -14933,6 +15921,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -14949,6 +15938,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -14960,13 +15950,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-runtime/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -14976,6 +15968,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -14983,44 +15976,36 @@
"node": ">=8"
}
},
- "node_modules/jest-serializer": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.6.2.tgz",
- "integrity": "sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "graceful-fs": "^4.2.4"
- },
- "engines": {
- "node": ">= 10.14.2"
- }
- },
"node_modules/jest-snapshot": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.6.2.tgz",
- "integrity": "sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.0.0",
- "@jest/types": "^26.6.2",
- "@types/babel__traverse": "^7.0.4",
- "@types/prettier": "^2.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": "^26.6.2",
- "graceful-fs": "^4.2.4",
- "jest-diff": "^26.6.2",
- "jest-get-type": "^26.3.0",
- "jest-haste-map": "^26.6.2",
- "jest-matcher-utils": "^26.6.2",
- "jest-message-util": "^26.6.2",
- "jest-resolve": "^26.6.2",
+ "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": "^26.6.2",
- "semver": "^7.3.2"
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-snapshot/node_modules/ansi-styles": {
@@ -15028,6 +16013,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -15043,6 +16029,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -15059,6 +16046,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -15070,37 +16058,25 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-snapshot/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/jest-snapshot/node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.6.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
- "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -15113,6 +16089,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -15120,32 +16097,28 @@
"node": ">=8"
}
},
- "node_modules/jest-snapshot/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
- },
"node_modules/jest-util": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.6.2.tgz",
- "integrity": "sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"chalk": "^4.0.0",
- "graceful-fs": "^4.2.4",
- "is-ci": "^2.0.0",
- "micromatch": "^4.0.2"
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-util/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==",
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -15160,6 +16133,7 @@
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -15171,10 +16145,26 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/jest-util/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/jest-util/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==",
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -15185,12 +16175,14 @@
"node_modules/jest-util/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=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/jest-util/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==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -15199,6 +16191,7 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -15207,20 +16200,21 @@
}
},
"node_modules/jest-validate": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.6.2.tgz",
- "integrity": "sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "camelcase": "^6.0.0",
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
"chalk": "^4.0.0",
- "jest-get-type": "^26.3.0",
+ "jest-get-type": "^29.6.3",
"leven": "^3.1.0",
- "pretty-format": "^26.6.2"
+ "pretty-format": "^29.7.0"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-validate/node_modules/ansi-styles": {
@@ -15228,6 +16222,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -15243,6 +16238,7 @@
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
@@ -15255,6 +16251,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -15271,6 +16268,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -15282,13 +16280,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-validate/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -15298,6 +16298,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -15306,21 +16307,23 @@
}
},
"node_modules/jest-watcher": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.6.2.tgz",
- "integrity": "sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/test-result": "^26.6.2",
- "@jest/types": "^26.6.2",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
"@types/node": "*",
"ansi-escapes": "^4.2.1",
"chalk": "^4.0.0",
- "jest-util": "^26.6.2",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
"string-length": "^4.0.1"
},
"engines": {
- "node": ">= 10.14.2"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-watcher/node_modules/ansi-styles": {
@@ -15328,6 +16331,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -15343,6 +16347,7 @@
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
@@ -15359,6 +16364,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -15370,13 +16376,15 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jest-watcher/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==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -15386,6 +16394,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -15394,17 +16403,19 @@
}
},
"node_modules/jest-worker": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
- "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*",
+ "jest-util": "^29.7.0",
"merge-stream": "^2.0.0",
- "supports-color": "^7.0.0"
+ "supports-color": "^8.0.0"
},
"engines": {
- "node": ">= 10.13.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/jest-worker/node_modules/has-flag": {
@@ -15412,20 +16423,25 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/jest-worker/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==",
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/jquery": {
@@ -15484,40 +16500,40 @@
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/jsdom": {
- "version": "16.7.0",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz",
- "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==",
- "dependencies": {
- "abab": "^2.0.5",
- "acorn": "^8.2.4",
- "acorn-globals": "^6.0.0",
- "cssom": "^0.4.4",
+ "version": "20.0.3",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
+ "integrity": "sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==",
+ "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": "^2.0.0",
- "decimal.js": "^10.2.1",
- "domexception": "^2.0.1",
+ "data-urls": "^3.0.2",
+ "decimal.js": "^10.4.2",
+ "domexception": "^4.0.0",
"escodegen": "^2.0.0",
- "form-data": "^3.0.0",
- "html-encoding-sniffer": "^2.0.1",
- "http-proxy-agent": "^4.0.1",
- "https-proxy-agent": "^5.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.0",
- "parse5": "6.0.1",
- "saxes": "^5.0.1",
+ "nwsapi": "^2.2.2",
+ "parse5": "^7.1.1",
+ "saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
- "tough-cookie": "^4.0.0",
- "w3c-hr-time": "^1.0.2",
- "w3c-xmlserializer": "^2.0.0",
- "webidl-conversions": "^6.1.0",
- "whatwg-encoding": "^1.0.5",
- "whatwg-mimetype": "^2.3.0",
- "whatwg-url": "^8.5.0",
- "ws": "^7.4.6",
- "xml-name-validator": "^3.0.0"
+ "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": ">=10"
+ "node": ">=14"
},
"peerDependencies": {
"canvas": "^2.5.0"
@@ -15529,9 +16545,10 @@
}
},
"node_modules/jsdom/node_modules/form-data": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz",
- "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -15541,10 +16558,47 @@
"node": ">= 6"
}
},
- "node_modules/jsdom/node_modules/parse5": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
- "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
+ "node_modules/jsdom/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jsdom/node_modules/whatwg-encoding": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
+ "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jsdom/node_modules/whatwg-mimetype": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",
+ "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jsdom/node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12"
+ }
},
"node_modules/jsesc": {
"version": "3.0.2",
@@ -15709,6 +16763,13 @@
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true
},
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
+ "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",
@@ -15718,7 +16779,8 @@
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
- "dev": true
+ "dev": true,
+ "license": "(AFL-2.1 OR BSD-3-Clause)"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
@@ -15758,7 +16820,8 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/json2mq": {
"version": "0.2.0",
@@ -15817,6 +16880,7 @@
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
@@ -15896,6 +16960,13 @@
"safe-buffer": "~5.1.0"
}
},
+ "node_modules/just-extend": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz",
+ "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/karma": {
"version": "0.13.22",
"resolved": "https://registry.npmjs.org/karma/-/karma-0.13.22.tgz",
@@ -15927,244 +16998,80 @@
"useragent": "^2.1.6"
},
"bin": {
- "karma": "bin/karma"
- },
- "engines": {
- "node": "0.10 || 0.12 || 4 || 5"
- }
- },
- "node_modules/karma-chrome-launcher": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-0.2.3.tgz",
- "integrity": "sha512-AiMVR7eY9MKLF3EVwgB08TyiHCBIUXAypgxcWJeOSUHB7QBvB2ebUr8tl0C0YwPS2Ce+oBAbR/SQkG46aLfJAA==",
- "dev": true,
- "dependencies": {
- "fs-access": "^1.0.0",
- "which": "^1.2.1"
- }
- },
- "node_modules/karma-chrome-launcher/node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
- }
- },
- "node_modules/karma-coverage": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-0.5.5.tgz",
- "integrity": "sha512-nC6B3DdP0IhNVUH25kx7ztVBT5belTC4MQ2tDhvvGMUhrpUPA3vUipBC9XqE9WqfHQDjRfQdn4z7Y0iKC6axBA==",
- "dev": true,
- "dependencies": {
- "dateformat": "^1.0.6",
- "istanbul": "^0.4.0",
- "minimatch": "^3.0.0",
- "source-map": "^0.5.1"
- }
- },
- "node_modules/karma-coverage/node_modules/camelcase": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
- "integrity": "sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/camelcase-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
- "integrity": "sha512-bA/Z/DERHKqoEOrp+qeGKw1QlvEQkGZSc0XaY6VnTxZr+Kv1G5zFwttpjv8qxZ/sBPT4nthwZaAcsAZTJlSKXQ==",
- "dev": true,
- "dependencies": {
- "camelcase": "^2.0.0",
- "map-obj": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/dateformat": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz",
- "integrity": "sha512-5sFRfAAmbHdIts+eKjR9kYJoF0ViCMVX9yqLu5A7S/v+nd077KgCITOMiirmyCBiZpKLDXbBOkYm6tu7rX/TKg==",
- "dev": true,
- "dependencies": {
- "get-stdin": "^4.0.1",
- "meow": "^3.3.0"
- },
- "bin": {
- "dateformat": "bin/cli.js"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/karma-coverage/node_modules/find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
- "dev": true,
- "dependencies": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/indent-string": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
- "integrity": "sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==",
- "dev": true,
- "dependencies": {
- "repeating": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/map-obj": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
- "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/meow": {
- "version": "3.7.0",
- "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
- "integrity": "sha512-TNdwZs0skRlpPpCUK25StC4VH+tP5GgeY1HQOOGP+lQ2xtdkN2VtT/5tiX9k3IWpkBPV9b3LsAWXn4GGi/PrSA==",
- "dev": true,
- "dependencies": {
- "camelcase-keys": "^2.0.0",
- "decamelize": "^1.1.2",
- "loud-rejection": "^1.0.0",
- "map-obj": "^1.0.1",
- "minimist": "^1.1.3",
- "normalize-package-data": "^2.3.4",
- "object-assign": "^4.0.1",
- "read-pkg-up": "^1.0.1",
- "redent": "^1.0.0",
- "trim-newlines": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
- "dev": true,
- "dependencies": {
- "pinkie-promise": "^2.0.0"
+ "karma": "bin/karma"
},
"engines": {
- "node": ">=0.10.0"
+ "node": "0.10 || 0.12 || 4 || 5"
}
},
- "node_modules/karma-coverage/node_modules/path-type": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
- "integrity": "sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==",
+ "node_modules/karma-chrome-launcher": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz",
+ "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "graceful-fs": "^4.1.2",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
+ "which": "^1.2.1"
}
},
- "node_modules/karma-coverage/node_modules/read-pkg": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
- "integrity": "sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==",
+ "node_modules/karma-chrome-launcher/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "load-json-file": "^1.0.0",
- "normalize-package-data": "^2.3.2",
- "path-type": "^1.0.0"
+ "isexe": "^2.0.0"
},
- "engines": {
- "node": ">=0.10.0"
+ "bin": {
+ "which": "bin/which"
}
},
- "node_modules/karma-coverage/node_modules/read-pkg-up": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
- "integrity": "sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==",
+ "node_modules/karma-coverage": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz",
+ "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "find-up": "^1.0.0",
- "read-pkg": "^1.0.0"
+ "istanbul-lib-coverage": "^3.2.0",
+ "istanbul-lib-instrument": "^5.1.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.1",
+ "istanbul-reports": "^3.0.5",
+ "minimatch": "^3.0.4"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10.0.0"
}
},
- "node_modules/karma-coverage/node_modules/redent": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
- "integrity": "sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==",
+ "node_modules/karma-firefox-launcher": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.3.tgz",
+ "integrity": "sha512-LMM2bseebLbYjODBOVt7TCPP9OI2vZIXCavIXhkO9m+10Uj5l7u/SKoeRmYx8FYHTVGZSpk6peX+3BMHC1WwNw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "indent-string": "^2.1.0",
- "strip-indent": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/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==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "is-wsl": "^2.2.0",
+ "which": "^3.0.0"
}
},
- "node_modules/karma-coverage/node_modules/strip-indent": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
- "integrity": "sha512-I5iQq6aFMM62fBEAIB/hXzwJD6EEZ0xEGCX2t7oXqaKPIRgt4WruAQ285BISgdkP+HLGWyeGmNJcpIwFeRYRUA==",
+ "node_modules/karma-firefox-launcher/node_modules/which": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz",
+ "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "get-stdin": "^4.0.1"
+ "isexe": "^2.0.0"
},
"bin": {
- "strip-indent": "cli.js"
+ "node-which": "bin/which.js"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/karma-coverage/node_modules/trim-newlines": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
- "integrity": "sha512-Nm4cF79FhSTzrLKGDMi3I4utBtFv8qKy4sq1enftf2gMdpqI8oVQTAfySkTz5r49giVzDj88SVZXP4CeYQwjaw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
- "node_modules/karma-firefox-launcher": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-0.1.7.tgz",
- "integrity": "sha512-jS+2RpaVUlEojyWJWsL5MVSxW0h6dRiQ0bpT19bYmLejkI3qCENWU6+xkCOc8d3/K1l6h2mkz+XCi2KQqOyncQ==",
- "dev": true
- },
"node_modules/karma-jasmine": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-0.3.8.tgz",
@@ -16200,24 +17107,28 @@
}
},
"node_modules/karma-junit-reporter": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-1.2.0.tgz",
- "integrity": "sha512-FeuLOKlXNtJhIQK3oQASbO5QOib762CEHV8+L9wwTQpiZJgp7xKg3sNno66rL5bQPV2soG6fJdAFWqqnMJuh2w==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-2.0.1.tgz",
+ "integrity": "sha512-VtcGfE0JE4OE1wn0LK8xxDKaTP7slN8DO3I+4xg6gAi1IoAHAXOJ1V9G/y45Xg6sxdxPOR3THCFtDlAfBo9Afw==",
"dev": true,
"license": "MIT",
"dependencies": {
"path-is-absolute": "^1.0.0",
- "xmlbuilder": "8.2.2"
+ "xmlbuilder": "12.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
},
"peerDependencies": {
"karma": ">=0.9"
}
},
"node_modules/karma-requirejs": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-0.2.6.tgz",
- "integrity": "sha512-8T7U+QwCy36XIYvC1obbWnN766kCck6hcJ7ehr6cgSLq9SnsvqWUETexHbkOPQ2SXnabCb6lbLDNUk3yCPbbrA==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/karma-requirejs/-/karma-requirejs-1.1.0.tgz",
+ "integrity": "sha512-MHTOYKdwwJBkvYid0TaYvBzOnFH3TDtzo6ie5E4o9SaUSXXsfMRLa/whUz6efVIgTxj1xnKYasNn/XwEgJeB/Q==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
"karma": ">=0.9",
"requirejs": "^2.1.0"
@@ -16247,18 +17158,26 @@
}
},
"node_modules/karma-spec-reporter": {
- "version": "0.0.36",
- "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.36.tgz",
- "integrity": "sha512-11bvOl1x6ryKZph7kmbmMpbi8vsngEGxGOoeTlIcDaH3ab3j8aPJnZ+r+K/SS0sBSGy5VGkGYO2+hLct7hw/6w==",
+ "version": "0.0.20",
+ "resolved": "https://registry.npmjs.org/karma-spec-reporter/-/karma-spec-reporter-0.0.20.tgz",
+ "integrity": "sha512-pl+KmLNwnu802F/q9cZx5n20FuxA0ebwM3uMuy4Qh+GGfviy4EFK8I5Bl2cWogSRBUC2Fhg5oOsUFVlv/j5tuA==",
"dev": true,
- "license": "MIT",
"dependencies": {
- "colors": "1.4.0"
+ "colors": "~0.6.0"
},
"peerDependencies": {
"karma": ">=0.9"
}
},
+ "node_modules/karma-spec-reporter/node_modules/colors": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz",
+ "integrity": "sha512-OsSVtHK8Ir8r3+Fxw/b4jS1ZLPXkV6ZxDRJQzeD7qo0SqMXWrHDM71DgYzPMHY8SFJ0Ao+nNU2p1MmwdzKqPrw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
"node_modules/karma-webpack": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-5.0.1.tgz",
@@ -16359,6 +17278,7 @@
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -16404,13 +17324,15 @@
"resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz",
"integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==",
"deprecated": "use String.prototype.padStart()",
- "dev": true
+ "dev": true,
+ "license": "WTFPL"
},
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
"integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -16445,46 +17367,6 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
- "node_modules/load-json-file": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
- "integrity": "sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "parse-json": "^2.2.0",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0",
- "strip-bom": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/load-json-file/node_modules/parse-json": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
- "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
- "dev": true,
- "dependencies": {
- "error-ex": "^1.2.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/load-json-file/node_modules/strip-bom": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
- "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
- "dev": true,
- "dependencies": {
- "is-utf8": "^0.2.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/loader-runner": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
@@ -16590,6 +17472,13 @@
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
"dev": true
},
+ "node_modules/lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
@@ -16641,7 +17530,8 @@
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
"integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lodash.template": {
"version": "4.5.0",
@@ -16713,12 +17603,6 @@
"semver": "bin/semver"
}
},
- "node_modules/lolex": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz",
- "integrity": "sha512-/bpxDL56TG5LS5zoXxKqA6Ro5tkOS5M8cm/7yQcwLIKIcM2HR5fjjNCaIhJNv96SEk4hNGSafYMZK42Xv5fihQ==",
- "dev": true
- },
"node_modules/longest": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -16738,19 +17622,6 @@
"loose-envify": "cli.js"
}
},
- "node_modules/loud-rejection": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
- "integrity": "sha512-RPNliZOFkqFumDhvYqOaNY4Uz9oJM2K9tC6JWsJJsNdhuONW4LQHRBpb0qf4pJApVffI5N39SwzWZJuEhfd7eQ==",
- "dev": true,
- "dependencies": {
- "currently-unhandled": "^0.4.1",
- "signal-exit": "^3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -16775,6 +17646,7 @@
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"semver": "^7.5.3"
},
@@ -16785,26 +17657,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/make-dir/node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/make-dir/node_modules/semver": {
- "version": "7.6.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
- "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
"dev": true,
- "dependencies": {
- "lru-cache": "^6.0.0"
- },
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -16812,12 +17670,6 @@
"node": ">=10"
}
},
- "node_modules/make-dir/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
- },
"node_modules/make-fetch-happen": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-13.0.0.tgz",
@@ -17033,6 +17885,7 @@
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -17046,20 +17899,6 @@
"node": ">=4"
}
},
- "node_modules/mini-create-react-context": {
- "version": "0.3.3",
- "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.3.3.tgz",
- "integrity": "sha512-TtF6hZE59SGmS4U8529qB+jJFeW6asTLDIpPgvPLSCsooAwJS7QprHIFTqv9/Qh3NdLwQxFYgiHX5lqb6jqzPA==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "dependencies": {
- "@babel/runtime": "^7.12.1",
- "tiny-warning": "^1.0.3"
- },
- "peerDependencies": {
- "prop-types": "^15.0.0",
- "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
- }
- },
"node_modules/mini-css-extract-plugin": {
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz",
@@ -17364,10 +18203,11 @@
"dev": true
},
"node_modules/nan": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.19.0.tgz",
- "integrity": "sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw==",
+ "version": "2.22.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz",
+ "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==",
"dev": true,
+ "license": "MIT",
"optional": true
},
"node_modules/nanoid": {
@@ -17436,12 +18276,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/native-promise-only": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz",
- "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==",
- "dev": true
- },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -17503,6 +18337,50 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
+ "node_modules/nise": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz",
+ "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1",
+ "@sinonjs/fake-timers": "^13.0.1",
+ "@sinonjs/text-encoding": "^0.7.3",
+ "just-extend": "^6.2.0",
+ "path-to-regexp": "^8.1.0"
+ }
+ },
+ "node_modules/nise/node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/nise/node_modules/@sinonjs/fake-timers": {
+ "version": "13.0.5",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
+ "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1"
+ }
+ },
+ "node_modules/nise/node_modules/path-to-regexp": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz",
+ "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
@@ -17511,9 +18389,9 @@
"optional": true
},
"node_modules/node-gyp": {
- "version": "10.2.0",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.2.0.tgz",
- "integrity": "sha512-sp3FonBAaFe4aYTcFdZUn2NYkbP7xroPGYvQmP4Nl5PxamznItBnNCgjrVTKrEfQynInMsJvZrdmqUnysCJ8rw==",
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-10.3.1.tgz",
+ "integrity": "sha512-Pp3nFHBThHzVtNY7U6JfPjvT/DTE8+o/4xKsLQtBoU+j2HLsGlhcfzflAoUreaJbNmYnX+LlLi0qjV8kpyO6xQ==",
"license": "MIT",
"dependencies": {
"env-paths": "^2.2.0",
@@ -17534,15 +18412,6 @@
"node": "^16.14.0 || >=18.0.0"
}
},
- "node_modules/node-gyp/node_modules/abbrev": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
- "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
- "license": "ISC",
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
"node_modules/node-gyp/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
@@ -17611,21 +18480,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/node-gyp/node_modules/nopt": {
- "version": "7.2.1",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
- "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
- "license": "ISC",
- "dependencies": {
- "abbrev": "^2.0.0"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
"node_modules/node-gyp/node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -17665,6 +18519,7 @@
"integrity": "sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==",
"dev": true,
"optional": true,
+ "peer": true,
"dependencies": {
"growly": "^1.3.0",
"is-wsl": "^2.2.0",
@@ -17680,6 +18535,7 @@
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"optional": true,
+ "peer": true,
"dependencies": {
"yallist": "^4.0.0"
},
@@ -17693,6 +18549,7 @@
"integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
"dev": true,
"optional": true,
+ "peer": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -17708,7 +18565,8 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
- "optional": true
+ "optional": true,
+ "peer": true
},
"node_modules/node-releases": {
"version": "2.0.18",
@@ -17717,15 +18575,18 @@
"license": "MIT"
},
"node_modules/nopt": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
- "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==",
- "dev": true,
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
+ "integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
+ "license": "ISC",
"dependencies": {
- "abbrev": "1"
+ "abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/normalize-package-data": {
@@ -17797,6 +18658,7 @@
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"path-key": "^3.0.0"
},
@@ -17816,15 +18678,6 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
- "node_modules/null-check": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz",
- "integrity": "sha512-j8ZNHg19TyIQOWCGeeQJBuu6xZYIEurf8M1Qsfd8mFrGEfIZytbw18YjKWg+LcO25NowXGZXZpKAx+Ui3TFfDw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/num2fraction": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
@@ -17849,6 +18702,7 @@
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": "*"
}
@@ -18023,6 +18877,28 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.getownpropertydescriptors": {
+ "version": "2.1.8",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.8.tgz",
+ "integrity": "sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array.prototype.reduce": "^1.0.6",
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0",
+ "gopd": "^1.0.1",
+ "safe-array-concat": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/object.groupby": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
@@ -18132,6 +19008,7 @@
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"mimic-fn": "^2.1.0"
},
@@ -18212,18 +19089,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/p-each-series": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
- "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@@ -18380,7 +19245,6 @@
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
"integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
- "dev": true,
"dependencies": {
"entities": "^4.4.0"
},
@@ -18555,36 +19419,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
- "dev": true,
- "dependencies": {
- "pinkie": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/pirates": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
@@ -19213,7 +20047,8 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
"integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/point-in-polygon": {
"version": "0.0.0",
@@ -19747,53 +20582,36 @@
}
},
"node_modules/pretty-format": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz",
- "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==",
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "license": "MIT",
"dependencies": {
- "@jest/types": "^26.6.2",
- "ansi-regex": "^5.0.0",
- "ansi-styles": "^4.0.0",
- "react-is": "^17.0.1"
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
},
"engines": {
- "node": ">= 10"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/pretty-format/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/pretty-format/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
- },
"node_modules/pretty-format/node_modules/react-is": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
+ "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/proc-log": {
"version": "4.2.0",
@@ -19836,6 +20654,7 @@
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
"integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"kleur": "^3.0.3",
"sisteransi": "^1.0.5"
@@ -19898,6 +20717,32 @@
"once": "^1.3.1"
}
},
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/q": {
"version": "0.9.7",
"resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz",
@@ -20294,27 +21139,24 @@
"integrity": "sha512-nopsRn7KnGgazBe2c3H2+Kf+Csp6PGDRLiBkYEDMKY8o/EIgft/WnIm/OnAKTawZiLnJXHAqhpFBddvs6NiXlw=="
},
"node_modules/react-redux": {
- "version": "5.0.7",
- "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz",
- "integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==",
- "dependencies": {
- "hoist-non-react-statics": "^2.5.0",
- "invariant": "^2.0.0",
- "lodash": "^4.17.5",
- "lodash-es": "^4.17.5",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.1.2.tgz",
+ "integrity": "sha512-Ns1G0XXc8hDyH/OcBHOxNgQx9ayH3SPxBnFCOidGKSle8pKihysQw2rG/PmciUQRoclhVBO8HMhiRmGXnDja9Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.1.2",
+ "hoist-non-react-statics": "^3.3.0",
+ "invariant": "^2.2.4",
"loose-envify": "^1.1.0",
- "prop-types": "^15.6.0"
+ "prop-types": "^15.6.1",
+ "react-is": "^16.6.0",
+ "react-lifecycles-compat": "^3.0.0"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0-0 || ^16.0.0-0",
"redux": "^2.0.0 || ^3.0.0 || ^4.0.0-0"
}
},
- "node_modules/react-redux/node_modules/hoist-non-react-statics": {
- "version": "2.5.5",
- "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
- "integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw=="
- },
"node_modules/react-remove-scroll": {
"version": "2.5.9",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.9.tgz",
@@ -20377,15 +21219,15 @@
}
},
"node_modules/react-router": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz",
- "integrity": "sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==",
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz",
+ "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==",
+ "license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.1.2",
+ "@babel/runtime": "^7.12.13",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
- "mini-create-react-context": "^0.3.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
@@ -20397,15 +21239,16 @@
}
},
"node_modules/react-router-dom": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.1.2.tgz",
- "integrity": "sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==",
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz",
+ "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==",
+ "license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.1.2",
+ "@babel/runtime": "^7.12.13",
"history": "^4.9.0",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.2",
- "react-router": "5.1.2",
+ "react-router": "5.3.4",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
},
@@ -20495,56 +21338,6 @@
"react-dom": ">=15.0.0"
}
},
- "node_modules/read-pkg": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
- "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
- "dev": true,
- "dependencies": {
- "@types/normalize-package-data": "^2.4.0",
- "normalize-package-data": "^2.5.0",
- "parse-json": "^5.0.0",
- "type-fest": "^0.6.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/read-pkg-up": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
- "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
- "dev": true,
- "dependencies": {
- "find-up": "^4.1.0",
- "read-pkg": "^5.2.0",
- "type-fest": "^0.8.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/read-pkg-up/node_modules/type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/read-pkg/node_modules/type-fest": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
- "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
@@ -20906,6 +21699,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/realpath-native": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz",
+ "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "util.promisify": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/rechoir": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
@@ -21125,24 +21931,13 @@
"node": ">=0.10"
}
},
- "node_modules/repeating": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
- "integrity": "sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==",
- "dev": true,
- "dependencies": {
- "is-finite": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
@@ -21174,6 +21969,7 @@
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"lodash": "^4.17.19"
},
@@ -21190,6 +21986,7 @@
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
"deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142",
"dev": true,
+ "license": "ISC",
"dependencies": {
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
@@ -21202,20 +21999,12 @@
"request": "^2.34"
}
},
- "node_modules/request-promise-native/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,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/request-promise-native/node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
@@ -21224,34 +22013,12 @@
"node": ">=0.8"
}
},
- "node_modules/request/node_modules/form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
- "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
- "dev": true,
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "node_modules/request/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,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/request/node_modules/qs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
"dev": true,
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.6"
}
@@ -21261,6 +22028,7 @@
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
@@ -21275,6 +22043,7 @@
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"dev": true,
+ "license": "MIT",
"bin": {
"uuid": "bin/uuid"
}
@@ -21284,6 +22053,7 @@
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -21406,6 +22176,16 @@
"deprecated": "https://github.com/lydell/resolve-url#deprecated",
"dev": true
},
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/restore-cursor": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz",
@@ -21655,13 +22435,6 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
- "node_modules/samsam": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz",
- "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==",
- "deprecated": "This package has been deprecated in favour of @sinonjs/samsam",
- "dev": true
- },
"node_modules/sane": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/sane/-/sane-4.1.0.tgz",
@@ -22216,9 +22989,9 @@
}
},
"node_modules/sass": {
- "version": "1.81.0",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.0.tgz",
- "integrity": "sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==",
+ "version": "1.82.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz",
+ "integrity": "sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==",
"license": "MIT",
"dependencies": {
"chokidar": "^4.0.0",
@@ -22236,9 +23009,9 @@
}
},
"node_modules/sass-loader": {
- "version": "14.2.1",
- "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.2.1.tgz",
- "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==",
+ "version": "16.0.4",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.4.tgz",
+ "integrity": "sha512-LavLbgbBGUt3wCiYzhuLLu65+fWXaXLmq7YxivLhEqmiupCFZ5sKUAipK3do6V80YSU0jvSxNhEdT13IXNr3rg==",
"license": "MIT",
"dependencies": {
"neo-async": "^2.6.2"
@@ -22309,14 +23082,15 @@
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"node_modules/saxes": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
- "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
+ "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
+ "license": "ISC",
"dependencies": {
"xmlchars": "^2.2.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=v12.22.7"
}
},
"node_modules/scheduler": {
@@ -22383,10 +23157,20 @@
"integrity": "sha512-qGVDoreyYiP1pkQnbnFAUIS5AjenNwwQBdl7zeos9etl+hYKWahjRTfzAZZYBv5xNHx7vNKCmaLDQZ6Fr2AEXg=="
},
"node_modules/selenium-webdriver": {
- "version": "4.26.0",
- "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.26.0.tgz",
- "integrity": "sha512-nA7jMRIPV17mJmAiTDBWN96Sy0Uxrz5CCLb7bLVV6PpL417SyBMPc2Zo/uoREc2EOHlzHwHwAlFtgmSngSY4WQ==",
+ "version": "4.27.0",
+ "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.27.0.tgz",
+ "integrity": "sha512-LkTJrNz5socxpPnWPODQ2bQ65eYx9JK+DQMYNihpTjMCqHwgWGYQnQTCAAche2W3ZP87alA+1zYPvgS8tHNzMQ==",
"dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/SeleniumHQ"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/selenium"
+ }
+ ],
"license": "Apache-2.0",
"dependencies": {
"@bazel/runfiles": "^6.3.1",
@@ -22408,28 +23192,6 @@
"node": ">=14.14"
}
},
- "node_modules/selenium-webdriver/node_modules/ws": {
- "version": "8.18.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
- "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
- "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/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -22446,12 +23208,6 @@
"randombytes": "^2.1.0"
}
},
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "dev": true
- },
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
@@ -22590,7 +23346,8 @@
"resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz",
"integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
"dev": true,
- "optional": true
+ "optional": true,
+ "peer": true
},
"node_modules/side-channel": {
"version": "1.0.6",
@@ -22609,43 +23366,85 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/simple-html-tokenizer": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz",
+ "integrity": "sha512-Mc/gH3RvlKvB/gkp9XwgDKEWrSYyefIJPGG8Jk1suZms/rISdUuVEMx5O1WBnTWaScvxXDvGJrZQWblUmQHjkQ=="
+ },
+ "node_modules/sinon": {
+ "version": "19.0.2",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz",
+ "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1",
+ "@sinonjs/fake-timers": "^13.0.2",
+ "@sinonjs/samsam": "^8.0.1",
+ "diff": "^7.0.0",
+ "nise": "^6.1.1",
+ "supports-color": "^7.2.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/sinon"
+ }
+ },
+ "node_modules/sinon/node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/sinon/node_modules/@sinonjs/fake-timers": {
+ "version": "13.0.5",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
+ "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.1"
+ }
},
- "node_modules/simple-html-tokenizer": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/simple-html-tokenizer/-/simple-html-tokenizer-0.1.1.tgz",
- "integrity": "sha512-Mc/gH3RvlKvB/gkp9XwgDKEWrSYyefIJPGG8Jk1suZms/rISdUuVEMx5O1WBnTWaScvxXDvGJrZQWblUmQHjkQ=="
+ "node_modules/sinon/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==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
},
- "node_modules/sinon": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz",
- "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==",
- "deprecated": "16.1.1",
+ "node_modules/sinon/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": "BSD-3-Clause",
+ "license": "MIT",
"dependencies": {
- "diff": "^3.1.0",
- "formatio": "1.2.0",
- "lolex": "^1.6.0",
- "native-promise-only": "^0.8.1",
- "path-to-regexp": "^1.7.0",
- "samsam": "^1.1.3",
- "text-encoding": "0.6.4",
- "type-detect": "^4.0.0"
+ "has-flag": "^4.0.0"
},
"engines": {
- "node": ">=0.1.103"
+ "node": ">=8"
}
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/slash": {
"version": "3.0.0",
@@ -23144,6 +23943,7 @@
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
@@ -23168,7 +23968,8 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/ssri": {
"version": "10.0.5",
@@ -23185,6 +23986,7 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
"integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "license": "MIT",
"dependencies": {
"escape-string-regexp": "^2.0.0"
},
@@ -23196,6 +23998,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
"integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -23252,6 +24055,7 @@
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": ">=0.10.0"
}
@@ -23283,6 +24087,7 @@
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
"integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"char-regex": "^1.0.2",
"strip-ansi": "^6.0.0"
@@ -23474,6 +24279,7 @@
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
"integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -23492,6 +24298,7 @@
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -24061,40 +24868,6 @@
"node": ">=4"
}
},
- "node_modules/supports-hyperlinks": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
- "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0",
- "supports-color": "^7.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-hyperlinks/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==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/supports-hyperlinks/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,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "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",
@@ -24302,22 +25075,6 @@
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
- "node_modules/terminal-link": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
- "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
- "dev": true,
- "dependencies": {
- "ansi-escapes": "^4.2.1",
- "supports-hyperlinks": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/terser": {
"version": "5.30.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.30.0.tgz",
@@ -24434,25 +25191,12 @@
"node": ">=8"
}
},
- "node_modules/text-encoding": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz",
- "integrity": "sha512-hJnc6Qg3dWoOMkqP53F0dzRIgtmsAge09kxUIqGrEUS4qr5rWLckGYaQAVr+opBrIMRErGgy6f5aPnyPpyGRfg==",
- "deprecated": "no longer maintained",
- "dev": true
- },
"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
},
- "node_modules/throat": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
- "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
- "dev": true
- },
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -24612,31 +25356,16 @@
"node": ">=6"
}
},
- "node_modules/tough-cookie/node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/tr46": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz",
- "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
+ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
+ "license": "MIT",
"dependencies": {
"punycode": "^2.1.1"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/tr46/node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "engines": {
- "node": ">=6"
+ "node": ">=12"
}
},
"node_modules/tsconfig-paths": {
@@ -24710,6 +25439,7 @@
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"safe-buffer": "^5.0.1"
},
@@ -24721,7 +25451,8 @@
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
- "dev": true
+ "dev": true,
+ "license": "Unlicense"
},
"node_modules/type": {
"version": "2.7.2",
@@ -24849,15 +25580,6 @@
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
"dev": true
},
- "node_modules/typedarray-to-buffer": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
- "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
- "dev": true,
- "dependencies": {
- "is-typedarray": "^1.0.0"
- }
- },
"node_modules/typescript": {
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
@@ -24945,11 +25667,6 @@
"node": ">=0.8.0"
}
},
- "node_modules/uglify-js/node_modules/async": {
- "version": "0.2.10",
- "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
- "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ=="
- },
"node_modules/uglify-js/node_modules/camelcase": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
@@ -24976,14 +25693,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/uglify-js/node_modules/wordwrap": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
- "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==",
- "engines": {
- "node": ">=0.4.0"
- }
- },
"node_modules/uglify-js/node_modules/yargs": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
@@ -25284,14 +25993,6 @@
"punycode": "^2.1.0"
}
},
- "node_modules/uri-js/node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/urijs": {
"version": "1.19.11",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz",
@@ -25314,6 +26015,11 @@
"requires-port": "^1.0.0"
}
},
+ "node_modules/url-toolkit": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz",
+ "integrity": "sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg=="
+ },
"node_modules/use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@@ -25415,6 +26121,25 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
+ "node_modules/util.promisify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.1.2.tgz",
+ "integrity": "sha512-PBdZ03m1kBnQ5cjjO0ZvJMJS+QsbyIcFwi4hY4U76OQsCO9JrOYjbCFgIF76ccFg9xnJo7ZHPkqyj1GqmdS7MA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "for-each": "^0.3.3",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "object.getownpropertydescriptors": "^2.1.6",
+ "safe-array-concat": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/util/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
@@ -25435,32 +26160,32 @@
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"optional": true,
+ "peer": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/v8-to-istanbul": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-7.1.2.tgz",
- "integrity": "sha512-TxNb7YEUwkLXCQYeudi6lgQ/SZrzNO4kMdlqVxaZPUIUjCv6iSSypUQX70kNBSERpQ8fk48+d61FXk+tgqcWow==",
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
"dev": true,
+ "license": "ISC",
"dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
"@types/istanbul-lib-coverage": "^2.0.1",
- "convert-source-map": "^1.6.0",
- "source-map": "^0.7.3"
+ "convert-source-map": "^2.0.0"
},
"engines": {
- "node": ">=10.10.0"
+ "node": ">=10.12.0"
}
},
- "node_modules/v8-to-istanbul/node_modules/source-map": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
- "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
+ "node_modules/v8-to-istanbul/node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true,
- "engines": {
- "node": ">= 8"
- }
+ "license": "MIT"
},
"node_modules/validate-npm-package-license": {
"version": "3.0.4",
@@ -25494,6 +26219,7 @@
"engines": [
"node >=0.6.0"
],
+ "license": "MIT",
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
@@ -25504,7 +26230,8 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/void-elements": {
"version": "2.0.1",
@@ -25520,19 +26247,30 @@
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
"integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==",
"deprecated": "Use your platform's native performance.now() and performance.timeOrigin.",
+ "dev": true,
"dependencies": {
"browser-process-hrtime": "^1.0.0"
}
},
"node_modules/w3c-xmlserializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz",
- "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
+ "integrity": "sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==",
+ "license": "MIT",
"dependencies": {
- "xml-name-validator": "^3.0.0"
+ "xml-name-validator": "^4.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=14"
+ }
+ },
+ "node_modules/w3c-xmlserializer/node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/walker": {
@@ -25565,24 +26303,25 @@
}
},
"node_modules/webidl-conversions": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz",
- "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">=10.4"
+ "node": ">=12"
}
},
"node_modules/webpack": {
- "version": "5.96.1",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
- "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
+ "version": "5.97.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
+ "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
- "@webassemblyjs/ast": "^1.12.1",
- "@webassemblyjs/wasm-edit": "^1.12.1",
- "@webassemblyjs/wasm-parser": "^1.12.1",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
"acorn": "^8.14.0",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
@@ -25807,6 +26546,7 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz",
"integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==",
+ "dev": true,
"dependencies": {
"iconv-lite": "0.4.24"
}
@@ -25820,19 +26560,20 @@
"node_modules/whatwg-mimetype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz",
- "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g=="
+ "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==",
+ "dev": true
},
"node_modules/whatwg-url": {
- "version": "8.7.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz",
- "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==",
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
+ "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
+ "license": "MIT",
"dependencies": {
- "lodash": "^4.7.0",
- "tr46": "^2.1.0",
- "webidl-conversions": "^6.1.0"
+ "tr46": "^3.0.0",
+ "webidl-conversions": "^7.0.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=12"
}
},
"node_modules/whet.extend": {
@@ -25934,12 +26675,6 @@
"rbush": "^1.3.2"
}
},
- "node_modules/which-module": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
- "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
- "dev": true
- },
"node_modules/which-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
@@ -25982,23 +26717,29 @@
}
},
"node_modules/wordwrap": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
- "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
- "dev": true
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
},
"node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
@@ -26053,6 +26794,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -26068,6 +26810,7 @@
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -26079,7 +26822,8 @@
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/wrappy": {
"version": "1.0.2",
@@ -26099,27 +26843,30 @@
}
},
"node_modules/write-file-atomic": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
- "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4",
- "is-typedarray": "^1.0.0",
- "signal-exit": "^3.0.2",
- "typedarray-to-buffer": "^3.1.5"
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
}
},
"node_modules/ws": {
- "version": "7.5.9",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
- "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "license": "MIT",
"engines": {
- "node": ">=8.3.0"
+ "node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -26139,21 +26886,24 @@
"node_modules/xml-name-validator": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz",
- "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw=="
+ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==",
+ "dev": true
},
"node_modules/xmlbuilder": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz",
- "integrity": "sha512-eKRAFz04jghooy8muekqzo8uCSVNeyRedbuJrp0fovbLIi7wlsYtdUn3vBAAPq2Y3/0xMz2WMEUQ8yhVVO9Stw==",
+ "version": "12.0.0",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-12.0.0.tgz",
+ "integrity": "sha512-lMo8DJ8u6JRWp0/Y4XLa/atVDr75H9litKlb2E5j3V3MesoL50EBgZDWoLT3F/LztVnG67GjPXLZpqcky/UMnQ==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=4.0"
+ "node": ">=6.0"
}
},
"node_modules/xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
- "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
+ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
+ "license": "MIT"
},
"node_modules/xmlhttprequest-ssl": {
"version": "1.6.3",
@@ -26174,10 +26924,14 @@
}
},
"node_modules/y18n": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
- "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
- "dev": true
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/yallist": {
"version": "3.1.1",
@@ -26185,25 +26939,22 @@
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"node_modules/yargs": {
- "version": "15.4.1",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
- "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cliui": "^6.0.0",
- "decamelize": "^1.2.0",
- "find-up": "^4.1.0",
- "get-caller-file": "^2.0.1",
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^4.2.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^18.1.2"
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
},
"engines": {
- "node": ">=8"
+ "node": ">=12"
}
},
"node_modules/yargs-parser": {
@@ -26216,16 +26967,13 @@
}
},
"node_modules/yargs/node_modules/yargs-parser": {
- "version": "18.1.3",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
- "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
- "dependencies": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
- },
+ "license": "ISC",
"engines": {
- "node": ">=6"
+ "node": ">=12"
}
},
"node_modules/yeast": {
diff --git a/package.json b/package.json
index 3d617f47be32..2f09f8a7df90 100644
--- a/package.json
+++ b/package.json
@@ -12,14 +12,33 @@
"compile-sass-dev": "scripts/compile_sass.py --env=development",
"watch": "{ npm run watch-webpack& npm run watch-sass& } && sleep infinity",
"watch-webpack": "npm run webpack-dev -- --watch",
- "watch-sass": "scripts/watch_sass.sh"
+ "watch-sass": "scripts/watch_sass.sh",
+ "lint": "python scripts/eslint.py",
+ "test": "npm run test-cms && npm run test-lms && npm run test-xmodule && npm run test-common && npm run test-jest",
+ "test-kind-vanilla": "npm run test-cms-vanilla && npm run test-xmodule-vanilla && npm run test-common-vanilla",
+ "test-kind-require": "npm run test-cms-require && npm run test-common-require",
+ "test-kind-webpack": "npm run test-cms-webpack && npm run test-lms-webpack && npm run test-xmodule-webpack",
+ "test-cms": "npm run test-cms-vanilla && npm run test-cms-require",
+ "test-cms-vanilla": "npm run test-suite -- cms/static/karma_cms.conf.js",
+ "test-cms-require": "npm run test-suite -- cms/static/karma_cms_squire.conf.js",
+ "test-cms-webpack": "npm run test-suite -- cms/static/karma_cms_webpack.conf.js",
+ "test-lms": "echo 'WARNING: Webpack JS tests are disabled. No LMS JS tests will be run. See https://github.com/openedx/edx-platform/issues/35956 for details.'",
+ "test-lms-webpack": "npm run test-suite -- lms/static/karma_lms.conf.js",
+ "test-xmodule": "npm run test-xmodule-vanilla",
+ "test-xmodule-vanilla": "npm run test-suite -- xmodule/js/karma_xmodule.conf.js",
+ "test-xmodule-webpack": "npm run test-suite -- xmodule/js/karma_xmodule_webpack.conf.js",
+ "test-common": "npm run test-common-vanilla && npm run test-common-require",
+ "test-common-vanilla": "npm run test-suite -- common/static/karma_common.conf.js",
+ "test-common-require": "npm run test-suite -- common/static/karma_common_requirejs.conf.js",
+ "test-suite": "${NODE_WRAPPER:-xvfb-run --auto-servernum} node --max_old_space_size=4096 node_modules/.bin/karma start --single-run=true --capture-timeout=60000 --browsers=FirefoxNoUpdates",
+ "test-jest": "jest"
},
"dependencies": {
"@babel/core": "7.26.0",
"@babel/plugin-proposal-object-rest-spread": "^7.18.9",
"@babel/plugin-transform-object-assign": "^7.18.6",
"@babel/preset-env": "^7.19.0",
- "@babel/preset-react": "7.25.9",
+ "@babel/preset-react": "7.26.3",
"@edx/brand-edx.org": "^2.0.7",
"@edx/edx-bootstrap": "1.0.4",
"@edx/edx-proctoring": "^4.18.1",
@@ -43,16 +62,16 @@
"exports-loader": "0.6.4",
"file-loader": "^6.2.0",
"font-awesome": "4.7.0",
- "hls.js": "1.5.17",
+ "hls.js": "0.14.17",
"imports-loader": "0.8.0",
- "jest-environment-jsdom": "^26.0.0",
+ "jest-environment-jsdom": "^29.0.0",
"jquery": "2.2.4",
"jquery-migrate": "1.4.1",
"jquery.scrollto": "2.1.3",
"js-cookie": "3.0.5",
"moment": "2.30.1",
"moment-timezone": "0.5.46",
- "node-gyp": "10.2.0",
+ "node-gyp": "10.3.1",
"picturefill": "3.0.3",
"popper.js": "1.16.1",
"prop-types": "15.8.1",
@@ -60,15 +79,15 @@
"react": "16.14.0",
"react-dom": "16.14.0",
"react-focus-lock": "^1.19.1",
- "react-redux": "5.0.7",
- "react-router-dom": "5.1.2",
+ "react-redux": "5.1.2",
+ "react-router-dom": "5.3.4",
"react-slick": "0.30.2",
"redux": "3.7.2",
"redux-thunk": "2.2.0",
"requirejs": "2.3.7",
"rtlcss": "4.3.0",
"sass": "^1.54.8",
- "sass-loader": "^14.1.1",
+ "sass-loader": "^16.0.0",
"scriptjs": "2.5.9",
"style-loader": "4.0.0",
"svg-inline-loader": "0.8.2",
@@ -85,30 +104,30 @@
"@edx/eslint-config": "^4.0.0",
"@edx/mockprock": "github:openedx/mockprock#d70b05231bd46b0122616c24e209c890ef2633c0",
"@edx/stylelint-config-edx": "2.3.3",
- "babel-jest": "26.6.3",
+ "babel-jest": "29.7.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.8",
"eslint-import-resolver-webpack": "0.13.9",
"jasmine-core": "2.6.4",
"jasmine-jquery": "git+https://git@github.com/velesin/jasmine-jquery.git#ebad463d592d3fea00c69f26ea18a930e09c7b58",
- "jest": "26.6.3",
- "jest-enzyme": "6.1.2",
+ "jest": "29.7.0",
+ "jest-enzyme": "7.1.2",
"karma": "0.13.22",
- "karma-chrome-launcher": "0.2.3",
- "karma-coverage": "0.5.5",
- "karma-firefox-launcher": "0.1.7",
+ "karma-chrome-launcher": "3.2.0",
+ "karma-coverage": "2.2.1",
+ "karma-firefox-launcher": "2.1.3",
"karma-jasmine": "0.3.8",
"karma-jasmine-html-reporter": "0.2.2",
- "karma-junit-reporter": "1.2.0",
- "karma-requirejs": "0.2.6",
+ "karma-junit-reporter": "2.0.1",
+ "karma-requirejs": "1.1.0",
"karma-selenium-webdriver-launcher": "github:openedx/karma-selenium-webdriver-launcher#0.0.4-openedx.0",
"karma-sourcemap-loader": "0.4.0",
- "karma-spec-reporter": "0.0.36",
+ "karma-spec-reporter": "0.0.20",
"karma-webpack": "^5.0.1",
"plato": "1.7.0",
"react-test-renderer": "16.14.0",
- "selenium-webdriver": "4.26.0",
- "sinon": "2.4.1",
+ "selenium-webdriver": "4.27.0",
+ "sinon": "19.0.2",
"squirejs": "0.1.0",
"string-replace-loader": "^3.1.0",
"stylelint-formatter-pretty": "4.0.1",
diff --git a/pavelib/__init__.py b/pavelib/__init__.py
index 875068166ff5..24f05618bdd7 100644
--- a/pavelib/__init__.py
+++ b/pavelib/__init__.py
@@ -3,4 +3,4 @@
"""
-from . import assets, js_test, prereqs, quality
+from . import assets
diff --git a/pavelib/js_test.py b/pavelib/js_test.py
deleted file mode 100644
index fb9c213499ac..000000000000
--- a/pavelib/js_test.py
+++ /dev/null
@@ -1,143 +0,0 @@
-"""
-Javascript test tasks
-"""
-
-
-import os
-import re
-import sys
-
-from paver.easy import cmdopts, needs, sh, task
-
-from pavelib.utils.envs import Env
-from pavelib.utils.test.suites import JestSnapshotTestSuite, JsTestSuite
-from pavelib.utils.timer import timed
-
-try:
- from pygments.console import colorize
-except ImportError:
- colorize = lambda color, text: text
-
-__test__ = False # do not collect
-
-
-@task
-@needs(
- 'pavelib.prereqs.install_node_prereqs',
- 'pavelib.utils.test.utils.clean_reports_dir',
-)
-@cmdopts([
- ("suite=", "s", "Test suite to run"),
- ("mode=", "m", "dev or run"),
- ("coverage", "c", "Run test under coverage"),
- ("port=", "p", "Port to run test server on (dev mode only)"),
- ('skip-clean', 'C', 'skip cleaning repository before running tests'),
- ('skip_clean', None, 'deprecated in favor of skip-clean'),
-], share_with=["pavelib.utils.tests.utils.clean_reports_dir"])
-@timed
-def test_js(options):
- """
- Run the JavaScript tests
- """
- mode = getattr(options, 'mode', 'run')
- port = None
- skip_clean = getattr(options, 'skip_clean', False)
-
- if mode == 'run':
- suite = getattr(options, 'suite', 'all')
- coverage = getattr(options, 'coverage', False)
- elif mode == 'dev':
- suite = getattr(options, 'suite', None)
- coverage = False
- port = getattr(options, 'port', None)
- else:
- sys.stderr.write("Invalid mode. Please choose 'dev' or 'run'.")
- return
-
- if (suite != 'all') and (suite not in Env.JS_TEST_ID_KEYS):
- sys.stderr.write(
- "Unknown test suite. Please choose from ({suites})\n".format(
- suites=", ".join(Env.JS_TEST_ID_KEYS)
- )
- )
- return
-
- if suite != 'jest-snapshot':
- test_suite = JsTestSuite(suite, mode=mode, with_coverage=coverage, port=port, skip_clean=skip_clean)
- test_suite.run()
-
- if (suite == 'jest-snapshot') or (suite == 'all'): # lint-amnesty, pylint: disable=consider-using-in
- test_suite = JestSnapshotTestSuite('jest')
- test_suite.run()
-
-
-@task
-@cmdopts([
- ("suite=", "s", "Test suite to run"),
- ("coverage", "c", "Run test under coverage"),
-])
-@timed
-def test_js_run(options):
- """
- Run the JavaScript tests and print results to the console
- """
- options.mode = 'run'
- test_js(options)
-
-
-@task
-@cmdopts([
- ("suite=", "s", "Test suite to run"),
- ("port=", "p", "Port to run test server on"),
-])
-@timed
-def test_js_dev(options):
- """
- Run the JavaScript tests in your default browsers
- """
- options.mode = 'dev'
- test_js(options)
-
-
-@task
-@needs('pavelib.prereqs.install_coverage_prereqs')
-@cmdopts([
- ("compare-branch=", "b", "Branch to compare against, defaults to origin/master"),
-], share_with=['coverage'])
-@timed
-def diff_coverage(options):
- """
- Build the diff coverage reports
- """
- compare_branch = options.get('compare_branch', 'origin/master')
-
- # Find all coverage XML files (both Python and JavaScript)
- xml_reports = []
-
- for filepath in Env.REPORT_DIR.walk():
- if bool(re.match(r'^coverage.*\.xml$', filepath.basename())):
- xml_reports.append(filepath)
-
- if not xml_reports:
- err_msg = colorize(
- 'red',
- "No coverage info found. Run `paver test` before running "
- "`paver coverage`.\n"
- )
- sys.stderr.write(err_msg)
- else:
- xml_report_str = ' '.join(xml_reports)
- diff_html_path = os.path.join(Env.REPORT_DIR, 'diff_coverage_combined.html')
-
- # Generate the diff coverage reports (HTML and console)
- # The --diff-range-notation parameter is a workaround for https://github.com/Bachmann1234/diff_cover/issues/153
- sh(
- "diff-cover {xml_report_str} --diff-range-notation '..' --compare-branch={compare_branch} "
- "--html-report {diff_html_path}".format(
- xml_report_str=xml_report_str,
- compare_branch=compare_branch,
- diff_html_path=diff_html_path,
- )
- )
-
- print("\n")
diff --git a/pavelib/paver_tests/conftest.py b/pavelib/paver_tests/conftest.py
deleted file mode 100644
index 214a35e3fe85..000000000000
--- a/pavelib/paver_tests/conftest.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Pytest fixtures for the pavelib unit tests.
-"""
-
-
-import os
-from shutil import rmtree
-
-import pytest
-
-from pavelib.utils.envs import Env
-
-
-@pytest.fixture(autouse=True, scope='session')
-def delete_quality_junit_xml():
- """
- Delete the JUnit XML results files for quality check tasks run during the
- unit tests.
- """
- yield
- if os.path.exists(Env.QUALITY_DIR):
- rmtree(Env.QUALITY_DIR, ignore_errors=True)
diff --git a/pavelib/paver_tests/test_eslint.py b/pavelib/paver_tests/test_eslint.py
deleted file mode 100644
index 5802d7d0d21b..000000000000
--- a/pavelib/paver_tests/test_eslint.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-Tests for Paver's Stylelint tasks.
-"""
-
-
-import unittest
-from unittest.mock import patch
-
-import pytest
-from paver.easy import BuildFailure, call_task
-
-import pavelib.quality
-
-
-class TestPaverESLint(unittest.TestCase):
- """
- For testing run_eslint
- """
-
- def setUp(self):
- super().setUp()
-
- # Mock the paver @needs decorator
- self._mock_paver_needs = patch.object(pavelib.quality.run_eslint, 'needs').start()
- self._mock_paver_needs.return_value = 0
-
- # Mock shell commands
- patcher = patch('pavelib.quality.sh')
- self._mock_paver_sh = patcher.start()
-
- # Cleanup mocks
- self.addCleanup(patcher.stop)
- self.addCleanup(self._mock_paver_needs.stop)
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_count_from_last_line')
- def test_eslint_violation_number_not_found(self, mock_count, mock_report_dir, mock_write_metric): # pylint: disable=unused-argument
- """
- run_eslint encounters an error parsing the eslint output log
- """
- mock_count.return_value = None
- with pytest.raises(BuildFailure):
- call_task('pavelib.quality.run_eslint', args=[''])
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_count_from_last_line')
- def test_eslint_vanilla(self, mock_count, mock_report_dir, mock_write_metric): # pylint: disable=unused-argument
- """
- eslint finds violations, but a limit was not set
- """
- mock_count.return_value = 1
- pavelib.quality.run_eslint("")
diff --git a/pavelib/paver_tests/test_js_test.py b/pavelib/paver_tests/test_js_test.py
deleted file mode 100644
index 4b165a156674..000000000000
--- a/pavelib/paver_tests/test_js_test.py
+++ /dev/null
@@ -1,148 +0,0 @@
-"""Unit tests for the Paver JavaScript testing tasks."""
-
-from unittest.mock import patch
-
-import ddt
-from paver.easy import call_task
-
-import pavelib.js_test
-from pavelib.utils.envs import Env
-
-from .utils import PaverTestCase
-
-
-@ddt.ddt
-class TestPaverJavaScriptTestTasks(PaverTestCase):
- """
- Test the Paver JavaScript testing tasks.
- """
-
- EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND = 'find {platform_root}/reports/javascript -type f -delete'
- EXPECTED_KARMA_OPTIONS = (
- "{config_file} "
- "--single-run={single_run} "
- "--capture-timeout=60000 "
- "--junitreportpath="
- "{platform_root}/reports/javascript/javascript_xunit-{suite}.xml "
- "--browsers={browser}"
- )
- EXPECTED_COVERAGE_OPTIONS = (
- ' --coverage --coveragereportpath={platform_root}/reports/javascript/coverage-{suite}.xml'
- )
-
- EXPECTED_COMMANDS = [
- "make report_dir",
- 'git clean -fqdx test_root/logs test_root/data test_root/staticfiles test_root/uploads',
- "find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \\;",
- 'rm -rf test_root/log/auto_screenshots/*',
- "rm -rf /tmp/mako_[cl]ms",
- ]
-
- def setUp(self):
- super().setUp()
-
- # Mock the paver @needs decorator
- self._mock_paver_needs = patch.object(pavelib.js_test.test_js, 'needs').start()
- self._mock_paver_needs.return_value = 0
-
- # Cleanup mocks
- self.addCleanup(self._mock_paver_needs.stop)
-
- @ddt.data(
- [""],
- ["--coverage"],
- ["--suite=lms"],
- ["--suite=lms --coverage"],
- )
- @ddt.unpack
- def test_test_js_run(self, options_string):
- """
- Test the "test_js_run" task.
- """
- options = self.parse_options_string(options_string)
- self.reset_task_messages()
- call_task("pavelib.js_test.test_js_run", options=options)
- self.verify_messages(options=options, dev_mode=False)
-
- @ddt.data(
- [""],
- ["--port=9999"],
- ["--suite=lms"],
- ["--suite=lms --port=9999"],
- )
- @ddt.unpack
- def test_test_js_dev(self, options_string):
- """
- Test the "test_js_run" task.
- """
- options = self.parse_options_string(options_string)
- self.reset_task_messages()
- call_task("pavelib.js_test.test_js_dev", options=options)
- self.verify_messages(options=options, dev_mode=True)
-
- def parse_options_string(self, options_string):
- """
- Parse a string containing the options for a test run
- """
- parameters = options_string.split(" ")
- suite = "all"
- if "--system=lms" in parameters:
- suite = "lms"
- elif "--system=common" in parameters:
- suite = "common"
- coverage = "--coverage" in parameters
- port = None
- if "--port=9999" in parameters:
- port = 9999
- return {
- "suite": suite,
- "coverage": coverage,
- "port": port,
- }
-
- def verify_messages(self, options, dev_mode):
- """
- Verify that the messages generated when running tests are as expected
- for the specified options and dev_mode.
- """
- is_coverage = options['coverage']
- port = options['port']
- expected_messages = []
- suites = Env.JS_TEST_ID_KEYS if options['suite'] == 'all' else [options['suite']]
-
- expected_messages.extend(self.EXPECTED_COMMANDS)
- if not dev_mode and not is_coverage:
- expected_messages.append(self.EXPECTED_DELETE_JAVASCRIPT_REPORT_COMMAND.format(
- platform_root=self.platform_root
- ))
-
- command_template = (
- 'node --max_old_space_size=4096 node_modules/.bin/karma start {options}'
- )
-
- for suite in suites:
- # Karma test command
- if suite != 'jest-snapshot':
- karma_config_file = Env.KARMA_CONFIG_FILES[Env.JS_TEST_ID_KEYS.index(suite)]
- expected_test_tool_command = command_template.format(
- options=self.EXPECTED_KARMA_OPTIONS.format(
- config_file=karma_config_file,
- single_run='false' if dev_mode else 'true',
- suite=suite,
- platform_root=self.platform_root,
- browser=Env.KARMA_BROWSER,
- ),
- )
- if is_coverage:
- expected_test_tool_command += self.EXPECTED_COVERAGE_OPTIONS.format(
- platform_root=self.platform_root,
- suite=suite
- )
- if port:
- expected_test_tool_command += f" --port={port}"
- else:
- expected_test_tool_command = 'jest'
-
- expected_messages.append(expected_test_tool_command)
-
- assert self.task_messages == expected_messages
diff --git a/pavelib/paver_tests/test_paver_quality.py b/pavelib/paver_tests/test_paver_quality.py
deleted file mode 100644
index 36d6dd59e172..000000000000
--- a/pavelib/paver_tests/test_paver_quality.py
+++ /dev/null
@@ -1,156 +0,0 @@
-""" # lint-amnesty, pylint: disable=django-not-configured
-Tests for paver quality tasks
-"""
-
-
-import os
-import shutil # lint-amnesty, pylint: disable=unused-import
-import tempfile
-import textwrap
-import unittest
-from unittest.mock import MagicMock, mock_open, patch # lint-amnesty, pylint: disable=unused-import
-
-import pytest # lint-amnesty, pylint: disable=unused-import
-from ddt import data, ddt, file_data, unpack # lint-amnesty, pylint: disable=unused-import
-from path import Path as path
-from paver.easy import BuildFailure # lint-amnesty, pylint: disable=unused-import
-
-import pavelib.quality
-from pavelib.paver_tests.utils import PaverTestCase, fail_on_eslint # lint-amnesty, pylint: disable=unused-import
-
-OPEN_BUILTIN = 'builtins.open'
-
-
-@ddt
-class TestPaverQualityViolations(unittest.TestCase):
- """
- For testing the paver violations-counting tasks
- """
- def setUp(self):
- super().setUp()
- self.f = tempfile.NamedTemporaryFile(delete=False) # lint-amnesty, pylint: disable=consider-using-with
- self.f.close()
- self.addCleanup(os.remove, self.f.name)
-
- def test_pep8_parser(self):
- with open(self.f.name, 'w') as f:
- f.write("hello\nhithere")
- num = len(pavelib.quality._pep8_violations(f.name)) # pylint: disable=protected-access
- assert num == 2
-
-
-class TestPaverReportViolationsCounts(unittest.TestCase):
- """
- For testing utility functions for getting counts from reports for
- run_eslint and run_xsslint.
- """
-
- def setUp(self):
- super().setUp()
-
- # Temporary file infrastructure
- self.f = tempfile.NamedTemporaryFile(delete=False) # lint-amnesty, pylint: disable=consider-using-with
- self.f.close()
-
- # Cleanup various mocks and tempfiles
- self.addCleanup(os.remove, self.f.name)
-
- def test_get_eslint_violations_count(self):
- with open(self.f.name, 'w') as f:
- f.write("3000 violations found")
- actual_count = pavelib.quality._get_count_from_last_line(self.f.name, "eslint") # pylint: disable=protected-access
- assert actual_count == 3000
-
- def test_get_eslint_violations_no_number_found(self):
- with open(self.f.name, 'w') as f:
- f.write("Not expected string regex")
- actual_count = pavelib.quality._get_count_from_last_line(self.f.name, "eslint") # pylint: disable=protected-access
- assert actual_count is None
-
- def test_get_eslint_violations_count_truncated_report(self):
- """
- A truncated report (i.e. last line is just a violation)
- """
- with open(self.f.name, 'w') as f:
- f.write("foo/bar/js/fizzbuzz.js: line 45, col 59, Missing semicolon.")
- actual_count = pavelib.quality._get_count_from_last_line(self.f.name, "eslint") # pylint: disable=protected-access
- assert actual_count is None
-
- def test_generic_value(self):
- """
- Default behavior is to look for an integer appearing at head of line
- """
- with open(self.f.name, 'w') as f:
- f.write("5.777 good to see you")
- actual_count = pavelib.quality._get_count_from_last_line(self.f.name, "foo") # pylint: disable=protected-access
- assert actual_count == 5
-
- def test_generic_value_none_found(self):
- """
- Default behavior is to look for an integer appearing at head of line
- """
- with open(self.f.name, 'w') as f:
- f.write("hello 5.777 good to see you")
- actual_count = pavelib.quality._get_count_from_last_line(self.f.name, "foo") # pylint: disable=protected-access
- assert actual_count is None
-
- def test_get_xsslint_counts_happy(self):
- """
- Test happy path getting violation counts from xsslint report.
- """
- report = textwrap.dedent("""
- test.html: 30:53: javascript-jquery-append: $('#test').append(print_tos);
-
- javascript-concat-html: 310 violations
- javascript-escape: 7 violations
-
- 2608 violations total
- """)
- with open(self.f.name, 'w') as f:
- f.write(report)
- counts = pavelib.quality._get_xsslint_counts(self.f.name) # pylint: disable=protected-access
- self.assertDictEqual(counts, {
- 'rules': {
- 'javascript-concat-html': 310,
- 'javascript-escape': 7,
- },
- 'total': 2608,
- })
-
- def test_get_xsslint_counts_bad_counts(self):
- """
- Test getting violation counts from truncated and malformed xsslint
- report.
- """
- report = textwrap.dedent("""
- javascript-concat-html: violations
- """)
- with open(self.f.name, 'w') as f:
- f.write(report)
- counts = pavelib.quality._get_xsslint_counts(self.f.name) # pylint: disable=protected-access
- self.assertDictEqual(counts, {
- 'rules': {},
- 'total': None,
- })
-
-
-class TestPrepareReportDir(unittest.TestCase):
- """
- Tests the report directory preparation
- """
-
- def setUp(self):
- super().setUp()
- self.test_dir = tempfile.mkdtemp()
- self.test_file = tempfile.NamedTemporaryFile(delete=False, dir=self.test_dir) # lint-amnesty, pylint: disable=consider-using-with
- self.addCleanup(os.removedirs, self.test_dir)
-
- def test_report_dir_with_files(self):
- assert os.path.exists(self.test_file.name)
- pavelib.quality._prepare_report_dir(path(self.test_dir)) # pylint: disable=protected-access
- assert not os.path.exists(self.test_file.name)
-
- def test_report_dir_without_files(self):
- os.remove(self.test_file.name)
- pavelib.quality._prepare_report_dir(path(self.test_dir)) # pylint: disable=protected-access
- assert os.listdir(path(self.test_dir)) == []
diff --git a/pavelib/paver_tests/test_pii_check.py b/pavelib/paver_tests/test_pii_check.py
deleted file mode 100644
index d034360acde0..000000000000
--- a/pavelib/paver_tests/test_pii_check.py
+++ /dev/null
@@ -1,79 +0,0 @@
-"""
-Tests for Paver's PII checker task.
-"""
-
-import shutil
-import tempfile
-import unittest
-from unittest.mock import patch
-
-from path import Path as path
-from paver.easy import call_task, BuildFailure
-
-import pavelib.quality
-from pavelib.utils.envs import Env
-
-
-class TestPaverPIICheck(unittest.TestCase):
- """
- For testing the paver run_pii_check task
- """
- def setUp(self):
- super().setUp()
- self.report_dir = path(tempfile.mkdtemp())
- self.addCleanup(shutil.rmtree, self.report_dir)
-
- @patch.object(pavelib.quality.run_pii_check, 'needs')
- @patch('pavelib.quality.sh')
- def test_pii_check_report_dir_override(self, mock_paver_sh, mock_needs):
- """
- run_pii_check succeeds with proper report dir
- """
- # Make the expected stdout files.
- cms_stdout_report = self.report_dir / 'pii_check_cms.report'
- cms_stdout_report.write_lines(['Coverage found 33 uncovered models:\n'])
- lms_stdout_report = self.report_dir / 'pii_check_lms.report'
- lms_stdout_report.write_lines(['Coverage found 66 uncovered models:\n'])
-
- mock_needs.return_value = 0
- call_task('pavelib.quality.run_pii_check', options={"report_dir": str(self.report_dir)})
- mock_calls = [str(call) for call in mock_paver_sh.mock_calls]
- assert len(mock_calls) == 2
- assert any('lms.envs.test' in call for call in mock_calls)
- assert any('cms.envs.test' in call for call in mock_calls)
- assert all(str(self.report_dir) in call for call in mock_calls)
- metrics_file = Env.METRICS_DIR / 'pii'
- assert open(metrics_file).read() == 'Number of PII Annotation violations: 66\n'
-
- @patch.object(pavelib.quality.run_pii_check, 'needs')
- @patch('pavelib.quality.sh')
- def test_pii_check_failed(self, mock_paver_sh, mock_needs):
- """
- run_pii_check fails due to crossing the threshold.
- """
- # Make the expected stdout files.
- cms_stdout_report = self.report_dir / 'pii_check_cms.report'
- cms_stdout_report.write_lines(['Coverage found 33 uncovered models:\n'])
- lms_stdout_report = self.report_dir / 'pii_check_lms.report'
- lms_stdout_report.write_lines([
- 'Coverage found 66 uncovered models:',
- 'Coverage threshold not met! Needed 100.0, actually 95.0!',
- ])
-
- mock_needs.return_value = 0
- try:
- with self.assertRaises(BuildFailure):
- call_task('pavelib.quality.run_pii_check', options={"report_dir": str(self.report_dir)})
- except SystemExit:
- # Sometimes the BuildFailure raises a SystemExit, sometimes it doesn't, not sure why.
- # As a hack, we just wrap it in try-except.
- # This is not good, but these tests weren't even running for years, and we're removing this whole test
- # suite soon anyway.
- pass
- mock_calls = [str(call) for call in mock_paver_sh.mock_calls]
- assert len(mock_calls) == 2
- assert any('lms.envs.test' in call for call in mock_calls)
- assert any('cms.envs.test' in call for call in mock_calls)
- assert all(str(self.report_dir) in call for call in mock_calls)
- metrics_file = Env.METRICS_DIR / 'pii'
- assert open(metrics_file).read() == 'Number of PII Annotation violations: 66\n'
diff --git a/pavelib/paver_tests/test_stylelint.py b/pavelib/paver_tests/test_stylelint.py
deleted file mode 100644
index 3e1c79c93f28..000000000000
--- a/pavelib/paver_tests/test_stylelint.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""
-Tests for Paver's Stylelint tasks.
-"""
-
-from unittest.mock import MagicMock, patch
-
-import pytest
-import ddt
-from paver.easy import call_task
-
-from .utils import PaverTestCase
-
-
-@ddt.ddt
-class TestPaverStylelint(PaverTestCase):
- """
- Tests for Paver's Stylelint tasks.
- """
- @ddt.data(
- [False],
- [True],
- )
- @ddt.unpack
- def test_run_stylelint(self, should_pass):
- """
- Verify that the quality task fails with Stylelint violations.
- """
- if should_pass:
- _mock_stylelint_violations = MagicMock(return_value=0)
- with patch('pavelib.quality._get_stylelint_violations', _mock_stylelint_violations):
- call_task('pavelib.quality.run_stylelint')
- else:
- _mock_stylelint_violations = MagicMock(return_value=100)
- with patch('pavelib.quality._get_stylelint_violations', _mock_stylelint_violations):
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_stylelint')
diff --git a/pavelib/paver_tests/test_timer.py b/pavelib/paver_tests/test_timer.py
deleted file mode 100644
index 0c39b59fdb59..000000000000
--- a/pavelib/paver_tests/test_timer.py
+++ /dev/null
@@ -1,168 +0,0 @@
-"""
-Tests of the pavelib.utils.timer module.
-"""
-
-
-from datetime import datetime, timedelta
-from unittest import TestCase
-
-from unittest.mock import MagicMock, patch
-
-from pavelib.utils import timer
-
-
-@timer.timed
-def identity(*args, **kwargs):
- """
- An identity function used as a default task to test the timing of.
- """
- return args, kwargs
-
-
-MOCK_OPEN = MagicMock(spec=open)
-
-
-@patch.dict('pavelib.utils.timer.__builtins__', open=MOCK_OPEN)
-class TimedDecoratorTests(TestCase):
- """
- Tests of the pavelib.utils.timer:timed decorator.
- """
- def setUp(self):
- super().setUp()
-
- patch_dumps = patch.object(timer.json, 'dump', autospec=True)
- self.mock_dump = patch_dumps.start()
- self.addCleanup(patch_dumps.stop)
-
- patch_makedirs = patch.object(timer.os, 'makedirs', autospec=True)
- self.mock_makedirs = patch_makedirs.start()
- self.addCleanup(patch_makedirs.stop)
-
- patch_datetime = patch.object(timer, 'datetime', autospec=True)
- self.mock_datetime = patch_datetime.start()
- self.addCleanup(patch_datetime.stop)
-
- patch_exists = patch.object(timer, 'exists', autospec=True)
- self.mock_exists = patch_exists.start()
- self.addCleanup(patch_exists.stop)
-
- MOCK_OPEN.reset_mock()
-
- def get_log_messages(self, task=identity, args=None, kwargs=None, raises=None):
- """
- Return all timing messages recorded during the execution of ``task``.
- """
- if args is None:
- args = []
- if kwargs is None:
- kwargs = {}
-
- if raises is None:
- task(*args, **kwargs)
- else:
- self.assertRaises(raises, task, *args, **kwargs)
-
- return [
- call[0][0] # log_message
- for call in self.mock_dump.call_args_list
- ]
-
- @patch.object(timer, 'PAVER_TIMER_LOG', '/tmp/some-log')
- def test_times(self):
- start = datetime(2016, 7, 20, 10, 56, 19)
- end = start + timedelta(seconds=35.6)
-
- self.mock_datetime.utcnow.side_effect = [start, end]
-
- messages = self.get_log_messages()
- assert len(messages) == 1
-
- assert 'duration' in messages[0] and messages[0]['duration'] == 35.6
- assert 'started_at' in messages[0] and messages[0]['started_at'] == start.isoformat(' ')
- assert 'ended_at' in messages[0] and messages[0]['ended_at'] == end.isoformat(' ')
-
- @patch.object(timer, 'PAVER_TIMER_LOG', None)
- def test_no_logs(self):
- messages = self.get_log_messages()
- assert len(messages) == 0
-
- @patch.object(timer, 'PAVER_TIMER_LOG', '/tmp/some-log')
- def test_arguments(self):
- messages = self.get_log_messages(args=(1, 'foo'), kwargs={"bar": 'baz'})
- assert len(messages) == 1
-
- assert 'args' in messages[0] and messages[0]['args'] == [repr(1), repr('foo')]
- assert 'kwargs' in messages[0] and messages[0]['kwargs'] == {'bar': repr('baz')}
-
- @patch.object(timer, 'PAVER_TIMER_LOG', '/tmp/some-log')
- def test_task_name(self):
- messages = self.get_log_messages()
- assert len(messages) == 1
-
- assert 'task' in messages[0] and messages[0]['task'] == 'pavelib.paver_tests.test_timer.identity'
-
- @patch.object(timer, 'PAVER_TIMER_LOG', '/tmp/some-log')
- def test_exceptions(self):
- @timer.timed
- def raises():
- """
- A task used for testing exception handling of the timed decorator.
- """
- raise Exception('The Message!')
-
- messages = self.get_log_messages(task=raises, raises=Exception)
- assert len(messages) == 1
-
- assert 'exception' in messages[0] and messages[0]['exception'] == 'Exception: The Message!'
-
- @patch.object(timer, 'PAVER_TIMER_LOG', '/tmp/some-log-%Y-%m-%d-%H-%M-%S.log')
- def test_date_formatting(self):
- start = datetime(2016, 7, 20, 10, 56, 19)
- end = start + timedelta(seconds=35.6)
-
- self.mock_datetime.utcnow.side_effect = [start, end]
-
- messages = self.get_log_messages()
- assert len(messages) == 1
-
- MOCK_OPEN.assert_called_once_with('/tmp/some-log-2016-07-20-10-56-19.log', 'a')
-
- @patch.object(timer, 'PAVER_TIMER_LOG', '/tmp/some-log')
- def test_nested_tasks(self):
-
- @timer.timed
- def parent():
- """
- A timed task that calls another task
- """
- identity()
-
- parent_start = datetime(2016, 7, 20, 10, 56, 19)
- parent_end = parent_start + timedelta(seconds=60)
- child_start = parent_start + timedelta(seconds=10)
- child_end = parent_end - timedelta(seconds=10)
-
- self.mock_datetime.utcnow.side_effect = [parent_start, child_start, child_end, parent_end]
-
- messages = self.get_log_messages(task=parent)
- assert len(messages) == 2
-
- # Child messages first
- assert 'duration' in messages[0]
- assert 40 == messages[0]['duration']
-
- assert 'started_at' in messages[0]
- assert child_start.isoformat(' ') == messages[0]['started_at']
-
- assert 'ended_at' in messages[0]
- assert child_end.isoformat(' ') == messages[0]['ended_at']
-
- # Parent messages after
- assert 'duration' in messages[1]
- assert 60 == messages[1]['duration']
-
- assert 'started_at' in messages[1]
- assert parent_start.isoformat(' ') == messages[1]['started_at']
-
- assert 'ended_at' in messages[1]
- assert parent_end.isoformat(' ') == messages[1]['ended_at']
diff --git a/pavelib/paver_tests/test_xsslint.py b/pavelib/paver_tests/test_xsslint.py
deleted file mode 100644
index a9b4a41e1600..000000000000
--- a/pavelib/paver_tests/test_xsslint.py
+++ /dev/null
@@ -1,120 +0,0 @@
-"""
-Tests for paver xsslint quality tasks
-"""
-from unittest.mock import patch
-
-import pytest
-from paver.easy import call_task
-
-import pavelib.quality
-
-from .utils import PaverTestCase
-
-
-class PaverXSSLintTest(PaverTestCase):
- """
- Test run_xsslint with a mocked environment in order to pass in opts
- """
-
- def setUp(self):
- super().setUp()
- self.reset_task_messages()
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_violation_number_not_found(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint encounters an error parsing the xsslint output log
- """
- _mock_counts.return_value = {}
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_xsslint')
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_vanilla(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint finds violations, but a limit was not set
- """
- _mock_counts.return_value = {'total': 0}
- call_task('pavelib.quality.run_xsslint')
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_invalid_thresholds_option(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint fails when thresholds option is poorly formatted
- """
- _mock_counts.return_value = {'total': 0}
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_xsslint', options={"thresholds": "invalid"})
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_invalid_thresholds_option_key(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint fails when thresholds option is poorly formatted
- """
- _mock_counts.return_value = {'total': 0}
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_xsslint', options={"thresholds": '{"invalid": 3}'})
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_too_many_violations(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint finds more violations than are allowed
- """
- _mock_counts.return_value = {'total': 4}
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_xsslint', options={"thresholds": '{"total": 3}'})
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_under_limit(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint finds fewer violations than are allowed
- """
- _mock_counts.return_value = {'total': 4}
- # No System Exit is expected
- call_task('pavelib.quality.run_xsslint', options={"thresholds": '{"total": 5}'})
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_rule_violation_number_not_found(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint encounters an error parsing the xsslint output log for a
- given rule threshold that was set.
- """
- _mock_counts.return_value = {'total': 4}
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_xsslint', options={"thresholds": '{"rules": {"javascript-escape": 3}}'})
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_too_many_rule_violations(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint finds more rule violations than are allowed
- """
- _mock_counts.return_value = {'total': 4, 'rules': {'javascript-escape': 4}}
- with pytest.raises(SystemExit):
- call_task('pavelib.quality.run_xsslint', options={"thresholds": '{"rules": {"javascript-escape": 3}}'})
-
- @patch.object(pavelib.quality, '_write_metric')
- @patch.object(pavelib.quality, '_prepare_report_dir')
- @patch.object(pavelib.quality, '_get_xsslint_counts')
- def test_xsslint_under_rule_limit(self, _mock_counts, _mock_report_dir, _mock_write_metric):
- """
- run_xsslint finds fewer rule violations than are allowed
- """
- _mock_counts.return_value = {'total': 4, 'rules': {'javascript-escape': 4}}
- # No System Exit is expected
- call_task('pavelib.quality.run_xsslint', options={"thresholds": '{"rules": {"javascript-escape": 5}}'})
diff --git a/pavelib/quality.py b/pavelib/quality.py
deleted file mode 100644
index 54d677446c45..000000000000
--- a/pavelib/quality.py
+++ /dev/null
@@ -1,602 +0,0 @@
-""" # lint-amnesty, pylint: disable=django-not-configured
-Check code quality using pycodestyle, pylint, and diff_quality.
-"""
-
-import json
-import os
-import re
-from datetime import datetime
-from xml.sax.saxutils import quoteattr
-
-from paver.easy import BuildFailure, cmdopts, needs, sh, task
-
-from .utils.envs import Env
-from .utils.timer import timed
-
-ALL_SYSTEMS = 'lms,cms,common,openedx,pavelib,scripts'
-JUNIT_XML_TEMPLATE = """
-
-{failure_element}
-
-"""
-JUNIT_XML_FAILURE_TEMPLATE = ''
-START_TIME = datetime.utcnow()
-
-
-def write_junit_xml(name, message=None):
- """
- Write a JUnit results XML file describing the outcome of a quality check.
- """
- if message:
- failure_element = JUNIT_XML_FAILURE_TEMPLATE.format(message=quoteattr(message))
- else:
- failure_element = ''
- data = {
- 'failure_count': 1 if message else 0,
- 'failure_element': failure_element,
- 'name': name,
- 'seconds': (datetime.utcnow() - START_TIME).total_seconds(),
- }
- Env.QUALITY_DIR.makedirs_p()
- filename = Env.QUALITY_DIR / f'{name}.xml'
- with open(filename, 'w') as f:
- f.write(JUNIT_XML_TEMPLATE.format(**data))
-
-
-def fail_quality(name, message):
- """
- Fail the specified quality check by generating the JUnit XML results file
- and raising a ``BuildFailure``.
- """
- write_junit_xml(name, message)
- raise BuildFailure(message)
-
-
-def top_python_dirs(dirname):
- """
- Find the directories to start from in order to find all the Python files in `dirname`.
- """
- top_dirs = []
-
- dir_init = os.path.join(dirname, "__init__.py")
- if os.path.exists(dir_init):
- top_dirs.append(dirname)
-
- for directory in ['djangoapps', 'lib']:
- subdir = os.path.join(dirname, directory)
- subdir_init = os.path.join(subdir, "__init__.py")
- if os.path.exists(subdir) and not os.path.exists(subdir_init):
- dirs = os.listdir(subdir)
- top_dirs.extend(d for d in dirs if os.path.isdir(os.path.join(subdir, d)))
-
- modules_to_remove = ['__pycache__']
- for module in modules_to_remove:
- if module in top_dirs:
- top_dirs.remove(module)
-
- return top_dirs
-
-
-def _get_pep8_violations(clean=True):
- """
- Runs pycodestyle. Returns a tuple of (number_of_violations, violations_string)
- where violations_string is a string of all PEP 8 violations found, separated
- by new lines.
- """
- report_dir = Env.REPORT_DIR / 'pep8'
- if clean:
- report_dir.rmtree(ignore_errors=True)
- report_dir.makedirs_p()
- report = report_dir / 'pep8.report'
-
- # Make sure the metrics subdirectory exists
- Env.METRICS_DIR.makedirs_p()
-
- if not report.exists():
- sh(f'pycodestyle . | tee {report} -a')
-
- violations_list = _pep8_violations(report)
-
- return len(violations_list), violations_list
-
-
-def _pep8_violations(report_file):
- """
- Returns the list of all PEP 8 violations in the given report_file.
- """
- with open(report_file) as f:
- return f.readlines()
-
-
-@task
-@cmdopts([
- ("system=", "s", "System to act on"),
-])
-@timed
-def run_pep8(options): # pylint: disable=unused-argument
- """
- Run pycodestyle on system code.
- Fail the task if any violations are found.
- """
- (count, violations_list) = _get_pep8_violations()
- violations_list = ''.join(violations_list)
-
- # Print number of violations to log
- violations_count_str = f"Number of PEP 8 violations: {count}"
- print(violations_count_str)
- print(violations_list)
-
- # Also write the number of violations to a file
- with open(Env.METRICS_DIR / "pep8", "w") as f:
- f.write(violations_count_str + '\n\n')
- f.write(violations_list)
-
- # Fail if any violations are found
- if count:
- failure_string = "FAILURE: Too many PEP 8 violations. " + violations_count_str
- failure_string += f"\n\nViolations:\n{violations_list}"
- fail_quality('pep8', failure_string)
- else:
- write_junit_xml('pep8')
-
-
-@task
-@needs(
- 'pavelib.prereqs.install_node_prereqs',
- 'pavelib.utils.test.utils.ensure_clean_package_lock',
-)
-@cmdopts([
- ("limit=", "l", "limit for number of acceptable violations"),
-])
-@timed
-def run_eslint(options):
- """
- Runs eslint on static asset directories.
- If limit option is passed, fails build if more violations than the limit are found.
- """
-
- eslint_report_dir = Env.REPORT_DIR / "eslint"
- eslint_report = eslint_report_dir / "eslint.report"
- _prepare_report_dir(eslint_report_dir)
- violations_limit = int(getattr(options, 'limit', -1))
-
- sh(
- "node --max_old_space_size=4096 node_modules/.bin/eslint "
- "--ext .js --ext .jsx --format=compact . | tee {eslint_report}".format(
- eslint_report=eslint_report
- ),
- ignore_error=True
- )
-
- try:
- num_violations = int(_get_count_from_last_line(eslint_report, "eslint"))
- except TypeError:
- fail_quality(
- 'eslint',
- "FAILURE: Number of eslint violations could not be found in {eslint_report}".format(
- eslint_report=eslint_report
- )
- )
-
- # Record the metric
- _write_metric(num_violations, (Env.METRICS_DIR / "eslint"))
-
- # Fail if number of violations is greater than the limit
- if num_violations > violations_limit > -1:
- fail_quality(
- 'eslint',
- "FAILURE: Too many eslint violations ({count}).\nThe limit is {violations_limit}.".format(
- count=num_violations, violations_limit=violations_limit
- )
- )
- else:
- write_junit_xml('eslint')
-
-
-def _get_stylelint_violations():
- """
- Returns the number of Stylelint violations.
- """
- stylelint_report_dir = Env.REPORT_DIR / "stylelint"
- stylelint_report = stylelint_report_dir / "stylelint.report"
- _prepare_report_dir(stylelint_report_dir)
- formatter = 'node_modules/stylelint-formatter-pretty'
-
- sh(
- "stylelint **/*.scss --custom-formatter={formatter} | tee {stylelint_report}".format(
- formatter=formatter,
- stylelint_report=stylelint_report,
- ),
- ignore_error=True
- )
-
- try:
- return int(_get_count_from_last_line(stylelint_report, "stylelint"))
- except TypeError:
- fail_quality(
- 'stylelint',
- "FAILURE: Number of stylelint violations could not be found in {stylelint_report}".format(
- stylelint_report=stylelint_report
- )
- )
-
-
-@task
-@needs('pavelib.prereqs.install_node_prereqs')
-@cmdopts([
- ("limit=", "l", "limit for number of acceptable violations"),
-])
-@timed
-def run_stylelint(options):
- """
- Runs stylelint on Sass files.
- If limit option is passed, fails build if more violations than the limit are found.
- """
- violations_limit = 0
- num_violations = _get_stylelint_violations()
-
- # Record the metric
- _write_metric(num_violations, (Env.METRICS_DIR / "stylelint"))
-
- # Fail if number of violations is greater than the limit
- if num_violations > violations_limit:
- fail_quality(
- 'stylelint',
- "FAILURE: Stylelint failed with too many violations: ({count}).\nThe limit is {violations_limit}.".format(
- count=num_violations,
- violations_limit=violations_limit,
- )
- )
- else:
- write_junit_xml('stylelint')
-
-
-@task
-@needs('pavelib.prereqs.install_python_prereqs')
-@cmdopts([
- ("thresholds=", "t", "json containing limit for number of acceptable violations per rule"),
-])
-@timed
-def run_xsslint(options):
- """
- Runs xsslint/xss_linter.py on the codebase
- """
-
- thresholds_option = getattr(options, 'thresholds', '{}')
- try:
- violation_thresholds = json.loads(thresholds_option)
- except ValueError:
- violation_thresholds = None
- if isinstance(violation_thresholds, dict) is False or \
- any(key not in ("total", "rules") for key in violation_thresholds.keys()):
-
- fail_quality(
- 'xsslint',
- """FAILURE: Thresholds option "{thresholds_option}" was not supplied using proper format.\n"""
- """Here is a properly formatted example, '{{"total":100,"rules":{{"javascript-escape":0}}}}' """
- """with property names in double-quotes.""".format(
- thresholds_option=thresholds_option
- )
- )
-
- xsslint_script = "xss_linter.py"
- xsslint_report_dir = Env.REPORT_DIR / "xsslint"
- xsslint_report = xsslint_report_dir / "xsslint.report"
- _prepare_report_dir(xsslint_report_dir)
-
- sh(
- "{repo_root}/scripts/xsslint/{xsslint_script} --rule-totals --config={cfg_module} >> {xsslint_report}".format(
- repo_root=Env.REPO_ROOT,
- xsslint_script=xsslint_script,
- xsslint_report=xsslint_report,
- cfg_module='scripts.xsslint_config'
- ),
- ignore_error=True
- )
-
- xsslint_counts = _get_xsslint_counts(xsslint_report)
-
- try:
- metrics_str = "Number of {xsslint_script} violations: {num_violations}\n".format(
- xsslint_script=xsslint_script, num_violations=int(xsslint_counts['total'])
- )
- if 'rules' in xsslint_counts and any(xsslint_counts['rules']):
- metrics_str += "\n"
- rule_keys = sorted(xsslint_counts['rules'].keys())
- for rule in rule_keys:
- metrics_str += "{rule} violations: {count}\n".format(
- rule=rule,
- count=int(xsslint_counts['rules'][rule])
- )
- except TypeError:
- fail_quality(
- 'xsslint',
- "FAILURE: Number of {xsslint_script} violations could not be found in {xsslint_report}".format(
- xsslint_script=xsslint_script, xsslint_report=xsslint_report
- )
- )
-
- metrics_report = Env.METRICS_DIR / "xsslint"
- # Record the metric
- _write_metric(metrics_str, metrics_report)
- # Print number of violations to log.
- sh(f"cat {metrics_report}", ignore_error=True)
-
- error_message = ""
-
- # Test total violations against threshold.
- if 'total' in list(violation_thresholds.keys()):
- if violation_thresholds['total'] < xsslint_counts['total']:
- error_message = "Too many violations total ({count}).\nThe limit is {violations_limit}.".format(
- count=xsslint_counts['total'], violations_limit=violation_thresholds['total']
- )
-
- # Test rule violations against thresholds.
- if 'rules' in violation_thresholds:
- threshold_keys = sorted(violation_thresholds['rules'].keys())
- for threshold_key in threshold_keys:
- if threshold_key not in xsslint_counts['rules']:
- error_message += (
- "\nNumber of {xsslint_script} violations for {rule} could not be found in "
- "{xsslint_report}."
- ).format(
- xsslint_script=xsslint_script, rule=threshold_key, xsslint_report=xsslint_report
- )
- elif violation_thresholds['rules'][threshold_key] < xsslint_counts['rules'][threshold_key]:
- error_message += \
- "\nToo many {rule} violations ({count}).\nThe {rule} limit is {violations_limit}.".format(
- rule=threshold_key, count=xsslint_counts['rules'][threshold_key],
- violations_limit=violation_thresholds['rules'][threshold_key],
- )
-
- if error_message:
- fail_quality(
- 'xsslint',
- "FAILURE: XSSLinter Failed.\n{error_message}\n"
- "See {xsslint_report} or run the following command to hone in on the problem:\n"
- " ./scripts/xss-commit-linter.sh -h".format(
- error_message=error_message, xsslint_report=xsslint_report
- )
- )
- else:
- write_junit_xml('xsslint')
-
-
-def _write_metric(metric, filename):
- """
- Write a given metric to a given file
- Used for things like reports/metrics/eslint, which will simply tell you the number of
- eslint violations found
- """
- Env.METRICS_DIR.makedirs_p()
-
- with open(filename, "w") as metric_file:
- metric_file.write(str(metric))
-
-
-def _prepare_report_dir(dir_name):
- """
- Sets a given directory to a created, but empty state
- """
- dir_name.rmtree_p()
- dir_name.mkdir_p()
-
-
-def _get_report_contents(filename, report_name, last_line_only=False):
- """
- Returns the contents of the given file. Use last_line_only to only return
- the last line, which can be used for getting output from quality output
- files.
-
- Arguments:
- last_line_only: True to return the last line only, False to return a
- string with full contents.
-
- Returns:
- String containing full contents of the report, or the last line.
-
- """
- if os.path.isfile(filename):
- with open(filename) as report_file:
- if last_line_only:
- lines = report_file.readlines()
- for line in reversed(lines):
- if line != '\n':
- return line
- return None
- else:
- return report_file.read()
- else:
- file_not_found_message = f"FAILURE: The following log file could not be found: {filename}"
- fail_quality(report_name, file_not_found_message)
-
-
-def _get_count_from_last_line(filename, file_type):
- """
- This will return the number in the last line of a file.
- It is returning only the value (as a floating number).
- """
- report_contents = _get_report_contents(filename, file_type, last_line_only=True)
-
- if report_contents is None:
- return 0
-
- last_line = report_contents.strip()
- # Example of the last line of a compact-formatted eslint report (for example): "62829 problems"
- regex = r'^\d+'
-
- try:
- return float(re.search(regex, last_line).group(0))
- # An AttributeError will occur if the regex finds no matches.
- # A ValueError will occur if the returned regex cannot be cast as a float.
- except (AttributeError, ValueError):
- return None
-
-
-def _get_xsslint_counts(filename):
- """
- This returns a dict of violations from the xsslint report.
-
- Arguments:
- filename: The name of the xsslint report.
-
- Returns:
- A dict containing the following:
- rules: A dict containing the count for each rule as follows:
- violation-rule-id: N, where N is the number of violations
- total: M, where M is the number of total violations
-
- """
- report_contents = _get_report_contents(filename, 'xsslint')
- rule_count_regex = re.compile(r"^(?P[a-z-]+):\s+(?P\d+) violations", re.MULTILINE)
- total_count_regex = re.compile(r"^(?P\d+) violations total", re.MULTILINE)
- violations = {'rules': {}}
- for violation_match in rule_count_regex.finditer(report_contents):
- try:
- violations['rules'][violation_match.group('rule_id')] = int(violation_match.group('count'))
- except ValueError:
- violations['rules'][violation_match.group('rule_id')] = None
- try:
- violations['total'] = int(total_count_regex.search(report_contents).group('count'))
- # An AttributeError will occur if the regex finds no matches.
- # A ValueError will occur if the returned regex cannot be cast as a float.
- except (AttributeError, ValueError):
- violations['total'] = None
- return violations
-
-
-def _extract_missing_pii_annotations(filename):
- """
- Returns the number of uncovered models from the stdout report of django_find_annotations.
-
- Arguments:
- filename: Filename where stdout of django_find_annotations was captured.
-
- Returns:
- three-tuple containing:
- 1. The number of uncovered models,
- 2. A bool indicating whether the coverage is still below the threshold, and
- 3. The full report as a string.
- """
- uncovered_models = 0
- pii_check_passed = True
- if os.path.isfile(filename):
- with open(filename) as report_file:
- lines = report_file.readlines()
-
- # Find the count of uncovered models.
- uncovered_regex = re.compile(r'^Coverage found ([\d]+) uncovered')
- for line in lines:
- uncovered_match = uncovered_regex.match(line)
- if uncovered_match:
- uncovered_models = int(uncovered_match.groups()[0])
- break
-
- # Find a message which suggests the check failed.
- failure_regex = re.compile(r'^Coverage threshold not met!')
- for line in lines:
- failure_match = failure_regex.match(line)
- if failure_match:
- pii_check_passed = False
- break
-
- # Each line in lines already contains a newline.
- full_log = ''.join(lines)
- else:
- fail_quality('pii', f'FAILURE: Log file could not be found: {filename}')
-
- return (uncovered_models, pii_check_passed, full_log)
-
-
-@task
-@needs('pavelib.prereqs.install_python_prereqs')
-@cmdopts([
- ("report-dir=", "r", "Directory in which to put PII reports"),
-])
-@timed
-def run_pii_check(options):
- """
- Guarantee that all Django models are PII-annotated.
- """
- pii_report_name = 'pii'
- default_report_dir = Env.REPORT_DIR / pii_report_name
- report_dir = getattr(options, 'report_dir', default_report_dir)
- output_file = os.path.join(report_dir, 'pii_check_{}.report')
- env_report = []
- pii_check_passed = True
- for env_name, env_settings_file in (("CMS", "cms.envs.test"), ("LMS", "lms.envs.test")):
- try:
- print()
- print(f"Running {env_name} PII Annotation check and report")
- print("-" * 45)
- run_output_file = str(output_file).format(env_name.lower())
- sh(
- "mkdir -p {} && " # lint-amnesty, pylint: disable=duplicate-string-formatting-argument
- "export DJANGO_SETTINGS_MODULE={}; "
- "code_annotations django_find_annotations "
- "--config_file .pii_annotations.yml --report_path {} --app_name {} "
- "--lint --report --coverage | tee {}".format(
- report_dir, env_settings_file, report_dir, env_name.lower(), run_output_file
- )
- )
- uncovered_model_count, pii_check_passed_env, full_log = _extract_missing_pii_annotations(run_output_file)
- env_report.append((
- uncovered_model_count,
- full_log,
- ))
-
- except BuildFailure as error_message:
- fail_quality(pii_report_name, f'FAILURE: {error_message}')
-
- if not pii_check_passed_env:
- pii_check_passed = False
-
- # Determine which suite is the worst offender by obtaining the max() keying off uncovered_count.
- uncovered_count, full_log = max(env_report, key=lambda r: r[0])
-
- # Write metric file.
- if uncovered_count is None:
- uncovered_count = 0
- metrics_str = f"Number of PII Annotation violations: {uncovered_count}\n"
- _write_metric(metrics_str, (Env.METRICS_DIR / pii_report_name))
-
- # Finally, fail the paver task if code_annotations suggests that the check failed.
- if not pii_check_passed:
- fail_quality('pii', full_log)
-
-
-@task
-@needs('pavelib.prereqs.install_python_prereqs')
-@timed
-def check_keywords():
- """
- Check Django model fields for names that conflict with a list of reserved keywords
- """
- report_path = os.path.join(Env.REPORT_DIR, 'reserved_keywords')
- sh(f"mkdir -p {report_path}")
-
- overall_status = True
- for env, env_settings_file in [('lms', 'lms.envs.test'), ('cms', 'cms.envs.test')]:
- report_file = f"{env}_reserved_keyword_report.csv"
- override_file = os.path.join(Env.REPO_ROOT, "db_keyword_overrides.yml")
- try:
- sh(
- "export DJANGO_SETTINGS_MODULE={settings_file}; "
- "python manage.py {app} check_reserved_keywords "
- "--override_file {override_file} "
- "--report_path {report_path} "
- "--report_file {report_file}".format(
- settings_file=env_settings_file, app=env, override_file=override_file,
- report_path=report_path, report_file=report_file
- )
- )
- except BuildFailure:
- overall_status = False
-
- if not overall_status:
- fail_quality(
- 'keywords',
- 'Failure: reserved keyword checker failed. Reports can be found here: {}'.format(
- report_path
- )
- )
diff --git a/pavelib/utils/envs.py b/pavelib/utils/envs.py
index d2cdd4a77d7a..7dc9870fbdea 100644
--- a/pavelib/utils/envs.py
+++ b/pavelib/utils/envs.py
@@ -88,15 +88,19 @@ class Env:
KARMA_BROWSER = 'FirefoxNoUpdates'
# Files used to run each of the js test suites
- # TODO: Store this as a dict. Order seems to matter for some
- # reason. See issue TE-415.
+ # TODO: We have [temporarily disabled] the three Webpack-based tests suites. They have been silently
+ # broken for a long time; after noticing they were broken, we added the DieHardPlugin to
+ # webpack.common.config.js to prevent future silent breakage, but have not yet been able to
+ # fix and re-enable the suites. Note that the LMS suite is all Webpack-based even though it's
+ # not in the name.
+ # Issue: https://github.com/openedx/edx-platform/issues/35956
KARMA_CONFIG_FILES = [
REPO_ROOT / 'cms/static/karma_cms.conf.js',
REPO_ROOT / 'cms/static/karma_cms_squire.conf.js',
- REPO_ROOT / 'cms/static/karma_cms_webpack.conf.js',
- REPO_ROOT / 'lms/static/karma_lms.conf.js',
+ ## [temporarily disabled] REPO_ROOT / 'cms/static/karma_cms_webpack.conf.js',
+ ## [temporarily disabled] REPO_ROOT / 'lms/static/karma_lms.conf.js',
REPO_ROOT / 'xmodule/js/karma_xmodule.conf.js',
- REPO_ROOT / 'xmodule/js/karma_xmodule_webpack.conf.js',
+ ## [temporarily disabled] REPO_ROOT / 'xmodule/js/karma_xmodule_webpack.conf.js',
REPO_ROOT / 'common/static/karma_common.conf.js',
REPO_ROOT / 'common/static/karma_common_requirejs.conf.js',
]
@@ -104,10 +108,10 @@ class Env:
JS_TEST_ID_KEYS = [
'cms',
'cms-squire',
- 'cms-webpack',
- 'lms',
+ ## [temporarily-disabled] 'cms-webpack',
+ ## [temporarily-disabled] 'lms',
'xmodule',
- 'xmodule-webpack',
+ ## [temporarily-disabled] 'xmodule-webpack',
'common',
'common-requirejs',
'jest-snapshot'
diff --git a/pavelib/utils/test/suites/__init__.py b/pavelib/utils/test/suites/__init__.py
deleted file mode 100644
index 34ecd49c1c74..000000000000
--- a/pavelib/utils/test/suites/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""
-TestSuite class and subclasses
-"""
-from .js_suite import JestSnapshotTestSuite, JsTestSuite
-from .suite import TestSuite
diff --git a/pavelib/utils/test/suites/js_suite.py b/pavelib/utils/test/suites/js_suite.py
deleted file mode 100644
index 4e53d454fee5..000000000000
--- a/pavelib/utils/test/suites/js_suite.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-Javascript test tasks
-"""
-
-
-from paver import tasks
-
-from pavelib.utils.envs import Env
-from pavelib.utils.test import utils as test_utils
-from pavelib.utils.test.suites.suite import TestSuite
-
-__test__ = False # do not collect
-
-
-class JsTestSuite(TestSuite):
- """
- A class for running JavaScript tests.
- """
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.run_under_coverage = kwargs.get('with_coverage', True)
- self.mode = kwargs.get('mode', 'run')
- self.report_dir = Env.JS_REPORT_DIR
- self.opts = kwargs
-
- suite = args[0]
- self.subsuites = self._default_subsuites if suite == 'all' else [JsTestSubSuite(*args, **kwargs)]
-
- def __enter__(self):
- super().__enter__()
- if tasks.environment.dry_run:
- tasks.environment.info("make report_dir")
- else:
- self.report_dir.makedirs_p()
- if not self.skip_clean:
- test_utils.clean_test_files()
-
- if self.mode == 'run' and not self.run_under_coverage:
- test_utils.clean_dir(self.report_dir)
-
- @property
- def _default_subsuites(self):
- """
- Returns all JS test suites
- """
- return [JsTestSubSuite(test_id, **self.opts) for test_id in Env.JS_TEST_ID_KEYS if test_id != 'jest-snapshot']
-
-
-class JsTestSubSuite(TestSuite):
- """
- Class for JS suites like cms, cms-squire, lms, common,
- common-requirejs and xmodule
- """
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- self.test_id = args[0]
- self.run_under_coverage = kwargs.get('with_coverage', True)
- self.mode = kwargs.get('mode', 'run')
- self.port = kwargs.get('port')
- self.root = self.root + ' javascript'
- self.report_dir = Env.JS_REPORT_DIR
-
- try:
- self.test_conf_file = Env.KARMA_CONFIG_FILES[Env.JS_TEST_ID_KEYS.index(self.test_id)]
- except ValueError:
- self.test_conf_file = Env.KARMA_CONFIG_FILES[0]
-
- self.coverage_report = self.report_dir / f'coverage-{self.test_id}.xml'
- self.xunit_report = self.report_dir / f'javascript_xunit-{self.test_id}.xml'
-
- @property
- def cmd(self):
- """
- Run the tests using karma runner.
- """
- cmd = [
- "node",
- "--max_old_space_size=4096",
- "node_modules/.bin/karma",
- "start",
- self.test_conf_file,
- "--single-run={}".format('false' if self.mode == 'dev' else 'true'),
- "--capture-timeout=60000",
- f"--junitreportpath={self.xunit_report}",
- f"--browsers={Env.KARMA_BROWSER}",
- ]
-
- if self.port:
- cmd.append(f"--port={self.port}")
-
- if self.run_under_coverage:
- cmd.extend([
- "--coverage",
- f"--coveragereportpath={self.coverage_report}",
- ])
-
- return cmd
-
-
-class JestSnapshotTestSuite(TestSuite):
- """
- A class for running Jest Snapshot tests.
- """
- @property
- def cmd(self):
- """
- Run the tests using Jest.
- """
- return ["jest"]
diff --git a/pavelib/utils/test/suites/suite.py b/pavelib/utils/test/suites/suite.py
deleted file mode 100644
index 5a423c827c21..000000000000
--- a/pavelib/utils/test/suites/suite.py
+++ /dev/null
@@ -1,149 +0,0 @@
-"""
-A class used for defining and running test suites
-"""
-
-
-import os
-import subprocess
-import sys
-
-from paver import tasks
-
-from pavelib.utils.process import kill_process
-
-try:
- from pygments.console import colorize
-except ImportError:
- colorize = lambda color, text: text
-
-__test__ = False # do not collect
-
-
-class TestSuite:
- """
- TestSuite is a class that defines how groups of tests run.
- """
- def __init__(self, *args, **kwargs):
- self.root = args[0]
- self.subsuites = kwargs.get('subsuites', [])
- self.failed_suites = []
- self.verbosity = int(kwargs.get('verbosity', 1))
- self.skip_clean = kwargs.get('skip_clean', False)
- self.passthrough_options = kwargs.get('passthrough_options', [])
-
- def __enter__(self):
- """
- This will run before the test suite is run with the run_suite_tests method.
- If self.run_test is called directly, it should be run in a 'with' block to
- ensure that the proper context is created.
-
- Specific setup tasks should be defined in each subsuite.
-
- i.e. Checking for and defining required directories.
- """
- print(f"\nSetting up for {self.root}")
- self.failed_suites = []
-
- def __exit__(self, exc_type, exc_value, traceback):
- """
- This is run after the tests run with the run_suite_tests method finish.
- Specific clean up tasks should be defined in each subsuite.
-
- If self.run_test is called directly, it should be run in a 'with' block
- to ensure that clean up happens properly.
-
- i.e. Cleaning mongo after the lms tests run.
- """
- print(f"\nCleaning up after {self.root}")
-
- @property
- def cmd(self):
- """
- The command to run tests (as a string). For this base class there is none.
- """
- return None
-
- @staticmethod
- def is_success(exit_code):
- """
- Determine if the given exit code represents a success of the test
- suite. By default, only a zero counts as a success.
- """
- return exit_code == 0
-
- def run_test(self):
- """
- Runs a self.cmd in a subprocess and waits for it to finish.
- It returns False if errors or failures occur. Otherwise, it
- returns True.
- """
- cmd = " ".join(self.cmd)
-
- if tasks.environment.dry_run:
- tasks.environment.info(cmd)
- return
-
- sys.stdout.write(cmd)
-
- msg = colorize(
- 'green',
- '\n{bar}\n Running tests for {suite_name} \n{bar}\n'.format(suite_name=self.root, bar='=' * 40),
- )
-
- sys.stdout.write(msg)
- sys.stdout.flush()
-
- if 'TEST_SUITE' not in os.environ:
- os.environ['TEST_SUITE'] = self.root.replace("/", "_")
- kwargs = {'shell': True, 'cwd': None}
- process = None
-
- try:
- process = subprocess.Popen(cmd, **kwargs) # lint-amnesty, pylint: disable=consider-using-with
- return self.is_success(process.wait())
- except KeyboardInterrupt:
- kill_process(process)
- sys.exit(1)
-
- def run_suite_tests(self):
- """
- Runs each of the suites in self.subsuites while tracking failures
- """
- # Uses __enter__ and __exit__ for context
- with self:
- # run the tests for this class, and for all subsuites
- if self.cmd:
- passed = self.run_test()
- if not passed:
- self.failed_suites.append(self)
-
- for suite in self.subsuites:
- suite.run_suite_tests()
- if suite.failed_suites:
- self.failed_suites.extend(suite.failed_suites)
-
- def report_test_results(self):
- """
- Writes a list of failed_suites to sys.stderr
- """
- if self.failed_suites:
- msg = colorize('red', "\n\n{bar}\nTests failed in the following suites:\n* ".format(bar="=" * 48))
- msg += colorize('red', '\n* '.join([s.root for s in self.failed_suites]) + '\n\n')
- else:
- msg = colorize('green', "\n\n{bar}\nNo test failures ".format(bar="=" * 48))
-
- print(msg)
-
- def run(self):
- """
- Runs the tests in the suite while tracking and reporting failures.
- """
- self.run_suite_tests()
-
- if tasks.environment.dry_run:
- return
-
- self.report_test_results()
-
- if self.failed_suites:
- sys.exit(1)
diff --git a/pavelib/utils/test/utils.py b/pavelib/utils/test/utils.py
deleted file mode 100644
index 0851251e2222..000000000000
--- a/pavelib/utils/test/utils.py
+++ /dev/null
@@ -1,91 +0,0 @@
-"""
-Helper functions for test tasks
-"""
-
-
-import os
-
-from paver.easy import cmdopts, sh, task
-
-from pavelib.utils.envs import Env
-from pavelib.utils.timer import timed
-
-
-MONGO_PORT_NUM = int(os.environ.get('EDXAPP_TEST_MONGO_PORT', '27017'))
-
-COVERAGE_CACHE_BUCKET = "edx-tools-coverage-caches"
-COVERAGE_CACHE_BASEPATH = "test_root/who_tests_what"
-COVERAGE_CACHE_BASELINE = "who_tests_what.{}.baseline".format(os.environ.get('WTW_CONTEXT', 'all'))
-WHO_TESTS_WHAT_DIFF = "who_tests_what.diff"
-
-
-__test__ = False # do not collect
-
-
-@task
-@timed
-def clean_test_files():
- """
- Clean fixture files used by tests and .pyc files
- """
- sh("git clean -fqdx test_root/logs test_root/data test_root/staticfiles test_root/uploads")
- # This find command removes all the *.pyc files that aren't in the .git
- # directory. See this blog post for more details:
- # http://nedbatchelder.com/blog/201505/be_careful_deleting_files_around_git.html
- sh(r"find . -name '.git' -prune -o -name '*.pyc' -exec rm {} \;")
- sh("rm -rf test_root/log/auto_screenshots/*")
- sh("rm -rf /tmp/mako_[cl]ms")
-
-
-@task
-@timed
-def ensure_clean_package_lock():
- """
- Ensure no untracked changes have been made in the current git context.
- """
- sh("""
- git diff --name-only --exit-code package-lock.json ||
- (echo \"Dirty package-lock.json, run 'npm install' and commit the generated changes\" && exit 1)
- """)
-
-
-def clean_dir(directory):
- """
- Delete all the files from the specified directory.
- """
- # We delete the files but preserve the directory structure
- # so that coverage.py has a place to put the reports.
- sh(f'find {directory} -type f -delete')
-
-
-@task
-@cmdopts([
- ('skip-clean', 'C', 'skip cleaning repository before running tests'),
- ('skip_clean', None, 'deprecated in favor of skip-clean'),
-])
-@timed
-def clean_reports_dir(options):
- """
- Clean coverage files, to ensure that we don't use stale data to generate reports.
- """
- if getattr(options, 'skip_clean', False):
- print('--skip-clean is set, skipping...')
- return
-
- # We delete the files but preserve the directory structure
- # so that coverage.py has a place to put the reports.
- reports_dir = Env.REPORT_DIR.makedirs_p()
- clean_dir(reports_dir)
-
-
-@task
-@timed
-def clean_mongo():
- """
- Clean mongo test databases
- """
- sh("mongo {host}:{port} {repo_root}/scripts/delete-mongo-test-dbs.js".format(
- host=Env.MONGO_HOST,
- port=MONGO_PORT_NUM,
- repo_root=Env.REPO_ROOT,
- ))
diff --git a/requirements/constraints.txt b/requirements/constraints.txt
index e4b2830a3255..66889a3e0902 100644
--- a/requirements/constraints.txt
+++ b/requirements/constraints.txt
@@ -78,7 +78,7 @@ django-storages<1.14.4
# The team that owns this package will manually bump this package rather than having it pulled in automatically.
# This is to allow them to better control its deployment and to do it in a process that works better
# for them.
-edx-enterprise==4.32.3
+edx-enterprise==5.4.2
# Date: 2024-05-09
# This has to be constrained as well because newer versions of edx-i18n-tools need the
@@ -135,7 +135,7 @@ optimizely-sdk<5.0
# Date: 2023-09-18
# pinning this version to avoid updates while the library is being developed
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269
-openedx-learning==0.17.0
+openedx-learning==0.18.1
# Date: 2023-11-29
# Open AI version 1.0.0 dropped support for openai.ChatCompletion which is currently in use in enterprise.
diff --git a/requirements/edx-sandbox/base.txt b/requirements/edx-sandbox/base.txt
index 15ea566721e5..cb224e498823 100644
--- a/requirements/edx-sandbox/base.txt
+++ b/requirements/edx-sandbox/base.txt
@@ -16,11 +16,15 @@ codejail-includes==1.0.0
# via -r requirements/edx-sandbox/base.in
contourpy==1.3.1
# via matplotlib
-cryptography==43.0.3
+cryptography==44.0.0
# via -r requirements/edx-sandbox/base.in
cycler==0.12.1
# via matplotlib
+<<<<<<< HEAD
fonttools==4.55.0
+=======
+fonttools==4.55.2
+>>>>>>> master
# via matplotlib
joblib==1.4.2
# via nltk
@@ -37,7 +41,7 @@ markupsafe==3.0.2
# via
# chem
# openedx-calc
-matplotlib==3.9.2
+matplotlib==3.9.3
# via -r requirements/edx-sandbox/base.in
mpmath==1.3.0
# via sympy
@@ -55,7 +59,7 @@ numpy==1.26.4
# matplotlib
# openedx-calc
# scipy
-openedx-calc==3.1.2
+openedx-calc==4.0.1
# via -r requirements/edx-sandbox/base.in
packaging==24.2
# via matplotlib
@@ -80,7 +84,7 @@ scipy==1.14.1
# -r requirements/edx-sandbox/base.in
# chem
# openedx-calc
-six==1.16.0
+six==1.17.0
# via
# codejail-includes
# python-dateutil
@@ -88,5 +92,9 @@ sympy==1.13.3
# via
# -r requirements/edx-sandbox/base.in
# openedx-calc
+<<<<<<< HEAD
tqdm==4.67.0
+=======
+tqdm==4.67.1
+>>>>>>> master
# via nltk
diff --git a/requirements/edx/assets.txt b/requirements/edx/assets.txt
index 6c3e1a41515c..15c38017919c 100644
--- a/requirements/edx/assets.txt
+++ b/requirements/edx/assets.txt
@@ -14,5 +14,5 @@ libsass==0.10.0
# -r requirements/edx/assets.in
nodeenv==1.9.1
# via -r requirements/edx/assets.in
-six==1.16.0
+six==1.17.0
# via libsass
diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt
index 0b0f20a4bec7..0ea205b6de4e 100644
--- a/requirements/edx/base.txt
+++ b/requirements/edx/base.txt
@@ -8,9 +8,13 @@
# via -r requirements/edx/github.in
acid-xblock==0.4.1
# via -r requirements/edx/kernel.in
-aiohappyeyeballs==2.4.3
+aiohappyeyeballs==2.4.4
# via aiohttp
+<<<<<<< HEAD
aiohttp==3.11.4
+=======
+aiohttp==3.11.9
+>>>>>>> master
# via
# geoip2
# openai
@@ -54,10 +58,12 @@ babel==2.16.0
# enmerkar-underscore
backoff==1.10.0
# via analytics-python
-bcrypt==4.2.0
+bcrypt==4.2.1
# via paramiko
beautifulsoup4==4.12.3
- # via pynliner
+ # via
+ # openedx-forum
+ # pynliner
billiard==4.2.1
# via celery
bleach[css]==6.2.0
@@ -70,13 +76,21 @@ bleach[css]==6.2.0
# xblock-poll
boto==2.49.0
# via -r requirements/edx/kernel.in
+<<<<<<< HEAD
boto3==1.35.64
+=======
+boto3==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/kernel.in
# django-ses
# fs-s3fs
# ora2
+<<<<<<< HEAD
botocore==1.35.64
+=======
+botocore==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/kernel.in
# boto3
@@ -138,7 +152,11 @@ click-plugins==1.1.1
# via celery
click-repl==0.3.0
# via celery
+<<<<<<< HEAD
code-annotations==1.8.1
+=======
+code-annotations==2.0.0
+>>>>>>> master
# via
# edx-enterprise
# edx-toggles
@@ -146,7 +164,7 @@ codejail-includes==1.0.0
# via -r requirements/edx/kernel.in
crowdsourcehinter-xblock==0.8
# via -r requirements/edx/bundled.in
-cryptography==43.0.3
+cryptography==44.0.0
# via
# -r requirements/edx/kernel.in
# django-fernet-fields-v2
@@ -168,7 +186,7 @@ defusedxml==0.7.1
# ora2
# python3-openid
# social-auth-core
-django==4.2.16
+django==4.2.17
# via
# -c requirements/edx/../common_constraints.txt
# -c requirements/edx/../constraints.txt
@@ -234,6 +252,7 @@ django==4.2.16
# openedx-django-wiki
# openedx-events
# openedx-filters
+ # openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -328,7 +347,7 @@ django-sekizai==4.1.0
# via
# -r requirements/edx/kernel.in
# openedx-django-wiki
-django-ses==4.2.0
+django-ses==4.3.0
# via -r requirements/edx/bundled.in
django-simple-history==3.4.0
# via
@@ -339,12 +358,13 @@ django-simple-history==3.4.0
# edx-organizations
# edx-proctoring
# ora2
-django-statici18n==2.5.0
+django-statici18n==2.6.0
# via
# -r requirements/edx/kernel.in
# lti-consumer-xblock
# xblock-drag-and-drop-v2
# xblock-poll
+ # xblocks-contrib
django-storages==1.14.3
# via
# -c requirements/edx/../constraints.txt
@@ -382,6 +402,7 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
+ # openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -395,7 +416,7 @@ done-xblock==2.4.0
# via -r requirements/edx/bundled.in
drf-jwt==1.19.2
# via edx-drf-extensions
-drf-spectacular==0.27.2
+drf-spectacular==0.28.0
# via -r requirements/edx/kernel.in
drf-yasg==1.21.8
# via
@@ -417,7 +438,7 @@ edx-bulk-grades==1.1.0
# via
# -r requirements/edx/kernel.in
# staff-graded-xblock
-edx-ccx-keys==1.3.0
+edx-ccx-keys==2.0.2
# via
# -r requirements/edx/kernel.in
# lti-consumer-xblock
@@ -438,7 +459,7 @@ edx-django-release-util==1.4.0
# edxval
edx-django-sites-extensions==4.2.0
# via -r requirements/edx/kernel.in
-edx-django-utils==7.0.0
+edx-django-utils==7.1.0
# via
# -r requirements/edx/kernel.in
# django-config-models
@@ -467,7 +488,7 @@ edx-drf-extensions==10.5.0
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.32.3
+edx-enterprise==5.4.2
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in
@@ -480,6 +501,7 @@ edx-i18n-tools==1.5.0
# -c requirements/edx/../constraints.txt
# -r requirements/edx/bundled.in
# ora2
+ # xblocks-contrib
edx-milestones==0.6.0
# via -r requirements/edx/kernel.in
edx-name-affirmation==3.0.1
@@ -502,7 +524,7 @@ edx-opaque-keys[django]==2.11.0
# ora2
edx-organizations==6.13.0
# via -r requirements/edx/kernel.in
-edx-proctoring==4.18.3
+edx-proctoring==4.18.4
# via
# -r requirements/edx/kernel.in
# edx-proctoring-proctortrack
@@ -514,7 +536,9 @@ edx-rest-api-client==6.0.0
# edx-enterprise
# edx-proctoring
edx-search==4.1.1
- # via -r requirements/edx/kernel.in
+ # via
+ # -r requirements/edx/kernel.in
+ # openedx-forum
edx-sga==0.25.0
# via -r requirements/edx/bundled.in
edx-submissions==3.8.3
@@ -547,6 +571,7 @@ elasticsearch==7.9.1
# via
# -c requirements/edx/../common_constraints.txt
# edx-search
+ # openedx-forum
enmerkar==0.7.1
# via enmerkar-underscore
enmerkar-underscore==2.3.1
@@ -591,7 +616,11 @@ google-api-core[grpc]==2.23.0
# google-cloud-core
# google-cloud-firestore
# google-cloud-storage
+<<<<<<< HEAD
google-api-python-client==2.153.0
+=======
+google-api-python-client==2.154.0
+>>>>>>> master
# via firebase-admin
google-auth==2.36.0
# via
@@ -609,7 +638,7 @@ google-cloud-core==2.4.1
# google-cloud-storage
google-cloud-firestore==2.19.0
# via firebase-admin
-google-cloud-storage==2.18.2
+google-cloud-storage==2.19.0
# via firebase-admin
google-crc32c==1.6.0
# via
@@ -621,11 +650,19 @@ googleapis-common-protos==1.66.0
# via
# google-api-core
# grpcio-status
+<<<<<<< HEAD
grpcio==1.68.0
# via
# google-api-core
# grpcio-status
grpcio-status==1.68.0
+=======
+grpcio==1.68.1
+ # via
+ # google-api-core
+ # grpcio-status
+grpcio-status==1.68.1
+>>>>>>> master
# via google-api-core
gunicorn==23.0.0
# via -r requirements/edx/kernel.in
@@ -639,7 +676,7 @@ httplib2==0.22.0
# via
# google-api-python-client
# google-auth-httplib2
-icalendar==6.0.1
+icalendar==6.1.0
# via -r requirements/edx/kernel.in
idna==3.10
# via
@@ -725,7 +762,7 @@ lxml-html-clean==0.4.1
# via lxml
mailsnake==1.6.4
# via -r requirements/edx/bundled.in
-mako==1.3.6
+mako==1.3.7
# via
# -r requirements/edx/kernel.in
# acid-xblock
@@ -749,7 +786,7 @@ markupsafe==3.0.2
# xblock
maxminddb==2.6.2
# via geoip2
-meilisearch==0.31.6
+meilisearch==0.33.0
# via
# -r requirements/edx/kernel.in
# edx-search
@@ -772,10 +809,17 @@ multidict==6.1.0
# aiohttp
# yarl
mysqlclient==2.2.6
+<<<<<<< HEAD
# via -r requirements/edx/kernel.in
newrelic==10.3.0
+=======
+ # via
+ # -r requirements/edx/kernel.in
+ # openedx-forum
+newrelic==10.3.1
+>>>>>>> master
# via edx-django-utils
-nh3==0.2.18
+nh3==0.2.19
# via -r requirements/edx/kernel.in
nltk==3.9.1
# via chem
@@ -802,13 +846,16 @@ openai==0.28.1
# -c requirements/edx/../constraints.txt
# edx-enterprise
openedx-atlas==0.6.2
- # via -r requirements/edx/kernel.in
-openedx-calc==3.1.2
+ # via
+ # -r requirements/edx/kernel.in
+ # openedx-forum
+openedx-calc==4.0.1
# via -r requirements/edx/kernel.in
openedx-django-pyfs==3.7.0
# via
# lti-consumer-xblock
# xblock
+ # xblocks-contrib
openedx-django-require==2.1.0
# via -r requirements/edx/kernel.in
openedx-django-wiki==2.1.0
@@ -827,7 +874,9 @@ openedx-filters==1.11.0
# -r requirements/edx/kernel.in
# lti-consumer-xblock
# ora2
-openedx-learning==0.17.0
+openedx-forum==0.1.5
+ # via -r requirements/edx/kernel.in
+openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in
@@ -837,7 +886,7 @@ optimizely-sdk==4.1.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/bundled.in
-ora2==6.14.0
+ora2==6.14.1
# via -r requirements/edx/bundled.in
packaging==24.2
# via
@@ -884,7 +933,11 @@ polib==1.2.0
# via edx-i18n-tools
prompt-toolkit==3.0.48
# via click-repl
+<<<<<<< HEAD
propcache==0.2.0
+=======
+propcache==0.2.1
+>>>>>>> master
# via
# aiohttp
# yarl
@@ -892,7 +945,7 @@ proto-plus==1.25.0
# via
# google-api-core
# google-cloud-firestore
-protobuf==5.28.3
+protobuf==5.29.1
# via
# google-api-core
# google-cloud-firestore
@@ -924,9 +977,9 @@ pycryptodomex==3.21.0
# edx-proctoring
# lti-consumer-xblock
# pyjwkest
-pydantic==2.9.2
+pydantic==2.10.3
# via camel-converter
-pydantic-core==2.23.4
+pydantic-core==2.27.1
# via pydantic
pygments==2.18.0
# via
@@ -937,7 +990,11 @@ pyjwkest==1.4.2
# -r requirements/edx/kernel.in
# edx-token-utils
# lti-consumer-xblock
+<<<<<<< HEAD
pyjwt[crypto]==2.10.0
+=======
+pyjwt[crypto]==2.10.1
+>>>>>>> master
# via
# -r requirements/edx/kernel.in
# drf-jwt
@@ -963,6 +1020,7 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
+ # openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -970,7 +1028,7 @@ pynacl==1.5.0
# paramiko
pynliner==0.8.0
# via -r requirements/edx/kernel.in
-pyopenssl==24.2.1
+pyopenssl==24.3.0
# via
# optimizely-sdk
# snowflake-connector-python
@@ -1072,6 +1130,7 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
+ # openedx-forum
# optimizely-sdk
# pyjwkest
# pylti1p3
@@ -1086,7 +1145,11 @@ requests-oauthlib==2.0.0
# via
# -r requirements/edx/kernel.in
# social-auth-core
+<<<<<<< HEAD
rpds-py==0.21.0
+=======
+rpds-py==0.22.3
+>>>>>>> master
# via
# jsonschema
# referencing
@@ -1098,7 +1161,7 @@ rules==3.5
# edx-enterprise
# edx-proctoring
# openedx-learning
-s3transfer==0.10.3
+s3transfer==0.10.4
# via boto3
sailthru-client==2.2.3
# via edx-ace
@@ -1117,7 +1180,7 @@ simplejson==3.19.3
# super-csv
# xblock
# xblock-utils
-six==1.16.0
+six==1.17.0
# via
# -r requirements/edx/kernel.in
# -r requirements/edx/paver.txt
@@ -1147,7 +1210,7 @@ slumber==0.7.1
# -r requirements/edx/kernel.in
# edx-bulk-grades
# edx-enterprise
-snowflake-connector-python==3.12.3
+snowflake-connector-python==3.12.4
# via edx-enterprise
social-auth-app-django==5.4.1
# via
@@ -1173,7 +1236,7 @@ sqlparse==0.5.2
# via django
staff-graded-xblock==2.3.0
# via -r requirements/edx/bundled.in
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r requirements/edx/kernel.in
# -r requirements/edx/paver.txt
@@ -1194,7 +1257,11 @@ tinycss2==1.4.0
# via bleach
tomlkit==0.13.2
# via snowflake-connector-python
+<<<<<<< HEAD
tqdm==4.67.0
+=======
+tqdm==4.67.1
+>>>>>>> master
# via
# nltk
# openai
@@ -1261,7 +1328,7 @@ webob==1.8.9
# via
# -r requirements/edx/kernel.in
# xblock
-wrapt==1.16.0
+wrapt==1.17.0
# via -r requirements/edx/paver.txt
xblock[django]==5.1.0
# via
@@ -1278,6 +1345,7 @@ xblock[django]==5.1.0
# xblock-drag-and-drop-v2
# xblock-google-drive
# xblock-utils
+ # xblocks-contrib
xblock-drag-and-drop-v2==4.0.3
# via -r requirements/edx/bundled.in
xblock-google-drive==0.7.0
@@ -1288,11 +1356,17 @@ xblock-utils==4.0.0
# via
# edx-sga
# xblock-poll
+xblocks-contrib==0.1.0
+ # via -r requirements/edx/bundled.in
xmlsec==1.3.14
# via python3-saml
xss-utils==0.6.0
# via -r requirements/edx/kernel.in
+<<<<<<< HEAD
yarl==1.17.2
+=======
+yarl==1.18.3
+>>>>>>> master
# via aiohttp
zipp==3.21.0
# via importlib-metadata
diff --git a/requirements/edx/bundled.in b/requirements/edx/bundled.in
index 5a46c710a6d2..a9394b809f55 100644
--- a/requirements/edx/bundled.in
+++ b/requirements/edx/bundled.in
@@ -47,3 +47,4 @@ ora2>=4.5.0 # Open Response Assessment XBlock
xblock-poll # Xblock for polling users
xblock-drag-and-drop-v2 # Drag and Drop XBlock
xblock-google-drive # XBlock for google docs and calendar
+xblocks-contrib # Package having multiple core XBlocks, https://github.com/openedx/xblocks-contrib?tab=readme-ov-file#xblocks-being-moved-here
diff --git a/requirements/edx/coverage.txt b/requirements/edx/coverage.txt
index 2e82a2fb4d9a..24caf4178a9e 100644
--- a/requirements/edx/coverage.txt
+++ b/requirements/edx/coverage.txt
@@ -6,7 +6,11 @@
#
chardet==5.2.0
# via diff-cover
+<<<<<<< HEAD
coverage==7.6.7
+=======
+coverage==7.6.8
+>>>>>>> master
# via -r requirements/edx/coverage.in
diff-cover==9.2.0
# via -r requirements/edx/coverage.in
diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt
index 4ec241c84683..a43bb3dc0f45 100644
--- a/requirements/edx/development.txt
+++ b/requirements/edx/development.txt
@@ -16,12 +16,16 @@ acid-xblock==0.4.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-aiohappyeyeballs==2.4.3
+aiohappyeyeballs==2.4.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# aiohttp
+<<<<<<< HEAD
aiohttp==3.11.4
+=======
+aiohttp==3.11.9
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -60,7 +64,7 @@ annotated-types==0.7.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# pydantic
-anyio==4.6.2.post1
+anyio==4.7.0
# via
# -r requirements/edx/testing.txt
# starlette
@@ -112,7 +116,7 @@ backoff==1.10.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# analytics-python
-bcrypt==4.2.0
+bcrypt==4.2.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -121,6 +125,7 @@ beautifulsoup4==4.12.3
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
+ # openedx-forum
# pydata-sphinx-theme
# pynliner
billiard==4.2.1
@@ -142,14 +147,22 @@ boto==2.49.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
+<<<<<<< HEAD
boto3==1.35.64
+=======
+boto3==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# django-ses
# fs-s3fs
# ora2
+<<<<<<< HEAD
botocore==1.35.64
+=======
+botocore==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -265,7 +278,11 @@ click-repl==0.3.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# celery
+<<<<<<< HEAD
code-annotations==1.8.1
+=======
+code-annotations==2.0.0
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -280,7 +297,11 @@ colorama==0.4.6
# via
# -r requirements/edx/testing.txt
# tox
+<<<<<<< HEAD
coverage[toml]==7.6.7
+=======
+coverage[toml]==7.6.8
+>>>>>>> master
# via
# -r requirements/edx/testing.txt
# pytest-cov
@@ -288,7 +309,7 @@ crowdsourcehinter-xblock==0.8
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-cryptography==43.0.3
+cryptography==44.0.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -335,7 +356,7 @@ distlib==0.3.9
# via
# -r requirements/edx/testing.txt
# virtualenv
-django==4.2.16
+django==4.2.17
# via
# -c requirements/edx/../common_constraints.txt
# -c requirements/edx/../constraints.txt
@@ -405,6 +426,7 @@ django==4.2.16
# openedx-django-wiki
# openedx-events
# openedx-filters
+ # openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -546,7 +568,7 @@ django-sekizai==4.1.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# openedx-django-wiki
-django-ses==4.2.0
+django-ses==4.3.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -560,13 +582,14 @@ django-simple-history==3.4.0
# edx-organizations
# edx-proctoring
# ora2
-django-statici18n==2.5.0
+django-statici18n==2.6.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# lti-consumer-xblock
# xblock-drag-and-drop-v2
# xblock-poll
+ # xblocks-contrib
django-storages==1.14.3
# via
# -c requirements/edx/../constraints.txt
@@ -617,6 +640,7 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
+ # openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -649,7 +673,7 @@ drf-jwt==1.19.2
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# edx-drf-extensions
-drf-spectacular==0.27.2
+drf-spectacular==0.28.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -682,7 +706,7 @@ edx-bulk-grades==1.1.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# staff-graded-xblock
-edx-ccx-keys==1.3.0
+edx-ccx-keys==2.0.2
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -712,7 +736,7 @@ edx-django-sites-extensions==4.2.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-edx-django-utils==7.0.0
+edx-django-utils==7.1.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -743,7 +767,7 @@ edx-drf-extensions==10.5.0
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.32.3
+edx-enterprise==5.4.2
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt
@@ -762,6 +786,7 @@ edx-i18n-tools==1.5.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# ora2
+ # xblocks-contrib
edx-lint==5.4.1
# via -r requirements/edx/testing.txt
edx-milestones==0.6.0
@@ -792,7 +817,7 @@ edx-organizations==6.13.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-edx-proctoring==4.18.3
+edx-proctoring==4.18.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -812,6 +837,7 @@ edx-search==4.1.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
+ # openedx-forum
edx-sga==0.25.0
# via
# -r requirements/edx/doc.txt
@@ -858,6 +884,7 @@ elasticsearch==7.9.1
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# edx-search
+ # openedx-forum
enmerkar==0.7.1
# via
# -r requirements/edx/doc.txt
@@ -881,11 +908,19 @@ execnet==2.1.1
# pytest-xdist
factory-boy==3.3.1
# via -r requirements/edx/testing.txt
+<<<<<<< HEAD
faker==33.0.0
# via
# -r requirements/edx/testing.txt
# factory-boy
fastapi==0.115.5
+=======
+faker==33.1.0
+ # via
+ # -r requirements/edx/testing.txt
+ # factory-boy
+fastapi==0.115.6
+>>>>>>> master
# via
# -r requirements/edx/testing.txt
# pact-python
@@ -954,7 +989,11 @@ google-api-core[grpc]==2.23.0
# google-cloud-core
# google-cloud-firestore
# google-cloud-storage
+<<<<<<< HEAD
google-api-python-client==2.153.0
+=======
+google-api-python-client==2.154.0
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -985,7 +1024,7 @@ google-cloud-firestore==2.19.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# firebase-admin
-google-cloud-storage==2.18.2
+google-cloud-storage==2.19.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1011,13 +1050,21 @@ grimp==3.5
# via
# -r requirements/edx/testing.txt
# import-linter
+<<<<<<< HEAD
grpcio==1.68.0
+=======
+grpcio==1.68.1
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# google-api-core
# grpcio-status
+<<<<<<< HEAD
grpcio-status==1.68.0
+=======
+grpcio-status==1.68.1
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1047,7 +1094,7 @@ httplib2==0.22.0
# google-auth-httplib2
httpretty==1.1.4
# via -r requirements/edx/testing.txt
-icalendar==6.0.1
+icalendar==6.1.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1206,7 +1253,7 @@ mailsnake==1.6.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-mako==1.3.6
+mako==1.3.7
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1240,7 +1287,7 @@ mccabe==0.7.0
# via
# -r requirements/edx/testing.txt
# pylint
-meilisearch==0.31.6
+meilisearch==0.33.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1296,12 +1343,17 @@ mysqlclient==2.2.6
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
+<<<<<<< HEAD
newrelic==10.3.0
+=======
+ # openedx-forum
+newrelic==10.3.1
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# edx-django-utils
-nh3==0.2.18
+nh3==0.2.19
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1346,7 +1398,8 @@ openedx-atlas==0.6.2
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-openedx-calc==3.1.2
+ # openedx-forum
+openedx-calc==4.0.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1356,6 +1409,7 @@ openedx-django-pyfs==3.7.0
# -r requirements/edx/testing.txt
# lti-consumer-xblock
# xblock
+ # xblocks-contrib
openedx-django-require==2.1.0
# via
# -r requirements/edx/doc.txt
@@ -1380,7 +1434,11 @@ openedx-filters==1.11.0
# -r requirements/edx/testing.txt
# lti-consumer-xblock
# ora2
-openedx-learning==0.17.0
+openedx-forum==0.1.5
+ # via
+ # -r requirements/edx/doc.txt
+ # -r requirements/edx/testing.txt
+openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt
@@ -1394,7 +1452,7 @@ optimizely-sdk==4.1.1
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-ora2==6.14.0
+ora2==6.14.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1494,7 +1552,7 @@ prompt-toolkit==3.0.48
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# click-repl
-propcache==0.2.0
+propcache==0.2.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1506,7 +1564,7 @@ proto-plus==1.25.0
# -r requirements/edx/testing.txt
# google-api-core
# google-cloud-firestore
-protobuf==5.28.3
+protobuf==5.29.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1559,13 +1617,13 @@ pycryptodomex==3.21.0
# edx-proctoring
# lti-consumer-xblock
# pyjwkest
-pydantic==2.9.2
+pydantic==2.10.3
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# camel-converter
# fastapi
-pydantic-core==2.23.4
+pydantic-core==2.27.1
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1590,7 +1648,11 @@ pyjwkest==1.4.2
# -r requirements/edx/testing.txt
# edx-token-utils
# lti-consumer-xblock
+<<<<<<< HEAD
pyjwt[crypto]==2.10.0
+=======
+pyjwt[crypto]==2.10.1
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1647,6 +1709,7 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
+ # openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1658,7 +1721,7 @@ pynliner==0.8.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-pyopenssl==24.2.1
+pyopenssl==24.3.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1692,7 +1755,11 @@ pysrt==1.1.2
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# edxval
+<<<<<<< HEAD
pytest==8.2.0
+=======
+pytest==8.3.4
+>>>>>>> master
# via
# -r requirements/edx/testing.txt
# pylint-pytest
@@ -1843,6 +1910,7 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
+ # openedx-forum
# optimizely-sdk
# pact-python
# pyjwkest
@@ -1860,7 +1928,11 @@ requests-oauthlib==2.0.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# social-auth-core
+<<<<<<< HEAD
rpds-py==0.21.0
+=======
+rpds-py==0.22.3
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1878,7 +1950,7 @@ rules==3.5
# edx-enterprise
# edx-proctoring
# openedx-learning
-s3transfer==0.10.3
+s3transfer==0.10.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -1913,7 +1985,7 @@ simplejson==3.19.3
# xblock-utils
singledispatch==4.1.0
# via -r requirements/edx/testing.txt
-six==1.16.0
+six==1.17.0
# via
# -r requirements/edx/assets.txt
# -r requirements/edx/doc.txt
@@ -1960,7 +2032,7 @@ snowballstemmer==2.2.0
# via
# -r requirements/edx/doc.txt
# sphinx
-snowflake-connector-python==3.12.3
+snowflake-connector-python==3.12.4
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -2004,7 +2076,7 @@ sphinx==8.1.3
# sphinxcontrib-httpdomain
# sphinxcontrib-openapi
# sphinxext-rediraffe
-sphinx-autoapi==3.3.3
+sphinx-autoapi==3.4.0
# via -r requirements/edx/doc.txt
sphinx-book-theme==1.1.3
# via -r requirements/edx/doc.txt
@@ -2062,7 +2134,7 @@ starlette==0.41.3
# via
# -r requirements/edx/testing.txt
# fastapi
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -2096,7 +2168,11 @@ tinycss2==1.4.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# bleach
+<<<<<<< HEAD
tomli==2.1.0
+=======
+tomli==2.2.1
+>>>>>>> master
# via django-stubs
tomlkit==0.13.2
# via
@@ -2106,7 +2182,11 @@ tomlkit==0.13.2
# snowflake-connector-python
tox==4.23.2
# via -r requirements/edx/testing.txt
+<<<<<<< HEAD
tqdm==4.67.0
+=======
+tqdm==4.67.1
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -2124,6 +2204,7 @@ typing-extensions==4.12.2
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
+ # anyio
# django-countries
# django-stubs
# django-stubs-ext
@@ -2174,7 +2255,7 @@ user-util==1.1.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
-uvicorn==0.32.0
+uvicorn==0.32.1
# via
# -r requirements/edx/testing.txt
# pact-python
@@ -2185,7 +2266,7 @@ vine==5.1.0
# amqp
# celery
# kombu
-virtualenv==20.27.1
+virtualenv==20.28.0
# via
# -r requirements/edx/testing.txt
# tox
@@ -2232,11 +2313,15 @@ webob==1.8.9
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# xblock
+<<<<<<< HEAD
wheel==0.45.0
+=======
+wheel==0.45.1
+>>>>>>> master
# via
# -r requirements/edx/../pip-tools.txt
# pip-tools
-wrapt==1.16.0
+wrapt==1.17.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
@@ -2256,6 +2341,7 @@ xblock[django]==5.1.0
# xblock-drag-and-drop-v2
# xblock-google-drive
# xblock-utils
+ # xblocks-contrib
xblock-drag-and-drop-v2==4.0.3
# via
# -r requirements/edx/doc.txt
@@ -2274,6 +2360,10 @@ xblock-utils==4.0.0
# -r requirements/edx/testing.txt
# edx-sga
# xblock-poll
+xblocks-contrib==0.1.0
+ # via
+ # -r requirements/edx/doc.txt
+ # -r requirements/edx/testing.txt
xmlsec==1.3.14
# via
# -r requirements/edx/doc.txt
@@ -2283,7 +2373,11 @@ xss-utils==0.6.0
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
+<<<<<<< HEAD
yarl==1.17.2
+=======
+yarl==1.18.3
+>>>>>>> master
# via
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt
index 19f9df40b088..a980f8b39168 100644
--- a/requirements/edx/doc.txt
+++ b/requirements/edx/doc.txt
@@ -10,11 +10,15 @@ accessible-pygments==0.0.5
# via pydata-sphinx-theme
acid-xblock==0.4.1
# via -r requirements/edx/base.txt
-aiohappyeyeballs==2.4.3
+aiohappyeyeballs==2.4.4
# via
# -r requirements/edx/base.txt
# aiohttp
+<<<<<<< HEAD
aiohttp==3.11.4
+=======
+aiohttp==3.11.9
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# geoip2
@@ -80,13 +84,14 @@ backoff==1.10.0
# via
# -r requirements/edx/base.txt
# analytics-python
-bcrypt==4.2.0
+bcrypt==4.2.1
# via
# -r requirements/edx/base.txt
# paramiko
beautifulsoup4==4.12.3
# via
# -r requirements/edx/base.txt
+ # openedx-forum
# pydata-sphinx-theme
# pynliner
billiard==4.2.1
@@ -104,13 +109,21 @@ bleach[css]==6.2.0
# xblock-poll
boto==2.49.0
# via -r requirements/edx/base.txt
+<<<<<<< HEAD
boto3==1.35.64
+=======
+boto3==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# django-ses
# fs-s3fs
# ora2
+<<<<<<< HEAD
botocore==1.35.64
+=======
+botocore==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# boto3
@@ -188,7 +201,11 @@ click-repl==0.3.0
# via
# -r requirements/edx/base.txt
# celery
+<<<<<<< HEAD
code-annotations==1.8.1
+=======
+code-annotations==2.0.0
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# -r requirements/edx/doc.in
@@ -198,7 +215,7 @@ codejail-includes==1.0.0
# via -r requirements/edx/base.txt
crowdsourcehinter-xblock==0.8
# via -r requirements/edx/base.txt
-cryptography==43.0.3
+cryptography==44.0.0
# via
# -r requirements/edx/base.txt
# django-fernet-fields-v2
@@ -224,7 +241,7 @@ defusedxml==0.7.1
# ora2
# python3-openid
# social-auth-core
-django==4.2.16
+django==4.2.17
# via
# -c requirements/edx/../common_constraints.txt
# -c requirements/edx/../constraints.txt
@@ -290,6 +307,7 @@ django==4.2.16
# openedx-django-wiki
# openedx-events
# openedx-filters
+ # openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -400,7 +418,7 @@ django-sekizai==4.1.0
# via
# -r requirements/edx/base.txt
# openedx-django-wiki
-django-ses==4.2.0
+django-ses==4.3.0
# via -r requirements/edx/base.txt
django-simple-history==3.4.0
# via
@@ -411,12 +429,13 @@ django-simple-history==3.4.0
# edx-organizations
# edx-proctoring
# ora2
-django-statici18n==2.5.0
+django-statici18n==2.6.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
# xblock-drag-and-drop-v2
# xblock-poll
+ # xblocks-contrib
django-storages==1.14.3
# via
# -c requirements/edx/../constraints.txt
@@ -454,6 +473,7 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
+ # openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -476,7 +496,7 @@ drf-jwt==1.19.2
# via
# -r requirements/edx/base.txt
# edx-drf-extensions
-drf-spectacular==0.27.2
+drf-spectacular==0.28.0
# via -r requirements/edx/base.txt
drf-yasg==1.21.8
# via
@@ -499,7 +519,7 @@ edx-bulk-grades==1.1.0
# via
# -r requirements/edx/base.txt
# staff-graded-xblock
-edx-ccx-keys==1.3.0
+edx-ccx-keys==2.0.2
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
@@ -520,7 +540,7 @@ edx-django-release-util==1.4.0
# edxval
edx-django-sites-extensions==4.2.0
# via -r requirements/edx/base.txt
-edx-django-utils==7.0.0
+edx-django-utils==7.1.0
# via
# -r requirements/edx/base.txt
# django-config-models
@@ -549,7 +569,7 @@ edx-drf-extensions==10.5.0
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.32.3
+edx-enterprise==5.4.2
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
@@ -562,6 +582,7 @@ edx-i18n-tools==1.5.0
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
# ora2
+ # xblocks-contrib
edx-milestones==0.6.0
# via -r requirements/edx/base.txt
edx-name-affirmation==3.0.1
@@ -583,7 +604,7 @@ edx-opaque-keys[django]==2.11.0
# ora2
edx-organizations==6.13.0
# via -r requirements/edx/base.txt
-edx-proctoring==4.18.3
+edx-proctoring==4.18.4
# via
# -r requirements/edx/base.txt
# edx-proctoring-proctortrack
@@ -597,7 +618,9 @@ edx-rest-api-client==6.0.0
# edx-enterprise
# edx-proctoring
edx-search==4.1.1
- # via -r requirements/edx/base.txt
+ # via
+ # -r requirements/edx/base.txt
+ # openedx-forum
edx-sga==0.25.0
# via -r requirements/edx/base.txt
edx-submissions==3.8.3
@@ -633,6 +656,7 @@ elasticsearch==7.9.1
# -c requirements/edx/../common_constraints.txt
# -r requirements/edx/base.txt
# edx-search
+ # openedx-forum
enmerkar==0.7.1
# via
# -r requirements/edx/base.txt
@@ -693,7 +717,11 @@ google-api-core[grpc]==2.23.0
# google-cloud-core
# google-cloud-firestore
# google-cloud-storage
+<<<<<<< HEAD
google-api-python-client==2.153.0
+=======
+google-api-python-client==2.154.0
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# firebase-admin
@@ -719,7 +747,7 @@ google-cloud-firestore==2.19.0
# via
# -r requirements/edx/base.txt
# firebase-admin
-google-cloud-storage==2.18.2
+google-cloud-storage==2.19.0
# via
# -r requirements/edx/base.txt
# firebase-admin
@@ -737,12 +765,20 @@ googleapis-common-protos==1.66.0
# -r requirements/edx/base.txt
# google-api-core
# grpcio-status
+<<<<<<< HEAD
grpcio==1.68.0
+=======
+grpcio==1.68.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# google-api-core
# grpcio-status
+<<<<<<< HEAD
grpcio-status==1.68.0
+=======
+grpcio-status==1.68.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# google-api-core
@@ -759,7 +795,7 @@ httplib2==0.22.0
# -r requirements/edx/base.txt
# google-api-python-client
# google-auth-httplib2
-icalendar==6.0.1
+icalendar==6.1.0
# via -r requirements/edx/base.txt
idna==3.10
# via
@@ -872,7 +908,7 @@ lxml-html-clean==0.4.1
# lxml
mailsnake==1.6.4
# via -r requirements/edx/base.txt
-mako==1.3.6
+mako==1.3.7
# via
# -r requirements/edx/base.txt
# acid-xblock
@@ -898,7 +934,7 @@ maxminddb==2.6.2
# via
# -r requirements/edx/base.txt
# geoip2
-meilisearch==0.31.6
+meilisearch==0.33.0
# via
# -r requirements/edx/base.txt
# edx-search
@@ -931,12 +967,19 @@ multidict==6.1.0
# aiohttp
# yarl
mysqlclient==2.2.6
+<<<<<<< HEAD
# via -r requirements/edx/base.txt
newrelic==10.3.0
+=======
+ # via
+ # -r requirements/edx/base.txt
+ # openedx-forum
+newrelic==10.3.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# edx-django-utils
-nh3==0.2.18
+nh3==0.2.19
# via -r requirements/edx/base.txt
nltk==3.9.1
# via
@@ -967,14 +1010,17 @@ openai==0.28.1
# -r requirements/edx/base.txt
# edx-enterprise
openedx-atlas==0.6.2
- # via -r requirements/edx/base.txt
-openedx-calc==3.1.2
+ # via
+ # -r requirements/edx/base.txt
+ # openedx-forum
+openedx-calc==4.0.1
# via -r requirements/edx/base.txt
openedx-django-pyfs==3.7.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
# xblock
+ # xblocks-contrib
openedx-django-require==2.1.0
# via -r requirements/edx/base.txt
openedx-django-wiki==2.1.0
@@ -993,7 +1039,9 @@ openedx-filters==1.11.0
# -r requirements/edx/base.txt
# lti-consumer-xblock
# ora2
-openedx-learning==0.17.0
+openedx-forum==0.1.5
+ # via -r requirements/edx/base.txt
+openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
@@ -1003,7 +1051,7 @@ optimizely-sdk==4.1.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
-ora2==6.14.0
+ora2==6.14.1
# via -r requirements/edx/base.txt
packaging==24.2
# via
@@ -1066,7 +1114,7 @@ prompt-toolkit==3.0.48
# via
# -r requirements/edx/base.txt
# click-repl
-propcache==0.2.0
+propcache==0.2.1
# via
# -r requirements/edx/base.txt
# aiohttp
@@ -1076,7 +1124,7 @@ proto-plus==1.25.0
# -r requirements/edx/base.txt
# google-api-core
# google-cloud-firestore
-protobuf==5.28.3
+protobuf==5.29.1
# via
# -r requirements/edx/base.txt
# google-api-core
@@ -1114,11 +1162,11 @@ pycryptodomex==3.21.0
# edx-proctoring
# lti-consumer-xblock
# pyjwkest
-pydantic==2.9.2
+pydantic==2.10.3
# via
# -r requirements/edx/base.txt
# camel-converter
-pydantic-core==2.23.4
+pydantic-core==2.27.1
# via
# -r requirements/edx/base.txt
# pydantic
@@ -1137,7 +1185,11 @@ pyjwkest==1.4.2
# -r requirements/edx/base.txt
# edx-token-utils
# lti-consumer-xblock
+<<<<<<< HEAD
pyjwt[crypto]==2.10.0
+=======
+pyjwt[crypto]==2.10.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# drf-jwt
@@ -1164,6 +1216,7 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
+ # openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1172,7 +1225,7 @@ pynacl==1.5.0
# paramiko
pynliner==0.8.0
# via -r requirements/edx/base.txt
-pyopenssl==24.2.1
+pyopenssl==24.3.0
# via
# -r requirements/edx/base.txt
# optimizely-sdk
@@ -1289,6 +1342,7 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
+ # openedx-forum
# optimizely-sdk
# pyjwkest
# pylti1p3
@@ -1304,7 +1358,11 @@ requests-oauthlib==2.0.0
# via
# -r requirements/edx/base.txt
# social-auth-core
+<<<<<<< HEAD
rpds-py==0.21.0
+=======
+rpds-py==0.22.3
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# jsonschema
@@ -1319,7 +1377,7 @@ rules==3.5
# edx-enterprise
# edx-proctoring
# openedx-learning
-s3transfer==0.10.3
+s3transfer==0.10.4
# via
# -r requirements/edx/base.txt
# boto3
@@ -1345,7 +1403,7 @@ simplejson==3.19.3
# super-csv
# xblock
# xblock-utils
-six==1.16.0
+six==1.17.0
# via
# -r requirements/edx/base.txt
# analytics-python
@@ -1379,7 +1437,7 @@ smmap==5.0.1
# via gitdb
snowballstemmer==2.2.0
# via sphinx
-snowflake-connector-python==3.12.3
+snowflake-connector-python==3.12.4
# via
# -r requirements/edx/base.txt
# edx-enterprise
@@ -1417,7 +1475,7 @@ sphinx==8.1.3
# sphinxcontrib-httpdomain
# sphinxcontrib-openapi
# sphinxext-rediraffe
-sphinx-autoapi==3.3.3
+sphinx-autoapi==3.4.0
# via -r requirements/edx/doc.in
sphinx-book-theme==1.1.3
# via -r requirements/edx/doc.in
@@ -1451,7 +1509,7 @@ sqlparse==0.5.2
# django
staff-graded-xblock==2.3.0
# via -r requirements/edx/base.txt
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r requirements/edx/base.txt
# code-annotations
@@ -1483,7 +1541,11 @@ tomlkit==0.13.2
# via
# -r requirements/edx/base.txt
# snowflake-connector-python
+<<<<<<< HEAD
tqdm==4.67.0
+=======
+tqdm==4.67.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# nltk
@@ -1562,8 +1624,15 @@ webob==1.8.9
# via
# -r requirements/edx/base.txt
# xblock
+<<<<<<< HEAD
wrapt==1.16.0
# via -r requirements/edx/base.txt
+=======
+wrapt==1.17.0
+ # via
+ # -r requirements/edx/base.txt
+ # astroid
+>>>>>>> master
xblock[django]==5.1.0
# via
# -r requirements/edx/base.txt
@@ -1579,6 +1648,7 @@ xblock[django]==5.1.0
# xblock-drag-and-drop-v2
# xblock-google-drive
# xblock-utils
+ # xblocks-contrib
xblock-drag-and-drop-v2==4.0.3
# via -r requirements/edx/base.txt
xblock-google-drive==0.7.0
@@ -1590,13 +1660,19 @@ xblock-utils==4.0.0
# -r requirements/edx/base.txt
# edx-sga
# xblock-poll
+xblocks-contrib==0.1.0
+ # via -r requirements/edx/base.txt
xmlsec==1.3.14
# via
# -r requirements/edx/base.txt
# python3-saml
xss-utils==0.6.0
# via -r requirements/edx/base.txt
+<<<<<<< HEAD
yarl==1.17.2
+=======
+yarl==1.18.3
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# aiohttp
diff --git a/requirements/edx/kernel.in b/requirements/edx/kernel.in
index 7323c243accf..60f49c5917e1 100644
--- a/requirements/edx/kernel.in
+++ b/requirements/edx/kernel.in
@@ -119,6 +119,7 @@ openedx-calc # Library supporting mathematical calculatio
openedx-django-require
openedx-events # Open edX Events from Hooks Extension Framework (OEP-50)
openedx-filters # Open edX Filters from Hooks Extension Framework (OEP-50)
+openedx-forum # Open edX forum v2 application
openedx-learning # Open edX Learning core (experimental)
openedx-mongodbproxy
openedx-django-wiki
diff --git a/requirements/edx/paver.txt b/requirements/edx/paver.txt
index 9f297db1926d..c9ee8f3aff49 100644
--- a/requirements/edx/paver.txt
+++ b/requirements/edx/paver.txt
@@ -47,11 +47,11 @@ python-memcached==1.62
# via -r requirements/edx/paver.in
requests==2.32.3
# via -r requirements/edx/paver.in
-six==1.16.0
+six==1.17.0
# via
# libsass
# paver
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r requirements/edx/paver.in
# edx-opaque-keys
@@ -61,5 +61,5 @@ urllib3==2.2.3
# via requests
watchdog==6.0.0
# via -r requirements/edx/paver.in
-wrapt==1.16.0
+wrapt==1.17.0
# via -r requirements/edx/paver.in
diff --git a/requirements/edx/semgrep.txt b/requirements/edx/semgrep.txt
index 153084bb164b..98481fc8d00a 100644
--- a/requirements/edx/semgrep.txt
+++ b/requirements/edx/semgrep.txt
@@ -108,7 +108,11 @@ requests==2.32.3
# semgrep
rich==13.5.3
# via semgrep
+<<<<<<< HEAD
rpds-py==0.21.0
+=======
+rpds-py==0.22.3
+>>>>>>> master
# via
# jsonschema
# referencing
@@ -116,7 +120,11 @@ ruamel-yaml==0.17.40
# via semgrep
ruamel-yaml-clib==0.2.12
# via ruamel-yaml
+<<<<<<< HEAD
semgrep==1.96.0
+=======
+semgrep==1.97.0
+>>>>>>> master
# via -r requirements/edx/semgrep.in
tomli==2.0.2
# via semgrep
@@ -130,7 +138,7 @@ urllib3==2.2.3
# semgrep
wcmatch==8.5.2
# via semgrep
-wrapt==1.16.0
+wrapt==1.17.0
# via
# deprecated
# opentelemetry-instrumentation
diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt
index 5328e04feb1e..c1b93657bb7d 100644
--- a/requirements/edx/testing.txt
+++ b/requirements/edx/testing.txt
@@ -8,11 +8,15 @@
# via -r requirements/edx/base.txt
acid-xblock==0.4.1
# via -r requirements/edx/base.txt
-aiohappyeyeballs==2.4.3
+aiohappyeyeballs==2.4.4
# via
# -r requirements/edx/base.txt
# aiohttp
+<<<<<<< HEAD
aiohttp==3.11.4
+=======
+aiohttp==3.11.9
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# geoip2
@@ -39,7 +43,7 @@ annotated-types==0.7.0
# via
# -r requirements/edx/base.txt
# pydantic
-anyio==4.6.2.post1
+anyio==4.7.0
# via starlette
appdirs==1.4.4
# via
@@ -78,7 +82,7 @@ backoff==1.10.0
# via
# -r requirements/edx/base.txt
# analytics-python
-bcrypt==4.2.0
+bcrypt==4.2.1
# via
# -r requirements/edx/base.txt
# paramiko
@@ -86,6 +90,7 @@ beautifulsoup4==4.12.3
# via
# -r requirements/edx/base.txt
# -r requirements/edx/testing.in
+ # openedx-forum
# pynliner
billiard==4.2.1
# via
@@ -102,13 +107,21 @@ bleach[css]==6.2.0
# xblock-poll
boto==2.49.0
# via -r requirements/edx/base.txt
+<<<<<<< HEAD
boto3==1.35.64
+=======
+boto3==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# django-ses
# fs-s3fs
# ora2
+<<<<<<< HEAD
botocore==1.35.64
+=======
+botocore==1.35.76
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# boto3
@@ -198,7 +211,11 @@ click-repl==0.3.0
# via
# -r requirements/edx/base.txt
# celery
+<<<<<<< HEAD
code-annotations==1.8.1
+=======
+code-annotations==2.0.0
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# -r requirements/edx/testing.in
@@ -209,13 +226,17 @@ codejail-includes==1.0.0
# via -r requirements/edx/base.txt
colorama==0.4.6
# via tox
+<<<<<<< HEAD
coverage[toml]==7.6.7
+=======
+coverage[toml]==7.6.8
+>>>>>>> master
# via
# -r requirements/edx/coverage.txt
# pytest-cov
crowdsourcehinter-xblock==0.8
# via -r requirements/edx/base.txt
-cryptography==43.0.3
+cryptography==44.0.0
# via
# -r requirements/edx/base.txt
# django-fernet-fields-v2
@@ -251,7 +272,7 @@ dill==0.3.9
# via pylint
distlib==0.3.9
# via virtualenv
-django==4.2.16
+django==4.2.17
# via
# -c requirements/edx/../common_constraints.txt
# -c requirements/edx/../constraints.txt
@@ -317,6 +338,7 @@ django==4.2.16
# openedx-django-wiki
# openedx-events
# openedx-filters
+ # openedx-forum
# openedx-learning
# ora2
# social-auth-app-django
@@ -427,7 +449,7 @@ django-sekizai==4.1.0
# via
# -r requirements/edx/base.txt
# openedx-django-wiki
-django-ses==4.2.0
+django-ses==4.3.0
# via -r requirements/edx/base.txt
django-simple-history==3.4.0
# via
@@ -438,12 +460,13 @@ django-simple-history==3.4.0
# edx-organizations
# edx-proctoring
# ora2
-django-statici18n==2.5.0
+django-statici18n==2.6.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
# xblock-drag-and-drop-v2
# xblock-poll
+ # xblocks-contrib
django-storages==1.14.3
# via
# -c requirements/edx/../constraints.txt
@@ -481,6 +504,7 @@ djangorestframework==3.14.0
# edx-organizations
# edx-proctoring
# edx-submissions
+ # openedx-forum
# openedx-learning
# ora2
# super-csv
@@ -498,7 +522,7 @@ drf-jwt==1.19.2
# via
# -r requirements/edx/base.txt
# edx-drf-extensions
-drf-spectacular==0.27.2
+drf-spectacular==0.28.0
# via -r requirements/edx/base.txt
drf-yasg==1.21.8
# via
@@ -521,7 +545,7 @@ edx-bulk-grades==1.1.0
# via
# -r requirements/edx/base.txt
# staff-graded-xblock
-edx-ccx-keys==1.3.0
+edx-ccx-keys==2.0.2
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
@@ -542,7 +566,7 @@ edx-django-release-util==1.4.0
# edxval
edx-django-sites-extensions==4.2.0
# via -r requirements/edx/base.txt
-edx-django-utils==7.0.0
+edx-django-utils==7.1.0
# via
# -r requirements/edx/base.txt
# django-config-models
@@ -571,7 +595,7 @@ edx-drf-extensions==10.5.0
# edx-when
# edxval
# openedx-learning
-edx-enterprise==4.32.3
+edx-enterprise==5.4.2
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
@@ -584,6 +608,7 @@ edx-i18n-tools==1.5.0
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
# ora2
+ # xblocks-contrib
edx-lint==5.4.1
# via -r requirements/edx/testing.in
edx-milestones==0.6.0
@@ -607,7 +632,7 @@ edx-opaque-keys[django]==2.11.0
# ora2
edx-organizations==6.13.0
# via -r requirements/edx/base.txt
-edx-proctoring==4.18.3
+edx-proctoring==4.18.4
# via
# -r requirements/edx/base.txt
# edx-proctoring-proctortrack
@@ -621,7 +646,9 @@ edx-rest-api-client==6.0.0
# edx-enterprise
# edx-proctoring
edx-search==4.1.1
- # via -r requirements/edx/base.txt
+ # via
+ # -r requirements/edx/base.txt
+ # openedx-forum
edx-sga==0.25.0
# via -r requirements/edx/base.txt
edx-submissions==3.8.3
@@ -657,6 +684,7 @@ elasticsearch==7.9.1
# -c requirements/edx/../common_constraints.txt
# -r requirements/edx/base.txt
# edx-search
+ # openedx-forum
enmerkar==0.7.1
# via
# -r requirements/edx/base.txt
@@ -674,9 +702,15 @@ execnet==2.1.1
# via pytest-xdist
factory-boy==3.3.1
# via -r requirements/edx/testing.in
+<<<<<<< HEAD
faker==33.0.0
# via factory-boy
fastapi==0.115.5
+=======
+faker==33.1.0
+ # via factory-boy
+fastapi==0.115.6
+>>>>>>> master
# via pact-python
fastavro==1.9.7
# via
@@ -725,7 +759,11 @@ google-api-core[grpc]==2.23.0
# google-cloud-core
# google-cloud-firestore
# google-cloud-storage
+<<<<<<< HEAD
google-api-python-client==2.153.0
+=======
+google-api-python-client==2.154.0
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# firebase-admin
@@ -751,7 +789,7 @@ google-cloud-firestore==2.19.0
# via
# -r requirements/edx/base.txt
# firebase-admin
-google-cloud-storage==2.18.2
+google-cloud-storage==2.19.0
# via
# -r requirements/edx/base.txt
# firebase-admin
@@ -771,12 +809,20 @@ googleapis-common-protos==1.66.0
# grpcio-status
grimp==3.5
# via import-linter
+<<<<<<< HEAD
grpcio==1.68.0
+=======
+grpcio==1.68.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# google-api-core
# grpcio-status
+<<<<<<< HEAD
grpcio-status==1.68.0
+=======
+grpcio-status==1.68.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# google-api-core
@@ -797,7 +843,7 @@ httplib2==0.22.0
# google-auth-httplib2
httpretty==1.1.4
# via -r requirements/edx/testing.in
-icalendar==6.0.1
+icalendar==6.1.0
# via -r requirements/edx/base.txt
idna==3.10
# via
@@ -917,7 +963,7 @@ lxml-html-clean==0.4.1
# lxml
mailsnake==1.6.4
# via -r requirements/edx/base.txt
-mako==1.3.6
+mako==1.3.7
# via
# -r requirements/edx/base.txt
# acid-xblock
@@ -946,7 +992,7 @@ maxminddb==2.6.2
# geoip2
mccabe==0.7.0
# via pylint
-meilisearch==0.31.6
+meilisearch==0.33.0
# via
# -r requirements/edx/base.txt
# edx-search
@@ -977,12 +1023,19 @@ multidict==6.1.0
# aiohttp
# yarl
mysqlclient==2.2.6
+<<<<<<< HEAD
# via -r requirements/edx/base.txt
newrelic==10.3.0
+=======
+ # via
+ # -r requirements/edx/base.txt
+ # openedx-forum
+newrelic==10.3.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# edx-django-utils
-nh3==0.2.18
+nh3==0.2.19
# via -r requirements/edx/base.txt
nltk==3.9.1
# via
@@ -1013,14 +1066,17 @@ openai==0.28.1
# -r requirements/edx/base.txt
# edx-enterprise
openedx-atlas==0.6.2
- # via -r requirements/edx/base.txt
-openedx-calc==3.1.2
+ # via
+ # -r requirements/edx/base.txt
+ # openedx-forum
+openedx-calc==4.0.1
# via -r requirements/edx/base.txt
openedx-django-pyfs==3.7.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
# xblock
+ # xblocks-contrib
openedx-django-require==2.1.0
# via -r requirements/edx/base.txt
openedx-django-wiki==2.1.0
@@ -1039,7 +1095,9 @@ openedx-filters==1.11.0
# -r requirements/edx/base.txt
# lti-consumer-xblock
# ora2
-openedx-learning==0.17.0
+openedx-forum==0.1.5
+ # via -r requirements/edx/base.txt
+openedx-learning==0.18.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
@@ -1049,7 +1107,7 @@ optimizely-sdk==4.1.1
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
-ora2==6.14.0
+ora2==6.14.1
# via -r requirements/edx/base.txt
packaging==24.2
# via
@@ -1124,7 +1182,7 @@ prompt-toolkit==3.0.48
# via
# -r requirements/edx/base.txt
# click-repl
-propcache==0.2.0
+propcache==0.2.1
# via
# -r requirements/edx/base.txt
# aiohttp
@@ -1134,7 +1192,7 @@ proto-plus==1.25.0
# -r requirements/edx/base.txt
# google-api-core
# google-cloud-firestore
-protobuf==5.28.3
+protobuf==5.29.1
# via
# -r requirements/edx/base.txt
# google-api-core
@@ -1178,12 +1236,12 @@ pycryptodomex==3.21.0
# edx-proctoring
# lti-consumer-xblock
# pyjwkest
-pydantic==2.9.2
+pydantic==2.10.3
# via
# -r requirements/edx/base.txt
# camel-converter
# fastapi
-pydantic-core==2.23.4
+pydantic-core==2.27.1
# via
# -r requirements/edx/base.txt
# pydantic
@@ -1198,7 +1256,11 @@ pyjwkest==1.4.2
# -r requirements/edx/base.txt
# edx-token-utils
# lti-consumer-xblock
+<<<<<<< HEAD
pyjwt[crypto]==2.10.0
+=======
+pyjwt[crypto]==2.10.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# drf-jwt
@@ -1242,6 +1304,7 @@ pymongo==4.4.0
# edx-opaque-keys
# event-tracking
# mongoengine
+ # openedx-forum
# openedx-mongodbproxy
pynacl==1.5.0
# via
@@ -1250,7 +1313,7 @@ pynacl==1.5.0
# paramiko
pynliner==0.8.0
# via -r requirements/edx/base.txt
-pyopenssl==24.2.1
+pyopenssl==24.3.0
# via
# -r requirements/edx/base.txt
# optimizely-sdk
@@ -1273,7 +1336,11 @@ pysrt==1.1.2
# via
# -r requirements/edx/base.txt
# edxval
+<<<<<<< HEAD
pytest==8.2.0
+=======
+pytest==8.3.4
+>>>>>>> master
# via
# -r requirements/edx/testing.in
# pylint-pytest
@@ -1398,6 +1465,7 @@ requests==2.32.3
# mailsnake
# meilisearch
# openai
+ # openedx-forum
# optimizely-sdk
# pact-python
# pyjwkest
@@ -1413,7 +1481,11 @@ requests-oauthlib==2.0.0
# via
# -r requirements/edx/base.txt
# social-auth-core
+<<<<<<< HEAD
rpds-py==0.21.0
+=======
+rpds-py==0.22.3
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# jsonschema
@@ -1428,7 +1500,7 @@ rules==3.5
# edx-enterprise
# edx-proctoring
# openedx-learning
-s3transfer==0.10.3
+s3transfer==0.10.4
# via
# -r requirements/edx/base.txt
# boto3
@@ -1456,7 +1528,7 @@ simplejson==3.19.3
# xblock-utils
singledispatch==4.1.0
# via -r requirements/edx/testing.in
-six==1.16.0
+six==1.17.0
# via
# -r requirements/edx/base.txt
# analytics-python
@@ -1489,7 +1561,7 @@ slumber==0.7.1
# edx-enterprise
sniffio==1.3.1
# via anyio
-snowflake-connector-python==3.12.3
+snowflake-connector-python==3.12.4
# via
# -r requirements/edx/base.txt
# edx-enterprise
@@ -1523,7 +1595,7 @@ staff-graded-xblock==2.3.0
# via -r requirements/edx/base.txt
starlette==0.41.3
# via fastapi
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r requirements/edx/base.txt
# code-annotations
@@ -1559,7 +1631,11 @@ tomlkit==0.13.2
# snowflake-connector-python
tox==4.23.2
# via -r requirements/edx/testing.in
+<<<<<<< HEAD
tqdm==4.67.0
+=======
+tqdm==4.67.1
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# nltk
@@ -1567,6 +1643,7 @@ tqdm==4.67.0
typing-extensions==4.12.2
# via
# -r requirements/edx/base.txt
+ # anyio
# django-countries
# edx-opaque-keys
# faker
@@ -1605,7 +1682,7 @@ urllib3==2.2.3
# requests
user-util==1.1.0
# via -r requirements/edx/base.txt
-uvicorn==0.32.0
+uvicorn==0.32.1
# via pact-python
vine==5.1.0
# via
@@ -1613,7 +1690,7 @@ vine==5.1.0
# amqp
# celery
# kombu
-virtualenv==20.27.1
+virtualenv==20.28.0
# via tox
voluptuous==0.15.2
# via
@@ -1647,8 +1724,15 @@ webob==1.8.9
# via
# -r requirements/edx/base.txt
# xblock
+<<<<<<< HEAD
wrapt==1.16.0
# via -r requirements/edx/base.txt
+=======
+wrapt==1.17.0
+ # via
+ # -r requirements/edx/base.txt
+ # astroid
+>>>>>>> master
xblock[django]==5.1.0
# via
# -r requirements/edx/base.txt
@@ -1664,6 +1748,7 @@ xblock[django]==5.1.0
# xblock-drag-and-drop-v2
# xblock-google-drive
# xblock-utils
+ # xblocks-contrib
xblock-drag-and-drop-v2==4.0.3
# via -r requirements/edx/base.txt
xblock-google-drive==0.7.0
@@ -1675,13 +1760,19 @@ xblock-utils==4.0.0
# -r requirements/edx/base.txt
# edx-sga
# xblock-poll
+xblocks-contrib==0.1.0
+ # via -r requirements/edx/base.txt
xmlsec==1.3.14
# via
# -r requirements/edx/base.txt
# python3-saml
xss-utils==0.6.0
# via -r requirements/edx/base.txt
+<<<<<<< HEAD
yarl==1.17.2
+=======
+yarl==1.18.3
+>>>>>>> master
# via
# -r requirements/edx/base.txt
# aiohttp
diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt
index b99cbb6be456..c5a5c5b6fea5 100644
--- a/requirements/pip-tools.txt
+++ b/requirements/pip-tools.txt
@@ -18,7 +18,7 @@ pyproject-hooks==1.2.0
# via
# build
# pip-tools
-wheel==0.45.0
+wheel==0.45.1
# via pip-tools
# The following packages are considered to be unsafe in a requirements file:
diff --git a/requirements/pip.txt b/requirements/pip.txt
index dc5fcdc8f714..0bdb9d7ac387 100644
--- a/requirements/pip.txt
+++ b/requirements/pip.txt
@@ -4,7 +4,7 @@
#
# make upgrade
#
-wheel==0.45.0
+wheel==0.45.1
# via -r requirements/pip.in
# The following packages are considered to be unsafe in a requirements file:
@@ -12,5 +12,5 @@ pip==24.2
# via
# -c requirements/common_constraints.txt
# -r requirements/pip.in
-setuptools==75.5.0
+setuptools==75.6.0
# via -r requirements/pip.in
diff --git a/scripts/eslint.py b/scripts/eslint.py
new file mode 100644
index 000000000000..3723ada6e219
--- /dev/null
+++ b/scripts/eslint.py
@@ -0,0 +1,73 @@
+""" # pylint: disable=django-not-configured
+Check code quality using eslint.
+"""
+
+import re
+import subprocess
+import shlex
+import sys
+
+
+class BuildFailure(Exception):
+ pass
+
+
+def fail_quality(message):
+ """
+ Fail the specified quality check.
+ """
+
+ raise BuildFailure(message)
+
+
+def run_eslint():
+ """
+ Runs eslint on static asset directories.
+ If limit option is passed, fails build if more violations than the limit are found.
+ """
+ violations_limit = 734
+
+ command = [
+ "node",
+ "--max_old_space_size=4096",
+ "node_modules/.bin/eslint",
+ "--ext", ".js",
+ "--ext", ".jsx",
+ "--format=compact",
+ "lms",
+ "cms",
+ "common",
+ "openedx",
+ "xmodule",
+ ]
+ print("Running command:", shlex.join(command))
+ result = subprocess.run(
+ command,
+ text=True,
+ check=False,
+ capture_output=True
+ )
+
+ print(result.stdout)
+ last_line = result.stdout.strip().splitlines()[-1] if result.stdout.strip().splitlines() else ""
+ regex = r'^\d+'
+ try:
+ num_violations = int(re.search(regex, last_line).group(0)) if last_line else 0
+ # Fail if number of violations is greater than the limit
+ if num_violations > violations_limit:
+ fail_quality(
+ "FAILURE: Too many eslint violations ({count}).\nThe limit is {violations_limit}.".format(count=num_violations, violations_limit=violations_limit))
+ else:
+ print(f"successfully run eslint with '{num_violations}' violations")
+
+ # An AttributeError will occur if the regex finds no matches.
+ except (AttributeError, ValueError):
+ fail_quality(f"FAILURE: Number of eslint violations could not be found in '{last_line}'")
+
+
+if __name__ == "__main__":
+ try:
+ run_eslint()
+ except BuildFailure as e:
+ print(e)
+ sys.exit(1)
diff --git a/scripts/generic-ci-tests.sh b/scripts/generic-ci-tests.sh
deleted file mode 100755
index 54b9cbb9d500..000000000000
--- a/scripts/generic-ci-tests.sh
+++ /dev/null
@@ -1,122 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-###############################################################################
-#
-# generic-ci-tests.sh
-#
-# Execute some tests for edx-platform.
-# (Most other tests are run by invoking `pytest`, `pylint`, etc. directly)
-#
-# This script can be called from CI jobs that define
-# these environment variables:
-#
-# `TEST_SUITE` defines which kind of test to run.
-# Possible values are:
-#
-# - "quality": Run the quality (pycodestyle/pylint) checks
-# - "js-unit": Run the JavaScript tests
-# - "pavelib-js-unit": Run the JavaScript tests and the Python unit
-# tests from the pavelib/lib directory
-#
-###############################################################################
-
-# Clean up previous builds
-git clean -qxfd
-
-function emptyxunit {
-
- cat > "reports/$1.xml" <
-
-
-
-END
-
-}
-
-# if specified tox environment is supported, prepend paver commands
-# with tox env invocation
-if [ -z ${TOX_ENV+x} ] || [[ ${TOX_ENV} == 'null' ]]; then
- echo "TOX_ENV: ${TOX_ENV}"
- TOX=""
-elif tox -l |grep -q "${TOX_ENV}"; then
- if [[ "${TOX_ENV}" == 'quality' ]]; then
- TOX=""
- else
- TOX="tox -r -e ${TOX_ENV} --"
- fi
-else
- echo "${TOX_ENV} is not currently supported. Please review the"
- echo "tox.ini file to see which environments are supported"
- exit 1
-fi
-
-PAVER_ARGS="-v"
-export SUBSET_JOB=$JOB_NAME
-
-function run_paver_quality {
- QUALITY_TASK=$1
- shift
- mkdir -p test_root/log/
- LOG_PREFIX="test_root/log/$QUALITY_TASK"
- $TOX paver "$QUALITY_TASK" "$@" 2> "$LOG_PREFIX.err.log" > "$LOG_PREFIX.out.log" || {
- echo "STDOUT (last 100 lines of $LOG_PREFIX.out.log):";
- tail -n 100 "$LOG_PREFIX.out.log"
- echo "STDERR (last 100 lines of $LOG_PREFIX.err.log):";
- tail -n 100 "$LOG_PREFIX.err.log"
- return 1;
- }
- return 0;
-}
-
-case "$TEST_SUITE" in
-
- "quality")
- EXIT=0
-
- mkdir -p reports
-
- echo "Finding pycodestyle violations and storing report..."
- run_paver_quality run_pep8 || { EXIT=1; }
- echo "Finding ESLint violations and storing report..."
- run_paver_quality run_eslint -l "$ESLINT_THRESHOLD" || { EXIT=1; }
- echo "Finding Stylelint violations and storing report..."
- run_paver_quality run_stylelint || { EXIT=1; }
- echo "Running xss linter report."
- run_paver_quality run_xsslint -t "$XSSLINT_THRESHOLDS" || { EXIT=1; }
- echo "Running PII checker on all Django models..."
- run_paver_quality run_pii_check || { EXIT=1; }
- echo "Running reserved keyword checker on all Django models..."
- run_paver_quality check_keywords || { EXIT=1; }
-
- # Need to create an empty test result so the post-build
- # action doesn't fail the build.
- emptyxunit "stub"
- exit "$EXIT"
- ;;
-
- "js-unit")
- $TOX paver test_js --coverage
- $TOX paver diff_coverage
- ;;
-
- "pavelib-js-unit")
- EXIT=0
- $TOX paver test_js --coverage --skip-clean || { EXIT=1; }
- paver test_lib --skip-clean $PAVER_ARGS || { EXIT=1; }
-
- # This is to ensure that the build status of the shard is properly set.
- # Because we are running two paver commands in a row, we need to capture
- # their return codes in order to exit with a non-zero code if either of
- # them fail. We put the || clause there because otherwise, when a paver
- # command fails, this entire script will exit, and not run the second
- # paver command in this case statement. So instead of exiting, the value
- # of a variable named EXIT will be set to 1 if either of the paver
- # commands fail. We then use this variable's value as our exit code.
- # Note that by default the value of this variable EXIT is not set, so if
- # neither command fails then the exit command resolves to simply exit
- # which is considered successful.
- exit "$EXIT"
- ;;
-esac
diff --git a/scripts/structures_pruning/requirements/base.txt b/scripts/structures_pruning/requirements/base.txt
index a3fcacad2f7e..b15cb81f29ee 100644
--- a/scripts/structures_pruning/requirements/base.txt
+++ b/scripts/structures_pruning/requirements/base.txt
@@ -22,7 +22,7 @@ pymongo==4.4.0
# -c scripts/structures_pruning/requirements/../../../requirements/constraints.txt
# -r scripts/structures_pruning/requirements/base.in
# edx-opaque-keys
-stevedore==5.3.0
+stevedore==5.4.0
# via edx-opaque-keys
typing-extensions==4.12.2
# via edx-opaque-keys
diff --git a/scripts/structures_pruning/requirements/testing.txt b/scripts/structures_pruning/requirements/testing.txt
index c0f645997f01..e121a05143fa 100644
--- a/scripts/structures_pruning/requirements/testing.txt
+++ b/scripts/structures_pruning/requirements/testing.txt
@@ -32,9 +32,9 @@ pymongo==4.4.0
# via
# -r scripts/structures_pruning/requirements/base.txt
# edx-opaque-keys
-pytest==8.3.3
+pytest==8.3.4
# via -r scripts/structures_pruning/requirements/testing.in
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r scripts/structures_pruning/requirements/base.txt
# edx-opaque-keys
diff --git a/scripts/user_retirement/requirements/base.txt b/scripts/user_retirement/requirements/base.txt
index e326343c0f5b..a98302aa009b 100644
--- a/scripts/user_retirement/requirements/base.txt
+++ b/scripts/user_retirement/requirements/base.txt
@@ -10,9 +10,15 @@ attrs==24.2.0
# via zeep
backoff==2.2.1
# via -r scripts/user_retirement/requirements/base.in
+<<<<<<< HEAD
boto3==1.35.64
# via -r scripts/user_retirement/requirements/base.in
botocore==1.35.64
+=======
+boto3==1.35.76
+ # via -r scripts/user_retirement/requirements/base.in
+botocore==1.35.76
+>>>>>>> master
# via
# boto3
# s3transfer
@@ -33,9 +39,9 @@ click==8.1.6
# -c scripts/user_retirement/requirements/../../../requirements/constraints.txt
# -r scripts/user_retirement/requirements/base.in
# edx-django-utils
-cryptography==43.0.3
+cryptography==44.0.0
# via pyjwt
-django==4.2.16
+django==4.2.17
# via
# -c scripts/user_retirement/requirements/../../../requirements/common_constraints.txt
# -c scripts/user_retirement/requirements/../../../requirements/constraints.txt
@@ -46,13 +52,17 @@ django-crum==0.7.9
# via edx-django-utils
django-waffle==4.2.0
# via edx-django-utils
-edx-django-utils==7.0.0
+edx-django-utils==7.1.0
# via edx-rest-api-client
edx-rest-api-client==6.0.0
# via -r scripts/user_retirement/requirements/base.in
google-api-core==2.23.0
# via google-api-python-client
+<<<<<<< HEAD
google-api-python-client==2.153.0
+=======
+google-api-python-client==2.154.0
+>>>>>>> master
# via -r scripts/user_retirement/requirements/base.in
google-auth==2.36.0
# via
@@ -81,7 +91,11 @@ lxml==5.3.0
# via zeep
more-itertools==10.5.0
# via simple-salesforce
+<<<<<<< HEAD
newrelic==10.3.0
+=======
+newrelic==10.3.1
+>>>>>>> master
# via edx-django-utils
pbr==6.1.0
# via stevedore
@@ -89,7 +103,7 @@ platformdirs==4.3.6
# via zeep
proto-plus==1.25.0
# via google-api-core
-protobuf==5.28.3
+protobuf==5.29.1
# via
# google-api-core
# googleapis-common-protos
@@ -104,7 +118,11 @@ pyasn1-modules==0.4.1
# via google-auth
pycparser==2.22
# via cffi
+<<<<<<< HEAD
pyjwt[crypto]==2.10.0
+=======
+pyjwt[crypto]==2.10.1
+>>>>>>> master
# via
# edx-rest-api-client
# simple-salesforce
@@ -136,19 +154,19 @@ requests-toolbelt==1.0.0
# via zeep
rsa==4.9
# via google-auth
-s3transfer==0.10.3
+s3transfer==0.10.4
# via boto3
simple-salesforce==1.12.6
# via -r scripts/user_retirement/requirements/base.in
simplejson==3.19.3
# via -r scripts/user_retirement/requirements/base.in
-six==1.16.0
+six==1.17.0
# via
# jenkinsapi
# python-dateutil
sqlparse==0.5.2
# via django
-stevedore==5.3.0
+stevedore==5.4.0
# via edx-django-utils
typing-extensions==4.12.2
# via simple-salesforce
diff --git a/scripts/user_retirement/requirements/testing.txt b/scripts/user_retirement/requirements/testing.txt
index 32152877688e..3cbe83bf6be7 100644
--- a/scripts/user_retirement/requirements/testing.txt
+++ b/scripts/user_retirement/requirements/testing.txt
@@ -14,11 +14,19 @@ attrs==24.2.0
# zeep
backoff==2.2.1
# via -r scripts/user_retirement/requirements/base.txt
+<<<<<<< HEAD
boto3==1.35.64
# via
# -r scripts/user_retirement/requirements/base.txt
# moto
botocore==1.35.64
+=======
+boto3==1.35.76
+ # via
+ # -r scripts/user_retirement/requirements/base.txt
+ # moto
+botocore==1.35.76
+>>>>>>> master
# via
# -r scripts/user_retirement/requirements/base.txt
# boto3
@@ -45,14 +53,14 @@ click==8.1.6
# via
# -r scripts/user_retirement/requirements/base.txt
# edx-django-utils
-cryptography==43.0.3
+cryptography==44.0.0
# via
# -r scripts/user_retirement/requirements/base.txt
# moto
# pyjwt
ddt==1.7.2
# via -r scripts/user_retirement/requirements/testing.in
-django==4.2.16
+django==4.2.17
# via
# -r scripts/user_retirement/requirements/base.txt
# django-crum
@@ -66,7 +74,7 @@ django-waffle==4.2.0
# via
# -r scripts/user_retirement/requirements/base.txt
# edx-django-utils
-edx-django-utils==7.0.0
+edx-django-utils==7.1.0
# via
# -r scripts/user_retirement/requirements/base.txt
# edx-rest-api-client
@@ -76,7 +84,11 @@ google-api-core==2.23.0
# via
# -r scripts/user_retirement/requirements/base.txt
# google-api-python-client
+<<<<<<< HEAD
google-api-python-client==2.153.0
+=======
+google-api-python-client==2.154.0
+>>>>>>> master
# via -r scripts/user_retirement/requirements/base.txt
google-auth==2.36.0
# via
@@ -132,7 +144,11 @@ more-itertools==10.5.0
# simple-salesforce
moto==4.2.14
# via -r scripts/user_retirement/requirements/testing.in
+<<<<<<< HEAD
newrelic==10.3.0
+=======
+newrelic==10.3.1
+>>>>>>> master
# via
# -r scripts/user_retirement/requirements/base.txt
# edx-django-utils
@@ -152,7 +168,7 @@ proto-plus==1.25.0
# via
# -r scripts/user_retirement/requirements/base.txt
# google-api-core
-protobuf==5.28.3
+protobuf==5.29.1
# via
# -r scripts/user_retirement/requirements/base.txt
# google-api-core
@@ -175,7 +191,11 @@ pycparser==2.22
# via
# -r scripts/user_retirement/requirements/base.txt
# cffi
+<<<<<<< HEAD
pyjwt[crypto]==2.10.0
+=======
+pyjwt[crypto]==2.10.1
+>>>>>>> master
# via
# -r scripts/user_retirement/requirements/base.txt
# edx-rest-api-client
@@ -188,7 +208,7 @@ pyparsing==3.2.0
# via
# -r scripts/user_retirement/requirements/base.txt
# httplib2
-pytest==8.3.3
+pytest==8.3.4
# via -r scripts/user_retirement/requirements/testing.in
python-dateutil==2.9.0.post0
# via
@@ -235,7 +255,7 @@ rsa==4.9
# via
# -r scripts/user_retirement/requirements/base.txt
# google-auth
-s3transfer==0.10.3
+s3transfer==0.10.4
# via
# -r scripts/user_retirement/requirements/base.txt
# boto3
@@ -243,7 +263,7 @@ simple-salesforce==1.12.6
# via -r scripts/user_retirement/requirements/base.txt
simplejson==3.19.3
# via -r scripts/user_retirement/requirements/base.txt
-six==1.16.0
+six==1.17.0
# via
# -r scripts/user_retirement/requirements/base.txt
# jenkinsapi
@@ -252,7 +272,7 @@ sqlparse==0.5.2
# via
# -r scripts/user_retirement/requirements/base.txt
# django
-stevedore==5.3.0
+stevedore==5.4.0
# via
# -r scripts/user_retirement/requirements/base.txt
# edx-django-utils
diff --git a/scripts/xsslint/xss_linter.py b/scripts/xsslint/xss_linter.py
index a35038c3de6d..b32c54aa5cd7 100755
--- a/scripts/xsslint/xss_linter.py
+++ b/scripts/xsslint/xss_linter.py
@@ -4,6 +4,316 @@
"""
+import argparse
+import importlib
+import json
+import os
+import re
+import sys
+
+from functools import reduce
+from io import StringIO
+from xsslint.reporting import SummaryResults
+from xsslint.rules import RuleSet
+from xsslint.utils import is_skip_dir
+
+
+class BuildFailure(Exception):
+ pass
+
+
+def fail_quality(message):
+ """
+ Fail the specified quality check.
+ """
+
+ raise BuildFailure(message)
+
+
+def _load_config_module(module_path):
+ cwd = os.getcwd()
+ if cwd not in sys.path:
+ # Enable config module to be imported relative to wherever the script was run from.
+ sys.path.append(cwd)
+ return importlib.import_module(module_path)
+
+
+def _build_ruleset(template_linters):
+ """
+ Combines the RuleSets from the provided template_linters into a single, aggregate RuleSet.
+
+ Arguments:
+ template_linters: A list of linting objects.
+
+ Returns:
+ The combined RuleSet.
+ """
+ return reduce(
+ lambda combined, current: combined + current.ruleset,
+ template_linters,
+ RuleSet()
+ )
+
+
+def _process_file(full_path, template_linters, options, summary_results, out):
+ """
+ For each linter, lints the provided file. This means finding and printing
+ violations.
+
+ Arguments:
+ full_path: The full path of the file to lint.
+ template_linters: A list of linting objects.
+ options: A list of the options.
+ summary_results: A SummaryResults with a summary of the violations.
+ out: output file
+
+ """
+ num_violations = 0
+ directory = os.path.dirname(full_path)
+ file_name = os.path.basename(full_path)
+ try:
+ for template_linter in template_linters:
+ results = template_linter.process_file(directory, file_name)
+ results.print_results(options, summary_results, out)
+ except BaseException as e:
+ raise Exception(f"Failed to process path: {full_path}") from e
+
+
+def _process_os_dir(directory, files, template_linters, options, summary_results, out):
+ """
+ Calls out to lint each file in the passed list of files.
+
+ Arguments:
+ directory: Directory being linted.
+ files: All files in the directory to be linted.
+ template_linters: A list of linting objects.
+ options: A list of the options.
+ summary_results: A SummaryResults with a summary of the violations.
+ out: output file
+
+ """
+ for current_file in sorted(files, key=lambda s: s.lower()):
+ full_path = os.path.join(directory, current_file)
+ _process_file(full_path, template_linters, options, summary_results, out)
+
+
+def _process_os_dirs(starting_dir, template_linters, options, summary_results, out):
+ """
+ For each linter, lints all the directories in the starting directory.
+
+ Arguments:
+ starting_dir: The initial directory to begin the walk.
+ template_linters: A list of linting objects.
+ options: A list of the options.
+ summary_results: A SummaryResults with a summary of the violations.
+ out: output file
+
+ """
+ skip_dirs = options.get('skip_dirs', ())
+ for root, dirs, files in os.walk(starting_dir):
+ if is_skip_dir(skip_dirs, root):
+ del dirs
+ continue
+ dirs.sort(key=lambda s: s.lower())
+ _process_os_dir(root, files, template_linters, options, summary_results, out)
+
+
+def _get_xsslint_counts(result_contents):
+ """
+ This returns a dict of violations from the xsslint report.
+
+ Arguments:
+ filename: The name of the xsslint report.
+
+ Returns:
+ A dict containing the following:
+ rules: A dict containing the count for each rule as follows:
+ violation-rule-id: N, where N is the number of violations
+ total: M, where M is the number of total violations
+
+ """
+
+ rule_count_regex = re.compile(r"^(?P[a-z-]+):\s+(?P\d+) violations", re.MULTILINE)
+ total_count_regex = re.compile(r"^(?P\d+) violations total", re.MULTILINE)
+ violations = {'rules': {}}
+ for violation_match in rule_count_regex.finditer(result_contents):
+ try:
+ violations['rules'][violation_match.group('rule_id')] = int(violation_match.group('count'))
+ except ValueError:
+ violations['rules'][violation_match.group('rule_id')] = None
+ try:
+ violations['total'] = int(total_count_regex.search(result_contents).group('count'))
+ # An AttributeError will occur if the regex finds no matches.
+ # A ValueError will occur if the returned regex cannot be cast as a float.
+ except (AttributeError, ValueError):
+ violations['total'] = None
+ return violations
+
+
+def _check_violations(options, results):
+ xsslint_script = "xss_linter.py"
+ try:
+ thresholds_option = options['thresholds']
+ # Read the JSON file
+ with open(thresholds_option, 'r') as file:
+ violation_thresholds = json.load(file)
+
+ except ValueError:
+ violation_thresholds = None
+ if isinstance(violation_thresholds, dict) is False or \
+ any(key not in ("total", "rules") for key in violation_thresholds.keys()):
+ print('xsslint')
+ fail_quality("""FAILURE: Thresholds option "{thresholds_option}" was not supplied using proper format.\n"""
+ """Here is a properly formatted example, '{{"total":100,"rules":{{"javascript-escape":0}}}}' """
+ """with property names in double-quotes.""".format(thresholds_option=thresholds_option))
+
+ try:
+ metrics_str = "Number of {xsslint_script} violations: {num_violations}\n".format(
+ xsslint_script=xsslint_script, num_violations=int(results['total'])
+ )
+ if 'rules' in results and any(results['rules']):
+ metrics_str += "\n"
+ rule_keys = sorted(results['rules'].keys())
+ for rule in rule_keys:
+ metrics_str += "{rule} violations: {count}\n".format(
+ rule=rule,
+ count=int(results['rules'][rule])
+ )
+ except TypeError:
+ print('xsslint')
+ fail_quality("FAILURE: Number of {xsslint_script} violations could not be found".format(
+ xsslint_script=xsslint_script
+ ))
+
+ error_message = ""
+ # Test total violations against threshold.
+ if 'total' in list(violation_thresholds.keys()):
+ if violation_thresholds['total'] < results['total']:
+ error_message = "Too many violations total ({count}).\nThe limit is {violations_limit}.".format(
+ count=results['total'], violations_limit=violation_thresholds['total']
+ )
+
+ # Test rule violations against thresholds.
+ if 'rules' in violation_thresholds:
+ threshold_keys = sorted(violation_thresholds['rules'].keys())
+ for threshold_key in threshold_keys:
+ if threshold_key not in results['rules']:
+ error_message += (
+ "\nNumber of {xsslint_script} violations for {rule} could not be found"
+ ).format(
+ xsslint_script=xsslint_script, rule=threshold_key
+ )
+ elif violation_thresholds['rules'][threshold_key] < results['rules'][threshold_key]:
+ error_message += \
+ "\nToo many {rule} violations ({count}).\nThe {rule} limit is {violations_limit}.".format(
+ rule=threshold_key, count=results['rules'][threshold_key],
+ violations_limit=violation_thresholds['rules'][threshold_key],
+ )
+
+ if error_message:
+ print('xsslint')
+ fail_quality("FAILURE: XSSLinter Failed.\n{error_message}\n"
+ "run the following command to hone in on the problem:\n"
+ "./scripts/xss-commit-linter.sh -h".format(error_message=error_message))
+ else:
+ print("successfully run xsslint")
+
+
+def _lint(file_or_dir, template_linters, options, summary_results, out):
+ """
+ For each linter, lints the provided file or directory.
+
+ Arguments:
+ file_or_dir: The file or initial directory to lint.
+ template_linters: A list of linting objects.
+ options: A list of the options.
+ summary_results: A SummaryResults with a summary of the violations.
+ out: output file
+
+ """
+
+ if file_or_dir is not None and os.path.isfile(file_or_dir):
+ _process_file(file_or_dir, template_linters, options, summary_results, out)
+ else:
+ directory = "."
+ if file_or_dir is not None:
+ if os.path.exists(file_or_dir):
+ directory = file_or_dir
+ else:
+ raise ValueError(f"Path [{file_or_dir}] is not a valid file or directory.")
+ _process_os_dirs(directory, template_linters, options, summary_results, out)
+
+ summary_results.print_results(options, out)
+ result_output = _get_xsslint_counts(out.getvalue())
+ _check_violations(options, result_output)
+
+
+def main():
+ """
+ Used to execute the linter. Use --help option for help.
+
+ Prints all violations.
+ """
+ epilog = "For more help using the xss linter, including details on how to\n"
+ epilog += "understand and fix any violations, read the docs here:\n"
+ epilog += "\n"
+ # pylint: disable=line-too-long
+ epilog += " https://edx.readthedocs.org/projects/edx-developer-guide/en/latest/conventions/preventing_xss.html#xss-linter\n"
+
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description='Checks that templates are safe.',
+ epilog=epilog,
+ )
+ parser.add_argument(
+ '--list-files', dest='list_files', action='store_true',
+ help='Only display the filenames that contain violations.'
+ )
+ parser.add_argument(
+ '--rule-totals', dest='rule_totals', action='store_true',
+ help='Display the totals for each rule.'
+ )
+ parser.add_argument(
+ '--summary-format', dest='summary_format',
+ choices=['eslint', 'json'], default='eslint',
+ help='Choose the display format for the summary.'
+ )
+ parser.add_argument(
+ '--verbose', dest='verbose', action='store_true',
+ help='Print multiple lines where possible for additional context of violations.'
+ )
+ parser.add_argument(
+ '--config', dest='config', action='store', default='xsslint.default_config',
+ help='Specifies the config module to use. The config module should be in Python package syntax.'
+ )
+ parser.add_argument(
+ '--thresholds', dest='thresholds', action='store',
+ help='Specifies the config module to use. The config module should be in Python package syntax.'
+ )
+ parser.add_argument('path', nargs="?", default=None, help='A file to lint or directory to recursively lint.')
+
+ args = parser.parse_args()
+ config = _load_config_module(args.config)
+ options = {
+ 'list_files': args.list_files,
+ 'rule_totals': args.rule_totals,
+ 'summary_format': args.summary_format,
+ 'verbose': args.verbose,
+ 'skip_dirs': getattr(config, 'SKIP_DIRS', ()),
+ 'thresholds': args.thresholds
+ }
+ template_linters = getattr(config, 'LINTERS', ())
+ if not template_linters:
+ raise ValueError(f"LINTERS is empty or undefined in the config module ({args.config}).")
+
+ ruleset = _build_ruleset(template_linters)
+ summary_results = SummaryResults(ruleset)
+ _lint(args.path, template_linters, options, summary_results, out=StringIO())
+
+
if __name__ == "__main__":
- from xsslint.main import main
- main()
+ try:
+ main()
+ except BuildFailure as e:
+ print(e)
+ sys.exit(1)
diff --git a/scripts/xsslint/xsslint/main.py b/scripts/xsslint/xsslint/main.py
deleted file mode 100644
index f8f8672b74b3..000000000000
--- a/scripts/xsslint/xsslint/main.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""
-The main function for the XSS linter.
-"""
-
-
-import argparse
-import importlib
-import os
-import sys
-from functools import reduce
-
-from xsslint.reporting import SummaryResults
-from xsslint.rules import RuleSet
-from xsslint.utils import is_skip_dir
-
-
-def _load_config_module(module_path):
- cwd = os.getcwd()
- if cwd not in sys.path:
- # Enable config module to be imported relative to wherever the script was run from.
- sys.path.append(cwd)
- return importlib.import_module(module_path)
-
-
-def _build_ruleset(template_linters):
- """
- Combines the RuleSets from the provided template_linters into a single, aggregate RuleSet.
-
- Arguments:
- template_linters: A list of linting objects.
-
- Returns:
- The combined RuleSet.
- """
- return reduce(
- lambda combined, current: combined + current.ruleset,
- template_linters,
- RuleSet()
- )
-
-
-def _process_file(full_path, template_linters, options, summary_results, out):
- """
- For each linter, lints the provided file. This means finding and printing
- violations.
-
- Arguments:
- full_path: The full path of the file to lint.
- template_linters: A list of linting objects.
- options: A list of the options.
- summary_results: A SummaryResults with a summary of the violations.
- out: output file
-
- """
- num_violations = 0
- directory = os.path.dirname(full_path)
- file_name = os.path.basename(full_path)
- try:
- for template_linter in template_linters:
- results = template_linter.process_file(directory, file_name)
- results.print_results(options, summary_results, out)
- except BaseException as e:
- raise Exception(f"Failed to process path: {full_path}") from e
-
-
-def _process_os_dir(directory, files, template_linters, options, summary_results, out):
- """
- Calls out to lint each file in the passed list of files.
-
- Arguments:
- directory: Directory being linted.
- files: All files in the directory to be linted.
- template_linters: A list of linting objects.
- options: A list of the options.
- summary_results: A SummaryResults with a summary of the violations.
- out: output file
-
- """
- for current_file in sorted(files, key=lambda s: s.lower()):
- full_path = os.path.join(directory, current_file)
- _process_file(full_path, template_linters, options, summary_results, out)
-
-
-def _process_os_dirs(starting_dir, template_linters, options, summary_results, out):
- """
- For each linter, lints all the directories in the starting directory.
-
- Arguments:
- starting_dir: The initial directory to begin the walk.
- template_linters: A list of linting objects.
- options: A list of the options.
- summary_results: A SummaryResults with a summary of the violations.
- out: output file
-
- """
- skip_dirs = options.get('skip_dirs', ())
- for root, dirs, files in os.walk(starting_dir):
- if is_skip_dir(skip_dirs, root):
- del dirs
- continue
- dirs.sort(key=lambda s: s.lower())
- _process_os_dir(root, files, template_linters, options, summary_results, out)
-
-
-def _lint(file_or_dir, template_linters, options, summary_results, out):
- """
- For each linter, lints the provided file or directory.
-
- Arguments:
- file_or_dir: The file or initial directory to lint.
- template_linters: A list of linting objects.
- options: A list of the options.
- summary_results: A SummaryResults with a summary of the violations.
- out: output file
-
- """
-
- if file_or_dir is not None and os.path.isfile(file_or_dir):
- _process_file(file_or_dir, template_linters, options, summary_results, out)
- else:
- directory = "."
- if file_or_dir is not None:
- if os.path.exists(file_or_dir):
- directory = file_or_dir
- else:
- raise ValueError(f"Path [{file_or_dir}] is not a valid file or directory.")
- _process_os_dirs(directory, template_linters, options, summary_results, out)
-
- summary_results.print_results(options, out)
-
-
-def main():
- """
- Used to execute the linter. Use --help option for help.
-
- Prints all violations.
- """
- epilog = "For more help using the xss linter, including details on how to\n"
- epilog += "understand and fix any violations, read the docs here:\n"
- epilog += "\n"
- # pylint: disable=line-too-long
- epilog += " https://edx.readthedocs.org/projects/edx-developer-guide/en/latest/conventions/preventing_xss.html#xss-linter\n"
-
- parser = argparse.ArgumentParser(
- formatter_class=argparse.RawDescriptionHelpFormatter,
- description='Checks that templates are safe.',
- epilog=epilog,
- )
- parser.add_argument(
- '--list-files', dest='list_files', action='store_true',
- help='Only display the filenames that contain violations.'
- )
- parser.add_argument(
- '--rule-totals', dest='rule_totals', action='store_true',
- help='Display the totals for each rule.'
- )
- parser.add_argument(
- '--summary-format', dest='summary_format',
- choices=['eslint', 'json'], default='eslint',
- help='Choose the display format for the summary.'
- )
- parser.add_argument(
- '--verbose', dest='verbose', action='store_true',
- help='Print multiple lines where possible for additional context of violations.'
- )
- parser.add_argument(
- '--config', dest='config', action='store', default='xsslint.default_config',
- help='Specifies the config module to use. The config module should be in Python package syntax.'
- )
- parser.add_argument('path', nargs="?", default=None, help='A file to lint or directory to recursively lint.')
-
- args = parser.parse_args()
- config = _load_config_module(args.config)
- options = {
- 'list_files': args.list_files,
- 'rule_totals': args.rule_totals,
- 'summary_format': args.summary_format,
- 'verbose': args.verbose,
- 'skip_dirs': getattr(config, 'SKIP_DIRS', ())
- }
- template_linters = getattr(config, 'LINTERS', ())
- if not template_linters:
- raise ValueError(f"LINTERS is empty or undefined in the config module ({args.config}).")
-
- ruleset = _build_ruleset(template_linters)
- summary_results = SummaryResults(ruleset)
- _lint(args.path, template_linters, options, summary_results, out=sys.stdout)
diff --git a/setup.py b/setup.py
index 3b8f8c59498d..3ccfe7734e33 100644
--- a/setup.py
+++ b/setup.py
@@ -138,7 +138,6 @@
],
"lms.djangoapp": [
"ace_common = openedx.core.djangoapps.ace_common.apps:AceCommonConfig",
- "announcements = openedx.features.announcements.apps:AnnouncementsConfig",
"content_libraries = openedx.core.djangoapps.content_libraries.apps:ContentLibrariesConfig",
"course_apps = openedx.core.djangoapps.course_apps.apps:CourseAppsConfig",
"course_live = openedx.core.djangoapps.course_live.apps:CourseLiveConfig",
@@ -157,7 +156,6 @@
"program_enrollments = lms.djangoapps.program_enrollments.apps:ProgramEnrollmentsConfig",
],
"cms.djangoapp": [
- "announcements = openedx.features.announcements.apps:AnnouncementsConfig",
"ace_common = openedx.core.djangoapps.ace_common.apps:AceCommonConfig",
"bookmarks = openedx.core.djangoapps.bookmarks.apps:BookmarksConfig",
"course_live = openedx.core.djangoapps.course_live.apps:CourseLiveConfig",
diff --git a/stylelint.config.js b/stylelint.config.js
deleted file mode 100644
index bd7769911708..000000000000
--- a/stylelint.config.js
+++ /dev/null
@@ -1,3 +0,0 @@
-module.exports = {
- extends: '@edx/stylelint-config-edx'
-};
diff --git a/tox.ini b/tox.ini
index 1b4252fd1905..e5df7f0fbd2f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py{38,311} quality
+envlist = py{311} quality
# This is needed to prevent the lms, cms, and openedx packages inside the "Open
# edX" package (defined in setup.py) from getting installed into site-packages
diff --git a/webpack.common.config.js b/webpack.common.config.js
index 322e252c6ae2..c9b69eef4292 100644
--- a/webpack.common.config.js
+++ b/webpack.common.config.js
@@ -26,6 +26,27 @@ var defineFooter = new RegExp('(' + defineCallFooter.source + ')|('
var staticRootLms = process.env.STATIC_ROOT_LMS || './test_root/staticfiles';
var staticRootCms = process.env.STATIC_ROOT_CMS || (staticRootLms + '/studio');
+class DieHardPlugin {
+ /* A small plugin which ensures that if Webpack fails, it causes the surrounding process to fail
+ * as well. This helps us prevent JavaScript CI from "false passing" upon build failures--that is,
+ * we want to avoid having another situation where the Webpack build breaks under Karma (our
+ * test runner) but Karma just lets it slide and moves on to the next test suite.
+ *
+ * One would imagine that this would be Webpack's default behavior (and maybe it is?) but,
+ * regardless, karma-webpack does not seem to consider Webpack build failures to be fatal errors
+ * without this plugin. We don't fully understand it, but this is good enough given that we plan
+ * to remove all JS in this repo soon (https://github.com/openedx/edx-platform/issues/31620).
+ *
+ * Inpsired by: https://github.com/codymikol/karma-webpack/issues/49#issuecomment-842682050
+ */
+ apply(compiler) {
+ compiler.hooks.failed.tap('DieHardPlugin', (error) => {
+ console.error(error);
+ process.exit(1);
+ });
+ }
+}
+
var workerConfig = function() {
try {
return {
@@ -112,7 +133,6 @@ module.exports = Merge.smart({
CourseSock: './openedx/features/course_experience/static/course_experience/js/CourseSock.js',
Currency: './openedx/features/course_experience/static/course_experience/js/currency.js',
- AnnouncementsView: './openedx/features/announcements/static/announcements/jsx/Announcements.jsx',
CookiePolicyBanner: './common/static/js/src/CookiePolicyBanner.jsx',
// Common
@@ -154,6 +174,7 @@ module.exports = Merge.smart({
// any other way to declare that dependency.
$script: 'scriptjs'
}),
+ new DieHardPlugin(),
],
module: {
@@ -172,19 +193,19 @@ module.exports = Merge.smart({
multiple: [
{ search: defineHeader, replace: '' },
{ search: defineFooter, replace: '' },
- {
+ {
search: /(\/\* RequireJS) \*\//g,
replace(match, p1, offset, string) {
return p1;
}
},
- {
+ {
search: /\/\* Webpack/g,
replace(match, p1, offset, string) {
return match + ' */';
}
},
- {
+ {
search: /text!(.*?\.underscore)/g,
replace(match, p1, offset, string) {
return p1;
@@ -635,13 +656,13 @@ module.exports = Merge.smart({
// We used to have node: { fs: 'empty' } in this file,
// that is no longer supported. Adding this based on the recommendation in
// https://stackoverflow.com/questions/64361940/webpack-error-configuration-node-has-an-unknown-property-fs
- //
+ //
// With this uncommented tests fail
// Tests failed in the following suites:
// * lms javascript
// * xmodule-webpack javascript
// Error: define cannot be used indirect
- //
+ //
// fallback: {
// fs: false
// }
diff --git a/xmodule/annotatable_block.py b/xmodule/annotatable_block.py
index cec677f6c5d5..dbcf0123c59a 100644
--- a/xmodule/annotatable_block.py
+++ b/xmodule/annotatable_block.py
@@ -3,22 +3,24 @@
import logging
import textwrap
+from django.conf import settings
from lxml import etree
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Scope, String
+from xblocks_contrib.annotatable import AnnotatableBlock as _ExtractedAnnotatableBlock
from openedx.core.djangolib.markup import HTML, Text
from xmodule.editing_block import EditingMixin
from xmodule.raw_block import RawMixin
from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment
-from xmodule.xml_block import XmlMixin
from xmodule.x_module import (
ResourceTemplates,
shim_xmodule_js,
XModuleMixin,
XModuleToXBlockMixin,
)
+from xmodule.xml_block import XmlMixin
log = logging.getLogger(__name__)
@@ -28,7 +30,7 @@
@XBlock.needs('mako')
-class AnnotatableBlock(
+class _BuiltInAnnotatableBlock(
RawMixin,
XmlMixin,
EditingMixin,
@@ -40,6 +42,8 @@ class AnnotatableBlock(
Annotatable XBlock.
"""
+ is_extracted = False
+
data = String(
help=_("XML data for the annotation"),
scope=Scope.content,
@@ -197,3 +201,10 @@ def studio_view(self, _context):
add_webpack_js_to_fragment(fragment, 'AnnotatableBlockEditor')
shim_xmodule_js(fragment, self.studio_js_module_name)
return fragment
+
+
+AnnotatableBlock = (
+ _ExtractedAnnotatableBlock if settings.USE_EXTRACTED_ANNOTATABLE_BLOCK
+ else _BuiltInAnnotatableBlock
+)
+AnnotatableBlock.__name__ = "AnnotatableBlock"
diff --git a/xmodule/capa_block.py b/xmodule/capa_block.py
index 61cca6a3f9ad..fdc3f12edebd 100644
--- a/xmodule/capa_block.py
+++ b/xmodule/capa_block.py
@@ -25,7 +25,14 @@
from xblock.core import XBlock
from xblock.fields import Boolean, Dict, Float, Integer, Scope, String, XMLString, List
from xblock.scorable import ScorableXBlockMixin, Score
+from xblocks_contrib.problem import ProblemBlock as _ExtractedProblemBlock
+from common.djangoapps.xblock_django.constants import (
+ ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID,
+ ATTR_KEY_USER_IS_STAFF,
+ ATTR_KEY_USER_ID,
+)
+from openedx.core.djangolib.markup import HTML, Text
from xmodule.capa import responsetypes
from xmodule.capa.capa_problem import LoncapaProblem, LoncapaSystem
from xmodule.capa.inputtypes import Status
@@ -36,8 +43,8 @@
from xmodule.exceptions import NotFoundError, ProcessingError
from xmodule.graders import ShowCorrectness
from xmodule.raw_block import RawMixin
-from xmodule.util.sandboxing import SandboxService
from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment
+from xmodule.util.sandboxing import SandboxService
from xmodule.x_module import (
ResourceTemplates,
XModuleMixin,
@@ -45,20 +52,12 @@
shim_xmodule_js
)
from xmodule.xml_block import XmlMixin
-from common.djangoapps.xblock_django.constants import (
- ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID,
- ATTR_KEY_USER_IS_STAFF,
- ATTR_KEY_USER_ID,
-)
-from openedx.core.djangolib.markup import HTML, Text
from .capa.xqueue_interface import XQueueService
-
from .fields import Date, ListScoreField, ScoreField, Timedelta
from .progress import Progress
log = logging.getLogger("edx.courseware")
-
# Make '_' a no-op so we can scrape strings. Using lambda instead of
# `django.utils.translation.gettext_noop` because Django cannot be imported in this file
_ = lambda text: text
@@ -134,7 +133,7 @@ def from_json(self, value):
@XBlock.needs('sandbox')
@XBlock.needs('replace_urls')
@XBlock.wants('call_to_action')
-class ProblemBlock(
+class _BuiltInProblemBlock(
ScorableXBlockMixin,
RawMixin,
XmlMixin,
@@ -161,6 +160,8 @@ class ProblemBlock(
"""
INDEX_CONTENT_TYPE = 'CAPA'
+ is_extracted = False
+
resources_dir = None
has_score = True
@@ -2509,3 +2510,10 @@ def randomization_bin(seed, problem_id):
r_hash.update(str(problem_id).encode())
# get the first few digits of the hash, convert to an int, then mod.
return int(r_hash.hexdigest()[:7], 16) % NUM_RANDOMIZATION_BINS
+
+
+ProblemBlock = (
+ _ExtractedProblemBlock if settings.USE_EXTRACTED_PROBLEM_BLOCK
+ else _BuiltInProblemBlock
+)
+ProblemBlock.__name__ = "ProblemBlock"
diff --git a/xmodule/discussion_block.py b/xmodule/discussion_block.py
index 89e573c07c83..79914b63d6b2 100644
--- a/xmodule/discussion_block.py
+++ b/xmodule/discussion_block.py
@@ -4,7 +4,7 @@
import logging
import urllib
-
+from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from django.utils.translation import get_language_bidi
@@ -14,6 +14,7 @@
from xblock.fields import UNIQUE_ID, Scope, String
from xblock.utils.resources import ResourceLoader
from xblock.utils.studio_editable import StudioEditableXBlockMixin
+from xblocks_contrib.discussion import DiscussionXBlock as _ExtractedDiscussionXBlock
from lms.djangoapps.discussion.django_comment_client.permissions import has_permission
from openedx.core.djangoapps.discussions.models import DiscussionsConfiguration, Provider
@@ -21,7 +22,6 @@
from openedx.core.lib.xblock_utils import get_css_dependencies, get_js_dependencies
from xmodule.xml_block import XmlMixin
-
log = logging.getLogger(__name__)
loader = ResourceLoader(__name__) # pylint: disable=invalid-name
@@ -36,10 +36,12 @@ def _(text):
@XBlock.needs('user') # pylint: disable=abstract-method
@XBlock.needs('i18n')
@XBlock.needs('mako')
-class DiscussionXBlock(XBlock, StudioEditableXBlockMixin, XmlMixin): # lint-amnesty, pylint: disable=abstract-method
+class _BuiltInDiscussionXBlock(XBlock, StudioEditableXBlockMixin,
+ XmlMixin): # lint-amnesty, pylint: disable=abstract-method
"""
Provides a discussion forum that is inline with other content in the courseware.
"""
+ is_extracted = False
completion_mode = XBlockCompletionMode.EXCLUDED
discussion_id = String(scope=Scope.settings, default=UNIQUE_ID)
@@ -275,3 +277,10 @@ def _apply_metadata_and_policy(cls, block, node, runtime):
for field_name, value in metadata.items():
if field_name in block.fields:
setattr(block, field_name, value)
+
+
+DiscussionXBlock = (
+ _ExtractedDiscussionXBlock if settings.USE_EXTRACTED_DISCUSSION_BLOCK
+ else _BuiltInDiscussionXBlock
+)
+DiscussionXBlock.__name__ = "DiscussionXBlock"
diff --git a/xmodule/html_block.py b/xmodule/html_block.py
index 62949647cee3..9840c3007f92 100644
--- a/xmodule/html_block.py
+++ b/xmodule/html_block.py
@@ -15,6 +15,7 @@
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Boolean, List, Scope, String
+from xblocks_contrib.html import HtmlBlock as _ExtractedHtmlBlock
from common.djangoapps.xblock_django.constants import ATTR_KEY_DEPRECATED_ANONYMOUS_USER_ID
from xmodule.contentstore.content import StaticContent
@@ -22,8 +23,8 @@
from xmodule.edxnotes_utils import edxnotes
from xmodule.html_checker import check_html
from xmodule.stringify import stringify_children
-from xmodule.util.misc import escape_html_characters
from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment
+from xmodule.util.misc import escape_html_characters
from xmodule.x_module import (
ResourceTemplates,
shim_xmodule_js,
@@ -50,6 +51,7 @@ class HtmlBlockMixin( # lint-amnesty, pylint: disable=abstract-method
The HTML XBlock mixin.
This provides the base class for all Html-ish blocks (including the HTML XBlock).
"""
+
display_name = String(
display_name=_("Display Name"),
help=_("The display name for this component."),
@@ -353,11 +355,12 @@ def index_dictionary(self):
@edxnotes
-class HtmlBlock(HtmlBlockMixin): # lint-amnesty, pylint: disable=abstract-method
+class _BuiltInHtmlBlock(HtmlBlockMixin): # lint-amnesty, pylint: disable=abstract-method
"""
This is the actual HTML XBlock.
Nothing extra is required; this is just a wrapper to include edxnotes support.
"""
+ is_extracted = False
class AboutFields: # lint-amnesty, pylint: disable=missing-class-docstring
@@ -489,3 +492,10 @@ def safe_parse_date(date):
return datetime.strptime(date, '%B %d, %Y')
except ValueError: # occurs for ill-formatted date values
return datetime.today()
+
+
+HtmlBlock = (
+ _ExtractedHtmlBlock if settings.USE_EXTRACTED_HTML_BLOCK
+ else _BuiltInHtmlBlock
+)
+HtmlBlock.__name__ = "HtmlBlock"
diff --git a/xmodule/js/fixtures/video_all.html b/xmodule/js/fixtures/video_all.html
index 280fc4db35f4..81b472d754d2 100644
--- a/xmodule/js/fixtures/video_all.html
+++ b/xmodule/js/fixtures/video_all.html
@@ -42,8 +42,13 @@ Video
Share on:
-
- Share on twitter
+
+
+
+
+
+
+ Share on twitter
diff --git a/xmodule/lti_block.py b/xmodule/lti_block.py
index e7c173075b4e..944a7ec88db0 100644
--- a/xmodule/lti_block.py
+++ b/xmodule/lti_block.py
@@ -59,9 +59,9 @@
import hashlib
import logging
import textwrap
-from xml.sax.saxutils import escape
from unittest import mock
from urllib import parse
+from xml.sax.saxutils import escape
import nh3
import oauthlib.oauth1
@@ -69,30 +69,29 @@
from lxml import etree
from oauthlib.oauth1.rfc5849 import signature
from pytz import UTC
-from webob import Response
from web_fragments.fragment import Fragment
+from webob import Response
from xblock.core import List, Scope, String, XBlock
from xblock.fields import Boolean, Float
-from xmodule.mako_block import MakoTemplateBlockBase
-
-from openedx.core.djangolib.markup import HTML, Text
-from xmodule.editing_block import EditingMixin
+from xblocks_contrib.lti import LTIBlock as _ExtractedLTIBlock
from common.djangoapps.xblock_django.constants import (
ATTR_KEY_ANONYMOUS_USER_ID,
ATTR_KEY_USER_ROLE,
)
+from openedx.core.djangolib.markup import HTML, Text
+from xmodule.editing_block import EditingMixin
from xmodule.lti_2_util import LTI20BlockMixin, LTIError
+from xmodule.mako_block import MakoTemplateBlockBase
from xmodule.raw_block import EmptyDataRawMixin
from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment
-from xmodule.xml_block import XmlMixin
from xmodule.x_module import (
ResourceTemplates,
shim_xmodule_js,
XModuleMixin,
XModuleToXBlockMixin,
)
-
+from xmodule.xml_block import XmlMixin
log = logging.getLogger(__name__)
@@ -274,7 +273,7 @@ class LTIFields:
@XBlock.needs("mako")
@XBlock.needs("user")
@XBlock.needs("rebind_user")
-class LTIBlock(
+class _BuiltInLTIBlock(
LTIFields,
LTI20BlockMixin,
EmptyDataRawMixin,
@@ -366,6 +365,7 @@ class LTIBlock(
Otherwise error message from LTI provider is generated.
"""
+ is_extracted = False
resources_dir = None
uses_xmodule_styles_setup = True
@@ -984,3 +984,10 @@ def is_past_due(self):
else:
close_date = due_date
return close_date is not None and datetime.datetime.now(UTC) > close_date
+
+
+LTIBlock = (
+ _ExtractedLTIBlock if settings.USE_EXTRACTED_LTI_BLOCK
+ else _BuiltInLTIBlock
+)
+LTIBlock.__name__ = "LTIBlock"
diff --git a/xmodule/poll_block.py b/xmodule/poll_block.py
index a1c9686f42ac..b8c65f1cdba8 100644
--- a/xmodule/poll_block.py
+++ b/xmodule/poll_block.py
@@ -6,18 +6,19 @@
If student have answered - Question with statistics for each answers.
"""
-
import html
import json
import logging
-from collections import OrderedDict
from copy import deepcopy
-from web_fragments.fragment import Fragment
-
+from collections import OrderedDict
+from django.conf import settings
from lxml import etree
+from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Boolean, Dict, List, Scope, String # lint-amnesty, pylint: disable=wrong-import-order
+from xblocks_contrib.poll import PollBlock as _ExtractedPollBlock
+
from openedx.core.djangolib.markup import Text, HTML
from xmodule.mako_block import MakoTemplateBlockBase
from xmodule.stringify import stringify_children
@@ -30,13 +31,12 @@
)
from xmodule.xml_block import XmlMixin
-
log = logging.getLogger(__name__)
_ = lambda text: text
@XBlock.needs('mako')
-class PollBlock(
+class _BuiltInPollBlock(
MakoTemplateBlockBase,
XmlMixin,
XModuleToXBlockMixin,
@@ -44,6 +44,9 @@ class PollBlock(
XModuleMixin,
): # pylint: disable=abstract-method
"""Poll Block"""
+
+ is_extracted = False
+
# Name of poll to use in links to this poll
display_name = String(
help=_("The display name for this component."),
@@ -244,3 +247,10 @@ def add_child(xml_obj, answer): # lint-amnesty, pylint: disable=unused-argument
add_child(xml_object, answer)
return xml_object
+
+
+PollBlock = (
+ _ExtractedPollBlock if settings.USE_EXTRACTED_POLL_QUESTION_BLOCK
+ else _BuiltInPollBlock
+)
+PollBlock.__name__ = "PollBlock"
diff --git a/xmodule/templates/html/zooming_image.yaml b/xmodule/templates/html/zooming_image.yaml
index b91717550b27..14e9ef2c2392 100644
--- a/xmodule/templates/html/zooming_image.yaml
+++ b/xmodule/templates/html/zooming_image.yaml
@@ -2,56 +2,238 @@
metadata:
display_name: Zooming Image Tool
data: |
- Zooming Image Tool
- Use the Zooming Image Tool to enable learners to see details of large, complex images.
- With the Zooming Image Tool, the learner can move the mouse pointer over a part of the image to enlarge it and see more detail.
- To use the Zooming Image Tool, you must first add the jquery.loupeAndLightbox.js JavaScript file to your course.
- You must also add both the regular and magnified image files to your course.
- The following HTML code shows the format required to use the Zooming Image tool. For the example in this template, you must replace the values in italics .
-
- <div class="zooming-image-place" style="position: relative;">
- <a class="loupe" href="path to the magnified version of the image ">
- <img alt="Text for screen readers "
- src="path to the image you want to display in the unit " />
- </a>
- <div class="script_placeholder"
- data-src="path to the jquery.loupeAndLightbox.js JavaScript file in your course "/>
- </div>
- <script type="text/javascript">// >![CDATA[
- JavascriptLoader.executeModuleScripts($('.zooming-image-place').eq(0), function() {
- $('.loupe').loupeAndLightbox({
+ Use the Zooming Image Tool to enable learners to see details of large, complex images. With the tool, the learner can move the mouse pointer over a part of the image to enlarge it and see more detail.
+ To set it up, first upload the regular image file and, optionally, a magnified image file to your course. Then refer to them with the following HTML code, replacing the values in italics accordingly:
+
+ <div class="zooming-image">
+ <a data-src ="(Optional) URL to the magnified image ">
+ <img src ="URL to the regular image " />
+ </a>
+ </div>
+
+ If a magnified image is not provided, the regular one will be used at its native size.
+ Feel free to modify the example below for your own use, but take care not to remove the included Javascript.
+
+
-
+ border: '2px solid #ccc',
+ fadeSpeed: 250,
+ errorMessage: 'Image load error'
+ };
+ })(jQuery);
+
+ $('.zooming-image').loupe();
+ //]]>
diff --git a/xmodule/templates/test/zooming_image.yaml b/xmodule/templates/test/zooming_image.yaml
deleted file mode 100644
index 3ac9d63bcbbc..000000000000
--- a/xmodule/templates/test/zooming_image.yaml
+++ /dev/null
@@ -1,25 +0,0 @@
----
-metadata:
- display_name: Zooming Image
-data: |
- ZOOMING DIAGRAMS
- Some edX classes use extremely large, extremely detailed graphics. To make it easier to understand we can offer two versions of those graphics, with the zoomed section showing when you click on the main view.
- The example below is from 7.00x: Introduction to Biology and shows a subset of the biochemical reactions that cells carry out.
- You can view the chemical structures of the molecules by clicking on them. The magnified view also lists the enzymes involved in each step.
- Press spacebar to open the magifier.
-
-
-
diff --git a/xmodule/tests/test_resource_templates.py b/xmodule/tests/test_resource_templates.py
index 742a7e9da199..470be9551489 100644
--- a/xmodule/tests/test_resource_templates.py
+++ b/xmodule/tests/test_resource_templates.py
@@ -18,7 +18,6 @@ class ResourceTemplatesTests(unittest.TestCase):
def test_templates(self):
expected = {
'latex_html.yaml',
- 'zooming_image.yaml',
'announcement.yaml',
'anon_user_id.yaml'}
got = {t['template_id'] for t in TestClass.templates()}
@@ -38,7 +37,6 @@ def test_get_custom_template(self):
def test_custom_templates(self):
expected = {
'latex_html.yaml',
- 'zooming_image.yaml',
'announcement.yaml',
'anon_user_id.yaml'}
got = {t['template_id'] for t in TestClassResourceTemplate.templates()}
diff --git a/xmodule/video_block/video_block.py b/xmodule/video_block/video_block.py
index ea9d1a44280a..84d7edcf7263 100644
--- a/xmodule/video_block/video_block.py
+++ b/xmodule/video_block/video_block.py
@@ -29,6 +29,7 @@
from xblock.core import XBlock
from xblock.fields import ScopeIds
from xblock.runtime import KvsFieldData
+from xblocks_contrib.video import VideoBlock as _ExtractedVideoBlock
from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE, ATTR_KEY_USER_ID
from openedx.core.djangoapps.video_config.models import HLSPlaybackEnabledFlag, CourseYoutubeBlockedFlag
@@ -47,8 +48,8 @@
from xmodule.mako_block import MakoTemplateBlockBase
from xmodule.modulestore.inheritance import InheritanceKeyValueStore, own_metadata
from xmodule.raw_block import EmptyDataRawMixin
+from xmodule.util.builtin_assets import add_css_to_fragment, add_webpack_js_to_fragment
from xmodule.validation import StudioValidation, StudioValidationMessage
-from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment
from xmodule.video_block import manage_video_subtitles_save
from xmodule.x_module import (
PUBLIC_VIEW, STUDENT_VIEW,
@@ -56,7 +57,6 @@
XModuleMixin, XModuleToXBlockMixin,
)
from xmodule.xml_block import XmlMixin, deserialize_field, is_pointer_tag, name_to_pathname
-
from .bumper_utils import bumperize
from .sharing_sites import sharing_sites_info_for_video
from .transcripts_utils import (
@@ -119,7 +119,7 @@
@XBlock.wants('settings', 'completion', 'i18n', 'request_cache')
@XBlock.needs('mako', 'user')
-class VideoBlock(
+class _BuiltInVideoBlock(
VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers,
EmptyDataRawMixin, XmlMixin, EditingMixin, XModuleToXBlockMixin,
ResourceTemplates, XModuleMixin, LicenseMixin):
@@ -134,6 +134,7 @@ class VideoBlock(
"""
+ is_extracted = False
has_custom_completion = True
completion_mode = XBlockCompletionMode.COMPLETABLE
@@ -1260,3 +1261,10 @@ def _poster(self):
edx_video_id=self.edx_video_id.strip()
)
return None
+
+
+VideoBlock = (
+ _ExtractedVideoBlock if settings.USE_EXTRACTED_VIDEO_BLOCK
+ else _BuiltInVideoBlock
+)
+VideoBlock.__name__ = "VideoBlock"
diff --git a/xmodule/video_block/video_handlers.py b/xmodule/video_block/video_handlers.py
index cdda2da65b65..b7857e881ece 100644
--- a/xmodule/video_block/video_handlers.py
+++ b/xmodule/video_block/video_handlers.py
@@ -467,6 +467,7 @@ def validate_transcript_upload_data(self, data):
return error
+ # pylint: disable=too-many-statements
@XBlock.handler
def studio_transcript(self, request, dispatch):
"""
@@ -534,6 +535,10 @@ def studio_transcript(self, request, dispatch):
'edx_video_id': edx_video_id,
'language_code': new_language_code
}
+ # If a new transcript is added, then both new_language_code and
+ # language_code fields will have the same value.
+ if language_code != new_language_code:
+ self.transcripts.pop(language_code, None)
self.transcripts[new_language_code] = f'{edx_video_id}-{new_language_code}.srt'
response = Response(json.dumps(payload), status=201)
except (TranscriptsGenerationException, UnicodeDecodeError):
diff --git a/xmodule/word_cloud_block.py b/xmodule/word_cloud_block.py
index d678f2a9a9f5..37e82400df78 100644
--- a/xmodule/word_cloud_block.py
+++ b/xmodule/word_cloud_block.py
@@ -6,23 +6,27 @@
If student have answered - words he entered and cloud.
"""
+from xblocks_contrib.word_cloud import WordCloudBlock as _ExtractedWordCloudBlock
import json
import logging
+from django.conf import settings
from web_fragments.fragment import Fragment
from xblock.core import XBlock
from xblock.fields import Boolean, Dict, Integer, List, Scope, String
+
from xmodule.editing_block import EditingMixin
from xmodule.raw_block import EmptyDataRawMixin
from xmodule.util.builtin_assets import add_webpack_js_to_fragment, add_css_to_fragment
-from xmodule.xml_block import XmlMixin
from xmodule.x_module import (
ResourceTemplates,
shim_xmodule_js,
XModuleMixin,
XModuleToXBlockMixin,
)
+from xmodule.xml_block import XmlMixin
+
log = logging.getLogger(__name__)
# Make '_' a no-op so we can scrape strings. Using lambda instead of
@@ -41,7 +45,7 @@ def pretty_bool(value):
@XBlock.needs('mako')
-class WordCloudBlock( # pylint: disable=abstract-method
+class _BuiltInWordCloudBlock( # pylint: disable=abstract-method
EmptyDataRawMixin,
XmlMixin,
EditingMixin,
@@ -53,6 +57,8 @@ class WordCloudBlock( # pylint: disable=abstract-method
Word Cloud XBlock.
"""
+ is_extracted = False
+
display_name = String(
display_name=_("Display Name"),
help=_("The display name for this component."),
@@ -308,3 +314,10 @@ def index_dictionary(self):
xblock_body["content_type"] = "Word Cloud"
return xblock_body
+
+
+WordCloudBlock = (
+ _ExtractedWordCloudBlock if settings.USE_EXTRACTED_WORD_CLOUD_BLOCK
+ else _BuiltInWordCloudBlock
+)
+WordCloudBlock.__name__ = "WordCloudBlock"
diff --git a/xmodule/xml_block.py b/xmodule/xml_block.py
index 2753d455adc7..63dbedb17e1e 100644
--- a/xmodule/xml_block.py
+++ b/xmodule/xml_block.py
@@ -123,7 +123,11 @@ class XmlMixin:
# places in the platform rely on it.
'course', 'org', 'url_name', 'filename',
# Used for storing xml attributes between import and export, for roundtrips
- 'xml_attributes')
+ 'xml_attributes',
+ # Used by _import_xml_node_to_parent in cms/djangoapps/contentstore/helpers.py to prevent
+ # XmlMixin from treating some XML nodes as "pointer nodes".
+ "x-is-pointer-node",
+ )
# This is a categories to fields map that contains the block category specific fields which should not be
# cleaned and/or override while adding xml to node.