diff --git a/kdb-bot/.cpl/schematic_query.py b/kdb-bot/.cpl/schematic_query.py new file mode 100644 index 00000000..e34a3b6e --- /dev/null +++ b/kdb-bot/.cpl/schematic_query.py @@ -0,0 +1,34 @@ +from cpl_cli.abc.generate_schematic_abc import GenerateSchematicABC + + +class query(GenerateSchematicABC): + def __init__(self, *args: str): + GenerateSchematicABC.__init__(self, *args) + + def get_code(self) -> str: + import textwrap + + code = textwrap.dedent( + """\ + from bot_graphql.abc.data_query_abc import DataQueryABC + + + class $ClassName(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "Name") + + self.set_field("id", self.resolve_id) + + @staticmethod + def resolve_id(x, *_): + return x.id + """ + ) + return self.build_code_str( + code, + ClassName=self._class_name, + ) + + @classmethod + def register(cls): + GenerateSchematicABC.register(cls, "query", []) diff --git a/kdb-bot/cpl-workspace.json b/kdb-bot/cpl-workspace.json index e7028946..90d77e00 100644 --- a/kdb-bot/cpl-workspace.json +++ b/kdb-bot/cpl-workspace.json @@ -6,13 +6,13 @@ "bot-api": "src/bot_api/bot-api.json", "bot-core": "src/bot_core/bot-core.json", "bot-data": "src/bot_data/bot-data.json", + "bot-graphql": "src/bot_graphql/bot-graphql.json", "auto-role": "src/modules/auto_role/auto-role.json", "base": "src/modules/base/base.json", "boot-log": "src/modules/boot_log/boot-log.json", "database": "src/modules/database/database.json", "level": "src/modules/level/level.json", "permission": "src/modules/permission/permission.json", - "stats": "src/modules/stats/stats.json", "technician": "src/modules/technician/technician.json", "checks": "tools/checks/checks.json", "get-version": "tools/get_version/get-version.json", diff --git a/kdb-bot/docker b/kdb-bot/docker index 6b25cc87..62475d65 160000 --- a/kdb-bot/docker +++ b/kdb-bot/docker @@ -1 +1 @@ -Subproject commit 6b25cc87fced30b5846505d95f20285a3e4d7adf +Subproject commit 62475d65465f289604c7a32d23b5c29bb8cd38a4 diff --git a/kdb-bot/dockerfile b/kdb-bot/dockerfile index 62360746..478bf7e7 100644 --- a/kdb-bot/dockerfile +++ b/kdb-bot/dockerfile @@ -14,6 +14,8 @@ RUN apk add nano RUN pip install -r requirements.txt --extra-index-url https://pip.sh-edraft.de RUN pip install flask[async] -RUN pip install dnspython==2.2.1 # https://stackoverflow.com/questions/75137717/eventlet-dns-python-attribute-error-module-dns-rdtypes-has-no-attribute-any + +# RUN pip install dnspython==2.2.1 # https://stackoverflow.com/questions/75137717/eventlet-dns-python-attribute-error-module-dns-rdtypes-has-no-attribute-any +# ^ probably fixed py package updates CMD [ "bash", "/app/bot/bot"] diff --git a/kdb-bot/src/bot/__init__.py b/kdb-bot/src/bot/__init__.py index 35309ad1..d069403f 100644 --- a/kdb-bot/src/bot/__init__.py +++ b/kdb-bot/src/bot/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot/bot.json b/kdb-bot/src/bot/bot.json index 66fec647..33a37b8f 100644 --- a/kdb-bot/src/bot/bot.json +++ b/kdb-bot/src/bot/bot.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "bot", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", @@ -18,20 +18,22 @@ "Dependencies": [ "cpl-core==2022.12.1.post3", "cpl-translation==2022.12.1", - "cpl-query==2022.12.2.post1", - "cpl-discord==2022.12.1.post2", + "cpl-query==2022.12.2.post2", + "cpl-discord==2022.12.2.post1", "Flask==2.2.2", "Flask-Classful==0.14.2", "Flask-Cors==3.0.10", "PyJWT==2.6.0", "waitress==2.1.2", "Flask-SocketIO==5.3.2", - "eventlet==0.33.2", + "eventlet==0.33.3", "requests-oauthlib==1.3.1", - "icmplib==3.0.3" + "icmplib==3.0.3", + "ariadne==0.17.1" ], "DevDependencies": [ - "cpl-cli==2022.12.1.post3" + "cpl-cli==2022.12.1.post3", + "pygount==1.5.1" ], "PythonVersion": ">=3.10.4", "PythonPath": {}, @@ -55,13 +57,13 @@ "../bot_api/bot-api.json", "../bot_core/bot-core.json", "../bot_data/bot-data.json", + "../bot_graphql/bot-graphql.json", "../modules/auto_role/auto-role.json", "../modules/base/base.json", "../modules/boot_log/boot-log.json", "../modules/database/database.json", "../modules/level/level.json", "../modules/permission/permission.json", - "../modules/stats/stats.json", "../modules/technician/technician.json" ] } diff --git a/kdb-bot/src/bot/config b/kdb-bot/src/bot/config index b0ae8762..0c946375 160000 --- a/kdb-bot/src/bot/config +++ b/kdb-bot/src/bot/config @@ -1 +1 @@ -Subproject commit b0ae87621bbe54fd9c5650071ec8c1c9ec32df48 +Subproject commit 0c9463753731ab1f5d0f916d21ac7ea304742995 diff --git a/kdb-bot/src/bot/extension/__init__.py b/kdb-bot/src/bot/extension/__init__.py index b6da1362..a1d4a58b 100644 --- a/kdb-bot/src/bot/extension/__init__.py +++ b/kdb-bot/src/bot/extension/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot.extension" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot/module_list.py b/kdb-bot/src/bot/module_list.py index a48a2e39..120926ef 100644 --- a/kdb-bot/src/bot/module_list.py +++ b/kdb-bot/src/bot/module_list.py @@ -4,13 +4,13 @@ from bot_api.api_module import ApiModule from bot_core.core_extension.core_extension_module import CoreExtensionModule from bot_core.core_module import CoreModule from bot_data.data_module import DataModule +from bot_graphql.graphql_module import GraphQLModule from modules.auto_role.auto_role_module import AutoRoleModule from modules.base.base_module import BaseModule from modules.boot_log.boot_log_module import BootLogModule from modules.database.database_module import DatabaseModule from modules.level.level_module import LevelModule from modules.permission.permission_module import PermissionModule -from modules.stats.stats_module import StatsModule from modules.technician.technician_module import TechnicianModule @@ -23,13 +23,13 @@ class ModuleList: [ CoreModule, # has to be first! DataModule, + GraphQLModule, PermissionModule, + LevelModule, DatabaseModule, AutoRoleModule, BaseModule, - LevelModule, ApiModule, - StatsModule, TechnicianModule, # has to be last! BootLogModule, diff --git a/kdb-bot/src/bot/startup_migration_extension.py b/kdb-bot/src/bot/startup_migration_extension.py index 4f149463..5eba461b 100644 --- a/kdb-bot/src/bot/startup_migration_extension.py +++ b/kdb-bot/src/bot/startup_migration_extension.py @@ -4,15 +4,20 @@ from cpl_core.dependency_injection import ServiceCollectionABC from cpl_core.environment import ApplicationEnvironmentABC from bot_data.abc.migration_abc import MigrationABC +from bot_data.migration.api_key_migration import ApiKeyMigration from bot_data.migration.api_migration import ApiMigration from bot_data.migration.auto_role_fix1_migration import AutoRoleFix1Migration from bot_data.migration.auto_role_migration import AutoRoleMigration +from bot_data.migration.db_history_migration import DBHistoryMigration from bot_data.migration.initial_migration import InitialMigration from bot_data.migration.level_migration import LevelMigration +from bot_data.migration.remove_stats_migration import RemoveStatsMigration from bot_data.migration.stats_migration import StatsMigration +from bot_data.migration.user_joined_game_server_migration import UserJoinedGameServerMigration from bot_data.migration.user_message_count_per_hour_migration import ( UserMessageCountPerHourMigration, ) +from bot_data.migration.user_warning_migration import UserWarningMigration from bot_data.service.migration_service import MigrationService @@ -32,3 +37,8 @@ class StartupMigrationExtension(StartupExtensionABC): services.add_transient(MigrationABC, StatsMigration) # 09.11.2022 #46 - 0.3.0 services.add_transient(MigrationABC, AutoRoleFix1Migration) # 30.12.2022 #151 - 0.3.0 services.add_transient(MigrationABC, UserMessageCountPerHourMigration) # 11.01.2023 #168 - 0.3.1 + services.add_transient(MigrationABC, ApiKeyMigration) # 09.02.2023 #162 - 1.0.0 + services.add_transient(MigrationABC, UserJoinedGameServerMigration) # 12.02.2023 #181 - 1.0.0 + services.add_transient(MigrationABC, RemoveStatsMigration) # 19.02.2023 #190 - 1.0.0 + services.add_transient(MigrationABC, UserWarningMigration) # 21.02.2023 #35 - 1.0.0 + services.add_transient(MigrationABC, DBHistoryMigration) # 06.03.2023 #246 - 1.0.0 diff --git a/kdb-bot/src/bot/translation/de.json b/kdb-bot/src/bot/translation/de.json index 17524fc7..4b6654d9 100644 --- a/kdb-bot/src/bot/translation/de.json +++ b/kdb-bot/src/bot/translation/de.json @@ -1,51 +1,27 @@ { + "api": { + "api": { + "test_mail": { + "message": "Dies ist eine Test-Mail vom Krümelmonster Web Interface\nGesendet von {}-{}", + "subject": "Krümelmonster Web Interface Test-Mail" + } + }, + "auth": { + "confirmation": { + "message": "Öffne den Link, um die E-Mail zu bestätigen:\n{}auth/register/{}", + "subject": "E-Mail für {} {} bestätigen" + }, + "forgot_password": { + "message": "Öffne den Link, um das Passwort zu ändern:\n{}auth/forgot-password/{}", + "subject": "Passwort für {} {} zurücksetzen" + } + }, + "mail": { + "automatic_mail": "\n\nDies ist eine automatische E-Mail.\nGesendet von {}-{}@{}" + } + }, "common": { - "hello_world": "Hallo Welt", "bot_has_no_permission_message": "Ey!!!\nWas soll das?\nIch habe keine Berechtigungen :(\nScheiß System...", - "no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯", - "not_implemented_yet": "Ey Alter, das kann ich noch nicht...", - "presence": { - "booting": "{} Ich fahre gerade hoch...", - "running": "{} Ich esse Kekse :D", - "restart": "{} Muss neue Kekse holen...", - "shutdown": "{} Ich werde bestimmt wieder kommen..." - }, - "errors": { - "error": "Es gab einen Fehler. Meld dich bitte bei einem Admin.", - "command_error": "Es gab einen Fehler beim bearbeiten des Befehls. Meld dich bitte bei einem Admin.", - "missing_required_argument": "Fehler: Ein benötigter Parameter fehlt!", - "argument_parsing_error": "Fehler: Parameter konnte nicht gelesen werden!", - "unexpected_quote_error": "Fehler: Unerwarteter Zitat Fehler!", - "invalid_end_of_quoted_string_error": "Fehler: Ungültiges Zitatende!", - "expected_closing_quote_error": "Fehler: Erwarte Zitatende!", - "bad_argument": "Fehler: Ungültiger Parameter!", - "bad_union_argument": "Fehler: Ungültiger Union Parameter!", - "private_message_only": "Fehler: Nur private Nachrichten sind erlaubt!", - "no_private_message": "Fehler: Private Nachrichten sind nicht erlaubt!", - "check_failure": "Fehler: Du hast nicht die benötigte Berechtigung!", - "check_any_failure": "Fehler: Alle checks sind Fehlgeschlagen!", - "command_not_found": "Fehler: Befehl konnte nicht gefunden werden!", - "disabled_command": "Fehler: Befehl wurde deaktiviert!", - "command_invoke_error": "Fehler: Befehl konnte nicht aufgerufen werden!", - "too_many_arguments": "Fehler: Zu viele Parameter!", - "user_input_error": "Fehler: Eingabefehler!", - "command_on_cooldown": "Fehler: Befehl befindet sich im cooldown!", - "max_concurrency_reached": "Fehler: Maximale Parallelität erreicht!", - "not_owner": "Fehler: Du bist nicht mein besitzer!", - "missing_permissions": "Fehler: Berechtigungen fehlen!", - "bot_missing_permissions": "Fehler: Mir fehlen Berechtigungen!", - "missing_role": "Fehler: Benötigte Rolle fehlt!", - "bot_missing_role": "Fehler: Mir fehlt eine benötigte Rolle!", - "missing_any_role": "Fehler: Alle benötigten Rollen fehlen!", - "bot_missing_any_role": "Fehler: Mir fehlen alle benötigten Rollen!", - "nsfw_channel_required": "Fehler: NSFW Kanal benötigt!", - "extension_error": "Fehler: Erweiterungsfehler!", - "extension_already_loaded": "Fehler: Erweiterung wurde bereits geladen!", - "extension_not_loaded": "Fehler: Erweiterung wurde nicht geladen!", - "no_entry_point_error": "Fehler: Kein Eintrittspunkt!", - "extension_failed": "Fehler: Erweiterung ist fehlgeschlagen!", - "bot_not_ready_yet": "Ey Alter! Gedulde dich doch mal! ..." - }, "colors": { "blue": "Blau", "dark_blue": "Dunkelblau", @@ -69,242 +45,296 @@ "red": "Rot", "teal": "Blaugrün", "yellow": "Gelb" + }, + "errors": { + "argument_parsing_error": "Fehler: Parameter konnte nicht gelesen werden!", + "bad_argument": "Fehler: Ungültiger Parameter!", + "bad_union_argument": "Fehler: Ungültiger Union Parameter!", + "bot_missing_any_role": "Fehler: Mir fehlen alle benötigten Rollen!", + "bot_missing_permissions": "Fehler: Mir fehlen Berechtigungen!", + "bot_missing_role": "Fehler: Mir fehlt eine benötigte Rolle!", + "bot_not_ready_yet": "Ey Alter! Gedulde dich doch mal! ...", + "check_any_failure": "Fehler: Alle Checks sind Fehlgeschlagen!", + "check_failure": "Fehler: Du hast nicht die benötigte Berechtigung!", + "command_error": "Es gab einen Fehler beim Bearbeiten des Befehls. Melde dich bitte bei einem Admin.", + "command_invoke_error": "Fehler: Befehl konnte nicht aufgerufen werden!", + "command_not_found": "Fehler: Befehl konnte nicht gefunden werden!", + "command_on_cooldown": "Fehler: Befehl befindet sich im Cooldown!", + "disabled_command": "Fehler: Befehl wurde deaktiviert!", + "error": "Es gab einen Fehler. Melde dich bitte bei einem Admin.", + "expected_closing_quote_error": "Fehler: Erwarte Zitatende!", + "extension_already_loaded": "Fehler: Erweiterung wurde bereits geladen!", + "extension_error": "Fehler: Erweiterungsfehler!", + "extension_failed": "Fehler: Erweiterung ist fehlgeschlagen!", + "extension_not_loaded": "Fehler: Erweiterung wurde nicht geladen!", + "invalid_end_of_quoted_string_error": "Fehler: Ungültiges Zitatende!", + "max_concurrency_reached": "Fehler: Maximale Parallelität erreicht!", + "missing_any_role": "Fehler: Alle benötigten Rollen fehlen!", + "missing_permissions": "Fehler: Berechtigungen fehlen!", + "missing_required_argument": "Fehler: Ein benötigter Parameter fehlt!", + "missing_role": "Fehler: Benötigte Rolle fehlt!", + "no_entry_point_error": "Fehler: Kein Eintrittspunkt!", + "no_private_message": "Fehler: Private Nachrichten sind nicht erlaubt!", + "not_owner": "Fehler: Du bist nicht mein besitzer!", + "nsfw_channel_required": "Fehler: NSFW Kanal benötigt!", + "private_message_only": "Fehler: Nur private Nachrichten sind erlaubt!", + "too_many_arguments": "Fehler: Zu viele Parameter!", + "unexpected_quote_error": "Fehler: Unerwarteter Fehler beim Anführungszeichen!", + "user_input_error": "Fehler: Eingabefehler!" + }, + "hello_world": "Hallo Welt", + "no_permission_message": "Nein!\nIch höre nicht auf dich ¯\\_(ツ)_/¯", + "not_implemented_yet": "Ey Alter, das kann ich noch nicht...", + "presence": { + "booting": "Ich fahre gerade hoch...", + "restart": "Muss neue Kekse holen...", + "running": "Ich esse Kekse :D", + "shutdown": "Ich werde bestimmt wieder kommen..." } }, "modules": { "auto_role": { - "list": { - "title": "Beobachtete Nachrichten:", - "description": "Von auto-role beobachtete Nachrichten:", - "auto_role_id": "auto-role Id", - "message_id": "Nachricht-Id" - }, "add": { - "success": "auto-role für die Nachricht {} wurde hinzugefügt :D", "error": { - "not_found": "Nachricht {} in {} nicht gefunden!", - "already_exists": "auto-role für die Nachricht {} existiert bereits!" - } - }, - "remove": { - "success": "auto-role {} wurde entfernt :D", - "error": { - "not_found": "auto-role {} nicht gefunden!" - } + "already_exists": "auto-role für die Nachricht {} existiert bereits!", + "not_found": "Nachricht {} in {} nicht gefunden!" + }, + "success": "auto-role für die Nachricht {} wurde hinzugefügt :D" }, "error": { "nothing_found": "Keine auto-role Einträge gefunden." }, + "list": { + "auto_role_id": "auto-role Id", + "description": "Von auto-role beobachtete Nachrichten:", + "message_id": "Nachricht-Id", + "title": "Beobachtete Nachrichten:" + }, + "remove": { + "error": { + "not_found": "auto-role {} nicht gefunden!" + }, + "success": "auto-role {} wurde entfernt :D" + }, "rule": { - "list": { - "title": "auto-role Regeln:", - "description": "Von auto-role angewendete Regeln:", - "auto_role_rule_id": "auto-role Regel Id", - "emoji": "Emoji", - "role": "Rolle" - }, "add": { - "success": "Regel {} -> {} für auto-role {} wurde hinzugefügt :D", "error": { - "not_found": "Regel für auto-role {} nicht gefunden!", + "already_exists": "Regel für auto-role {} existiert bereits!", "emoji_not_found": "Emoji {} für auto-role Regel {} nicht gefunden!", - "role_not_found": "Rolle {} für auto-role Regel {} nicht gefunden!", - "already_exists": "Regel für auto-role {} existiert bereits!" - } - }, - "remove": { - "success": "Regel für auto-role {} wurde entfernt :D", - "error": { - "not_found": "Regel für auto-role {} nicht gefunden!" - } + "not_found": "Regel für auto-role {} nicht gefunden!", + "role_not_found": "Rolle {} für auto-role Regel {} nicht gefunden!" + }, + "success": "Regel {} -> {} für auto-role {} wurde hinzugefügt :D" }, "error": { "id_not_found": "Kein auto-role Eintrag mit der Id gefunden!" + }, + "list": { + "auto_role_rule_id": "auto-role Regel Id", + "description": "Von auto-role angewendete Regeln:", + "emoji": "Emoji", + "role": "Rolle", + "title": "auto-role Regeln:" + }, + "remove": { + "error": { + "not_found": "Regel für auto-role {} nicht gefunden!" + }, + "success": "Regel für auto-role {} wurde entfernt :D" } } }, - "moderator": { - "purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss." - }, "base": { - "technician_error_message": "Es gab ein Fehler mit dem Event: {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.\nUUID: {}", - "technician_command_error_message": "Es gab ein Fehler mit dem Befehl: {} ausgelöst von {} -> {}\nDatum und Zeit: {}\nSchau bitte ins log für Details.\nUUID: {}", - "welcome_message": "Hello There!\nIch heiße dich bei {} herzlichst Willkommen!", - "welcome_message_for_team": "{} hat gerade das Irrenhaus betreten.", - "goodbye_message": "Schade, dass du uns so schnell verlässt :(", "afk_command_channel_missing_message": "Zu unfähig einem Sprachkanal beizutreten?", "afk_command_move_message": "Ich verschiebe dich ja schon... (◔_◔)", - "member_joined_help_voice_channel": "{} braucht hilfe, bitte kümmer dich drum :D", - "pong": "Pong", + "game_server": { + "error": { + "nothing_found": "Keine Gameserver gefunden." + }, + "list": { + "title": "Gameserver", + "description": "Konfigurierte Gameserver:", + "name": "Name", + "api_key": "API Key" + }, + "add": { + "success": "Gameserver {} wurde hinzugefügt :)" + }, + "remove": { + "success": "Gameserver wurde entfernt :D" + } + }, + "goodbye_message": "Schade, dass du uns so schnell verlässt :(", "info": { - "title": "Krümmelmonster", "description": "Informationen über mich", "fields": { - "version": "Version", - "ontime": "Ontime", - "sent_message_count": "Gesendete Nachrichten", - "received_message_count": "Empfangene Nachrichten", "deleted_message_count": "Gelöschte Nachrichten", - "received_command_count": "Empfangene Befehle", + "modules": "Module", "moved_users_count": "Verschobene Benutzer", - "modules": "Module" + "ontime": "Ontime", + "received_command_count": "Empfangene Befehle", + "received_message_count": "Empfangene Nachrichten", + "sent_message_count": "Gesendete Nachrichten", + "version": "Version" }, - "footer": "" + "footer": "", + "title": "Krümelmonster" }, "mass_move": { - "moved": "Alle Personen aus {} wurden nach {} verschoben.", - "channel_from_error": "Du musst dich in einem Voicechannel befinden oder die Option \"channel_from\" mit angeben." + "channel_from_error": "Du musst dich in einem Voicechannel befinden oder die Option \"channel_from\" mit angeben.", + "moved": "Alle Personen aus {} wurden nach {} verschoben." }, + "member_joined_help_voice_channel": "{} braucht Hilfe, bitte kümmere dich drum :D", + "pong": "Pong", "presence": { "changed": "Presence wurde geändert.", - "removed": "Presence wurde entfernt.", - "max_char_count_exceeded": "Der Text darf nicht mehr als 128 Zeichen lang sein!" + "max_char_count_exceeded": "Der Text darf nicht mehr als 128 Zeichen lang sein!", + "removed": "Presence wurde entfernt." + }, + "register": { + "not_found": "Benutzer konnte nicht gefunden werden!", + "success": "Spieler wurde mit dem Mitglied verlinkt :D" + }, + "technician_command_error_message": "Es gab ein Fehler mit dem Befehl: {} ausgelöst von {} -> {}\nDatum und Zeit: {}\nSchau bitte ins Log für Details.\nUUID: {}", + "technician_error_message": "Es gab ein Fehler mit dem Event: {}\nDatum und Zeit: {}\nSchau bitte ins Log für Details.\nUUID: {}", + "unregister": { + "success": "Verlinkung wurde entfernt :D" }, "user": { + "add": { + "xp": "Die {} von {} wurden um {} erhöht" + }, "atr": { - "id": "Id", - "name": "Name", "discord_join": "Discord beigetreten am", + "id": "Id", + "joins": "Beitritte", "last_join": "Server beigetreten am", - "xp": "XP", + "lefts": "Abgänge", + "name": "Name", "ontime": "Ontime", "roles": "Rollen", - "joins": "Beitritte", - "lefts": "Abgänge", - "warnings": "Verwarnungen" + "warnings": "Verwarnungen", + "xp": "XP" + }, + "error": { + "atr_not_found": "Das Attribut {} konnte nicht gefunden werden :(" + }, + "get": { + "ontime": "{} war insgesamt {} Stunden aktiv in einem Sprachkanal", + "xp": "{} hat {} xp" }, "info": { "footer": "" }, - "get": { - "xp": "{} hat {} xp", - "ontime": "{} war insgesamt {} Stunden aktiv in einem Sprachkanal" - }, - "set": { - "xp": "{} hat nun {} xp", - "error": { - "value_type_not_numeric": "Der angegebende Wert ist keine Ganzzahl! :(", - "type_error": "Der angegebene Wert ist keine Zahl! :(" - } - }, - "add": { - "xp": "Die {} von {} wurden um {} erhöht" - }, "remove": { "xp": "Die {} von {} wurden um {} verringert" }, "reset": { - "xp": "Die {} von {} wurden entfernt", - "ontime": "Die {} von {} wurden entfernt" + "ontime": "Die {} von {} wurden entfernt", + "xp": "Die {} von {} wurden entfernt" }, - "error": { - "atr_not_found": "Das Attribut {} konnte nicht gefunden werden :(" + "set": { + "error": { + "type_error": "Der angegebene Wert ist keine Zahl! :(", + "value_type_not_numeric": "Der angegebende Wert ist keine Ganzzahl! :(" + }, + "xp": "{} hat nun {} xp" } - } + }, + "warnings": { + "add": { + "failed": "Verwarnung konnte nicht hinzugefügt werden :(", + "success": "Verwarnung wurde hinzugefügt :)" + }, + "first": "Bei der nächsten Verwarnung wirst du auf das vorherige Level zurückgesetzt!", + "kick": "Ich musste {} aufgrund zu vieler Verwarnungen kicken", + "remove": { + "failed": "Verwarnung konnte nicht entfernt werden :(", + "success": "Verwarnung wurde entfernt :)" + }, + "removed": "Die Verwarnung '{}' wurde entfernt.", + "second": "Bei der nächsten verwarnung wirst du auf das erste Level zurückgesetzt!", + "show": { + "description": "Beschreibung", + "id": "Id" + }, + "team_removed": "Die Verwarnung '{}' an {} wurde entfernt.", + "team_warned": "{} wurde verwarnt. Der Grund ist: {}", + "third": "Bei der nächsten verwarnung wirst du gekickt und zurückgesetzt!", + "warned": "Du wurdest verwarnt. Der Grund ist: {}" + }, + "welcome_message": "Hello There!\nIch heiße dich bei {} herzlichst Willkommen!", + "welcome_message_for_team": "{} hat gerade das Irrenhaus betreten." }, "boot_log": { "login_message": "Ich bin on the line :D\nDer Scheiß hat {} Sekunden gedauert" }, "level": { - "new_level_message": "{} ist nun Level {}", - "seeding_started": "Levelsystem wird neu geladen...", - "seeding_failed": "Levelsystem konnte nicht neu geladen werden :(", - "seeding_finished": "Levelsystem wurde Erfolgreich neu geladen :)", - "error": { - "nothing_found": "Keine Level Einträge gefunden.", - "level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!", - "level_with_xp_already_exists": "Das Level {} hat bereits die Mindest-XP {}!" - }, - "list": { - "title": "Level:", - "description": "Konfigurierte Level:", - "name": "Name", - "min_xp": "Mindest-XP", - "permission_int": "Berechtigungen" - }, "create": { "created": "Level {} mit Berechtigungen {} wurde erstellt :D" }, - "edit": { - "edited": "Level {} wurde bearbeitet :D", - "color_invalid": "Die Farbe {} ist ungültig!", - "permission_invalid": "Der Berechtigungswert {} ist ungültig!", - "not_found": "Level {} nicht gefunden!" - }, - "remove": { - "success": "Level {} wurde entfernt :D", - "error": { - "not_found": "Level {} nicht gefunden!" - } - }, "down": { "already_first": "{} hat bereits das erste Level.", - "success": "{} wurde auf Level {} runtergesetzt :)", - "failed": "{} konnte nicht runtergesetzt werden :(" + "failed": "{} konnte nicht runtergesetzt werden :(", + "success": "{} wurde auf Level {} runtergesetzt :)" + }, + "edit": { + "color_invalid": "Die Farbe {} ist ungültig!", + "edited": "Level {} wurde bearbeitet :D", + "not_found": "Level {} nicht gefunden!", + "permission_invalid": "Der Berechtigungswert {} ist ungültig!" + }, + "error": { + "level_with_name_already_exists": "Ein Level mit dem Namen {} existiert bereits!", + "level_with_xp_already_exists": "Das Level {} hat bereits die Mindest-XP {}!", + "nothing_found": "Keine Einträge gefunden." + }, + "list": { + "description": "Konfigurierte Level:", + "min_xp": "Mindest-XP", + "name": "Name", + "permission_int": "Berechtigungen", + "title": "Level:" + }, + "new_level_message": "{} ist nun Level {}", + "remove": { + "error": { + "not_found": "Level {} nicht gefunden!" + }, + "success": "Level {} wurde entfernt :D" + }, + "seeding_failed": "Levelsystem konnte nicht neu geladen werden :(", + "seeding_finished": "Levelsystem wurde erfolgreich neu geladen :)", + "seeding_started": "Levelsystem wird neu geladen...", + "set": { + "already_level": "{} hat bereits das Level {} :/", + "failed": "Das Level von {} konnte nicht auf {} gesetzt werden :(", + "not_found": "Das Level {} konnte nicht gefunden werden :(", + "success": "{} ist nun Level {} :)" }, "up": { "already_last": "{} hat bereits das höchste Level.", - "success": "{} wurde auf Level {} hochgesetzt :)", - "failed": "{} konnte nicht hochgesetzt werden :(" - }, - "set": { - "already_level": "{} hat bereits das Level {} :/", - "success": "{} ist nun Level {} :)", - "failed": "Das Level von {} konnte nicht auf {} gesetzt werden :(", - "not_found": "Das Level {} konnte nicht gefunden werden :(" + "failed": "{} konnte nicht hochgesetzt werden :(", + "success": "{} wurde auf Level {} hochgesetzt :)" } }, - "database": {}, - "permission": {}, - "stats": { - "list": { - "statistic": "Statistik", - "description": "Beschreibung", - "nothing_found": "Keine Statistiken gefunden." - }, - "view": { - "statistic": "Statistik", - "description": "Beschreibung", - "failed": "Statistik kann nicht gezeigt werden :(" - }, - "add": { - "failed": "Statistik kann nicht hinzugefügt werden :(", - "success": "Statistik wurde hinzugefügt :D" - }, - "edit": { - "failed": "Statistik kann nicht bearbeitet werden :(", - "success": "Statistik wurde gespeichert :D" - }, - "remove": { - "failed": "Statistik kann nicht gelöscht werden :(", - "success": "Statistik wurde gelöscht :D" - } + "moderator": { + "purge_message": "Na gut..., ich lösche alle Nachrichten wenns sein muss." }, "technician": { - "restart_message": "Bin gleich wieder da :D", - "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, Euer Freund. Lebt lange und in Frieden :)", - "log_message": "Hier sind deine Logdateien! :)" - } - }, - "api": { - "mail": { - "automatic_mail": "\n\nDies ist eine automatische E-Mail.\nGesendet von {}-{}@{}" - }, - "api": { - "test_mail": { - "subject": "Krümmelmonster Web Interface Test-Mail", - "message": "Dies ist eine Test-Mail vom Krümmelmonster Web Interface\nGesendet von {}-{}" - } - }, - "auth": { - "confirmation": { - "subject": "E-Mail für {} {} bestätigen", - "message": "Öffne den Link um die E-Mail zu bestätigen:\n{}auth/register/{}" + "api_key": { + "add": { + "success": "API-Schlüssel für {} wurde erstellt: {}" + }, + "get": "API-Schlüssel für {}: {}", + "remove": { + "not_found": "API-Schlüssel konnte nicht gefunden werden!", + "success": "API-Schlüssel wurde entfernt :D" + } }, - "forgot_password": { - "subject": "Passwort für {} {} zurücksetzen", - "message": "Öffne den Link um das Passwort zu ändern:\n{}auth/forgot-password/{}" - } + "log_message": "Hier sind deine Logdateien! :)", + "restart_message": "Bin gleich wieder da :D", + "shutdown_message": "Trauert nicht um mich, es war eine logische Entscheidung. Das Wohl von Vielen, es wiegt schwerer als das Wohl von Wenigen oder eines Einzelnen. Ich war es und ich werde es immer sein, euer Freund. Lebt lange und in Frieden :)" } } } \ No newline at end of file diff --git a/kdb-bot/src/bot_api/__init__.py b/kdb-bot/src/bot_api/__init__.py index 3428ee5e..888398e8 100644 --- a/kdb-bot/src/bot_api/__init__.py +++ b/kdb-bot/src/bot_api/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/abc/__init__.py b/kdb-bot/src/bot_api/abc/__init__.py index 9cb606dd..0e958334 100644 --- a/kdb-bot/src/bot_api/abc/__init__.py +++ b/kdb-bot/src/bot_api/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.abc" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/abc/auth_service_abc.py b/kdb-bot/src/bot_api/abc/auth_service_abc.py index 34c1b5f2..1ba5fbbb 100644 --- a/kdb-bot/src/bot_api/abc/auth_service_abc.py +++ b/kdb-bot/src/bot_api/abc/auth_service_abc.py @@ -52,17 +52,13 @@ class AuthServiceABC(ABC): pass @abstractmethod - async def add_auth_user_async(self, user_dto: AuthUserDTO): + def add_auth_user(self, user_dto: AuthUserDTO): pass @abstractmethod async def add_auth_user_by_oauth_async(self, dto: OAuthDTO): pass - @abstractmethod - async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO: - pass - @abstractmethod async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): pass @@ -83,12 +79,16 @@ class AuthServiceABC(ABC): async def verify_login(self, token_str: str) -> bool: pass + @abstractmethod + def verify_api_key(self, api_key: str) -> bool: + pass + @abstractmethod async def login_async(self, user_dto: AuthUserDTO) -> TokenDTO: pass @abstractmethod - async def login_discord_async(self, oauth_dto: AuthUserDTO) -> TokenDTO: + async def login_discord_async(self, oauth_dto: AuthUserDTO, dc_id: int) -> TokenDTO: pass @abstractmethod diff --git a/kdb-bot/src/bot_api/api.py b/kdb-bot/src/bot_api/api.py index e8872a5c..023fd54b 100644 --- a/kdb-bot/src/bot_api/api.py +++ b/kdb-bot/src/bot_api/api.py @@ -1,4 +1,3 @@ -import re import sys import textwrap import uuid @@ -16,7 +15,6 @@ from werkzeug.exceptions import NotFound from bot_api.configuration.api_settings import ApiSettings from bot_api.configuration.authentication_settings import AuthenticationSettings -from bot_api.configuration.frontend_settings import FrontendSettings from bot_api.exception.service_error_code_enum import ServiceErrorCode from bot_api.exception.service_exception import ServiceException from bot_api.logging.api_logger import ApiLogger @@ -30,7 +28,6 @@ class Api(Flask): logger: ApiLogger, services: ServiceProviderABC, api_settings: ApiSettings, - frontend_settings: FrontendSettings, auth_settings: AuthenticationSettings, *args, **kwargs, @@ -146,20 +143,13 @@ class Api(Flask): return response def start(self): - self._logger.info( - __name__, - f"Starting API {self._api_settings.host}:{self._api_settings.port}", - ) + self._logger.info(__name__, f"Starting API {self._api_settings.host}:{self._api_settings.port}") self._register_routes() self.secret_key = CredentialManager.decrypt(self._auth_settings.secret_key) # from waitress import serve # https://docs.pylonsproject.org/projects/waitress/en/stable/arguments.html # serve(self, host=self._apt_settings.host, port=self._apt_settings.port, threads=10, connection_limit=1000, channel_timeout=10) - wsgi.server( - eventlet.listen((self._api_settings.host, self._api_settings.port)), - self, - log_output=False, - ) + wsgi.server(eventlet.listen((self._api_settings.host, self._api_settings.port)), self, log_output=False) def on_connect(self): self._logger.info(__name__, f"Client connected") diff --git a/kdb-bot/src/bot_api/api_module.py b/kdb-bot/src/bot_api/api_module.py index 81030d51..8f40f95e 100644 --- a/kdb-bot/src/bot_api/api_module.py +++ b/kdb-bot/src/bot_api/api_module.py @@ -13,7 +13,7 @@ from bot_api.api import Api from bot_api.api_thread import ApiThread from bot_api.controller.auth_controller import AuthController from bot_api.controller.auth_discord_controller import AuthDiscordController -from bot_api.controller.discord.server_controller import ServerController +from bot_api.controller.graphql_controller import GraphQLController from bot_api.controller.gui_controller import GuiController from bot_api.event.bot_api_on_ready_event import BotApiOnReadyEvent from bot_api.service.auth_service import AuthService @@ -45,7 +45,7 @@ class ApiModule(ModuleABC): services.add_transient(AuthDiscordController) services.add_transient(GuiController) services.add_transient(DiscordService) - services.add_transient(ServerController) + services.add_transient(GraphQLController) # cpl-discord self._dc.add_event(DiscordEventTypesEnum.on_ready.value, BotApiOnReadyEvent) diff --git a/kdb-bot/src/bot_api/app_api_extension.py b/kdb-bot/src/bot_api/app_api_extension.py index 91075b3d..ea9fda56 100644 --- a/kdb-bot/src/bot_api/app_api_extension.py +++ b/kdb-bot/src/bot_api/app_api_extension.py @@ -2,12 +2,9 @@ from cpl_core.application import ApplicationExtensionABC from cpl_core.configuration import ConfigurationABC from cpl_core.dependency_injection import ServiceProviderABC -from bot_api.abc.auth_service_abc import AuthServiceABC -from bot_api.configuration.authentication_settings import AuthenticationSettings from bot_api.route.route import Route from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings -from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC class AppApiExtension(ApplicationExtensionABC): @@ -19,7 +16,4 @@ class AppApiExtension(ApplicationExtensionABC): if not feature_flags.get_flag(FeatureFlagsEnum.api_module): return - auth_settings: AuthenticationSettings = config.get_configuration(AuthenticationSettings) - auth_users: AuthUserRepositoryABC = services.get_service(AuthUserRepositoryABC) - auth: AuthServiceABC = services.get_service(AuthServiceABC) - Route.init_authorize(auth_users, auth) + Route.init_authorize() diff --git a/kdb-bot/src/bot_api/bot-api.json b/kdb-bot/src/bot_api/bot-api.json index ede5d405..c38a5060 100644 --- a/kdb-bot/src/bot_api/bot-api.json +++ b/kdb-bot/src/bot_api/bot-api.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "bot-api", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/bot_api/config b/kdb-bot/src/bot_api/config index e6046881..c712f856 160000 --- a/kdb-bot/src/bot_api/config +++ b/kdb-bot/src/bot_api/config @@ -1 +1 @@ -Subproject commit e6046881b562982008583afa973b39ff08b6a3c7 +Subproject commit c712f856ebe30c71ac0b144045599ed2f91a1cba diff --git a/kdb-bot/src/bot_api/configuration/__init__.py b/kdb-bot/src/bot_api/configuration/__init__.py index a0b51ead..fb43f88c 100644 --- a/kdb-bot/src/bot_api/configuration/__init__.py +++ b/kdb-bot/src/bot_api/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.configuration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/controller/__init__.py b/kdb-bot/src/bot_api/controller/__init__.py index 05c377e5..61f1e736 100644 --- a/kdb-bot/src/bot_api/controller/__init__.py +++ b/kdb-bot/src/bot_api/controller/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.controller" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/controller/auth_controller.py b/kdb-bot/src/bot_api/controller/auth_controller.py index f47bf75e..983b5fb9 100644 --- a/kdb-bot/src/bot_api/controller/auth_controller.py +++ b/kdb-bot/src/bot_api/controller/auth_controller.py @@ -6,8 +6,6 @@ from flask import request, jsonify, Response from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.api import Api -from bot_api.exception.service_error_code_enum import ServiceErrorCode -from bot_api.exception.service_exception import ServiceException from bot_api.filter.auth_user_select_criteria import AuthUserSelectCriteria from bot_api.json_processor import JSONProcessor from bot_api.logging.api_logger import ApiLogger @@ -73,7 +71,7 @@ class AuthController: @Route.post(f"{BasePath}/register") async def register(self): dto: AuthUserDTO = JSONProcessor.process(AuthUserDTO, request.get_json(force=True, silent=True)) - await self._auth_service.add_auth_user_async(dto) + self._auth_service.add_auth_user(dto) return "", 200 @Route.post(f"{BasePath}/register-by-id/") @@ -131,7 +129,6 @@ class AuthController: return "", 200 @Route.post(f"{BasePath}/refresh") - @Route.authorize async def refresh(self) -> Response: dto: TokenDTO = JSONProcessor.process(TokenDTO, request.get_json(force=True, silent=True)) result = await self._auth_service.refresh_async(dto) diff --git a/kdb-bot/src/bot_api/controller/auth_discord_controller.py b/kdb-bot/src/bot_api/controller/auth_discord_controller.py index 322e186c..8ad193cc 100644 --- a/kdb-bot/src/bot_api/controller/auth_discord_controller.py +++ b/kdb-bot/src/bot_api/controller/auth_discord_controller.py @@ -8,7 +8,7 @@ from cpl_core.utils import CredentialManager from cpl_discord.service import DiscordBotServiceABC from cpl_translation import TranslatePipe from flask import jsonify, Response -from flask import request, session +from flask import request from requests_oauthlib import OAuth2Session from bot_api.abc.auth_service_abc import AuthServiceABC @@ -16,10 +16,8 @@ from bot_api.api import Api from bot_api.configuration.discord_authentication_settings import ( DiscordAuthenticationSettings, ) -from bot_api.json_processor import JSONProcessor from bot_api.logging.api_logger import ApiLogger from bot_api.model.auth_user_dto import AuthUserDTO -from bot_api.model.o_auth_dto import OAuthDTO from bot_api.route.route import Route from bot_data.model.auth_role_enum import AuthRoleEnum @@ -59,7 +57,7 @@ class AuthDiscordController: self._bot.user.id, redirect_uri=self._auth_settings.redirect_url, state=request.args.get("state"), - scope=self._auth_settings.scope, + scope=self._auth_settings.scope.to_list(), ) token = discord.fetch_token( self._auth_settings.token_url, @@ -74,28 +72,11 @@ class AuthDiscordController: oauth = OAuth2Session( self._bot.user.id, redirect_uri=self._auth_settings.redirect_url, - scope=self._auth_settings.scope, + scope=self._auth_settings.scope.to_list(), ) login_url, state = oauth.authorization_url(self._auth_settings.auth_url) return jsonify({"loginUrl": login_url}) - @Route.get(f"{BasePath}/create-user") - async def discord_create_user(self) -> Response: - response = self._get_user_from_discord_response() - result = await self._auth_service.add_auth_user_by_discord_async( - AuthUserDTO( - 0, - response["username"], - response["discriminator"], - response["email"], - str(uuid.uuid4()), - None, - AuthRoleEnum.normal, - ), - response["id"], - ) - return jsonify(result.to_dict()) - @Route.get(f"{BasePath}/login") async def discord_login(self) -> Response: response = self._get_user_from_discord_response() @@ -109,5 +90,5 @@ class AuthDiscordController: AuthRoleEnum.normal, ) - result = await self._auth_service.login_discord_async(dto) + result = await self._auth_service.login_discord_async(dto, response["id"]) return jsonify(result.to_dict()) diff --git a/kdb-bot/src/bot_api/controller/discord/server_controller.py b/kdb-bot/src/bot_api/controller/discord/server_controller.py deleted file mode 100644 index a9f0efe1..00000000 --- a/kdb-bot/src/bot_api/controller/discord/server_controller.py +++ /dev/null @@ -1,67 +0,0 @@ -from cpl_core.configuration import ConfigurationABC -from cpl_core.environment import ApplicationEnvironmentABC -from cpl_core.mailing import EMailClientABC, EMailClientSettings -from cpl_translation import TranslatePipe -from flask import Response, jsonify, request - -from bot_api.api import Api -from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria -from bot_api.json_processor import JSONProcessor -from bot_api.logging.api_logger import ApiLogger -from bot_api.route.route import Route -from bot_api.service.discord_service import DiscordService -from bot_data.model.auth_role_enum import AuthRoleEnum - - -class ServerController: - BasePath = f"/api/discord/server" - - def __init__( - self, - config: ConfigurationABC, - env: ApplicationEnvironmentABC, - logger: ApiLogger, - t: TranslatePipe, - api: Api, - mail_settings: EMailClientSettings, - mailer: EMailClientABC, - discord_service: DiscordService, - ): - self._config = config - self._env = env - self._logger = logger - self._t = t - self._api = api - self._mail_settings = mail_settings - self._mailer = mailer - self._discord_service = discord_service - - @Route.get(f"{BasePath}/get/servers") - @Route.authorize(role=AuthRoleEnum.admin) - async def get_all_servers(self) -> Response: - result = await self._discord_service.get_all_servers() - result = result.select(lambda x: x.to_dict()).to_list() - return jsonify(result) - - @Route.get(f"{BasePath}/get/servers-by-user") - @Route.authorize - async def get_all_servers_by_user(self) -> Response: - result = await self._discord_service.get_all_servers_by_user() - result = result.select(lambda x: x.to_dict()).to_list() - return jsonify(result) - - @Route.post(f"{BasePath}/get/filtered") - @Route.authorize - async def get_filtered_servers(self) -> Response: - dto: ServerSelectCriteria = JSONProcessor.process( - ServerSelectCriteria, request.get_json(force=True, silent=True) - ) - result = await self._discord_service.get_filtered_servers_async(dto) - result.result = result.result.select(lambda x: x.to_dict()).to_list() - return jsonify(result.to_dict()) - - @Route.get(f"{BasePath}/get/") - @Route.authorize - async def get_server_by_id(self, id: int) -> Response: - result = await self._discord_service.get_server_by_id_async(id).to_list() - return jsonify(result.to_dict()) diff --git a/kdb-bot/src/bot_api/controller/graphql_controller.py b/kdb-bot/src/bot_api/controller/graphql_controller.py new file mode 100644 index 00000000..d9072029 --- /dev/null +++ b/kdb-bot/src/bot_api/controller/graphql_controller.py @@ -0,0 +1,44 @@ +from ariadne import graphql_sync +from ariadne.constants import PLAYGROUND_HTML +from cpl_core.configuration import ConfigurationABC +from cpl_core.environment import ApplicationEnvironmentABC +from flask import request, jsonify + +from bot_api.logging.api_logger import ApiLogger +from bot_api.route.route import Route +from bot_graphql.schema import Schema + + +class GraphQLController: + BasePath = f"/api/graphql" + + def __init__( + self, + config: ConfigurationABC, + env: ApplicationEnvironmentABC, + logger: ApiLogger, + schema: Schema, + ): + self._config = config + self._env = env + self._logger = logger + self._schema = schema + + @Route.get(f"{BasePath}/playground") + @Route.authorize(skip_in_dev=True) + async def playground(self): + if self._env.environment_name != "development": + return "", 403 + + return PLAYGROUND_HTML, 200 + + @Route.post(f"{BasePath}") + @Route.authorize(by_api_key=True) + async def graphql(self): + data = request.get_json() + + # Note: Passing the request to the context is optional. + # In Flask, the current request is always accessible as flask.request + success, result = graphql_sync(self._schema.schema, data, context_value=request) + + return jsonify(result), 200 if success else 400 diff --git a/kdb-bot/src/bot_api/event/__init__.py b/kdb-bot/src/bot_api/event/__init__.py index 32b4550f..b2a685dc 100644 --- a/kdb-bot/src/bot_api/event/__init__.py +++ b/kdb-bot/src/bot_api/event/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.event" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/exception/__init__.py b/kdb-bot/src/bot_api/exception/__init__.py index 489cbd68..c7f15967 100644 --- a/kdb-bot/src/bot_api/exception/__init__.py +++ b/kdb-bot/src/bot_api/exception/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.exception" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/exception/service_error_code_enum.py b/kdb-bot/src/bot_api/exception/service_error_code_enum.py index 5848bf33..4bb3072f 100644 --- a/kdb-bot/src/bot_api/exception/service_error_code_enum.py +++ b/kdb-bot/src/bot_api/exception/service_error_code_enum.py @@ -4,7 +4,6 @@ from werkzeug.exceptions import Unauthorized class ServiceErrorCode(Enum): - Unknown = 0 InvalidDependencies = 1 diff --git a/kdb-bot/src/bot_api/filter/__init__.py b/kdb-bot/src/bot_api/filter/__init__.py index d8c8e234..e9b05a0e 100644 --- a/kdb-bot/src/bot_api/filter/__init__.py +++ b/kdb-bot/src/bot_api/filter/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.filter" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/filter/discord/__init__.py b/kdb-bot/src/bot_api/filter/discord/__init__.py index 65e59d93..4abc2014 100644 --- a/kdb-bot/src/bot_api/filter/discord/__init__.py +++ b/kdb-bot/src/bot_api/filter/discord/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.filter.discord" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/logging/__init__.py b/kdb-bot/src/bot_api/logging/__init__.py index 91c72c2f..0dd44016 100644 --- a/kdb-bot/src/bot_api/logging/__init__.py +++ b/kdb-bot/src/bot_api/logging/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.logging" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/model/__init__.py b/kdb-bot/src/bot_api/model/__init__.py index cbe353f7..ebc8348c 100644 --- a/kdb-bot/src/bot_api/model/__init__.py +++ b/kdb-bot/src/bot_api/model/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.model" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/model/auth_user_dto.py b/kdb-bot/src/bot_api/model/auth_user_dto.py index 8d0d98b3..0572fad8 100644 --- a/kdb-bot/src/bot_api/model/auth_user_dto.py +++ b/kdb-bot/src/bot_api/model/auth_user_dto.py @@ -1,6 +1,10 @@ +from datetime import datetime from typing import Optional +from cpl_query.extension import List + from bot_api.abc.dto_abc import DtoABC +from bot_api.model.user_dto import UserDTO from bot_data.model.auth_role_enum import AuthRoleEnum @@ -14,6 +18,9 @@ class AuthUserDTO(DtoABC): password: str = None, confirmation_id: Optional[str] = None, auth_role: AuthRoleEnum = None, + users: List[UserDTO] = None, + created_at: datetime = None, + modified_at: datetime = None, ): DtoABC.__init__(self) @@ -24,6 +31,13 @@ class AuthUserDTO(DtoABC): self._password = password self._is_confirmed = confirmation_id is None self._auth_role = auth_role + self._created_at = created_at + self._modified_at = modified_at + + if users is None: + self._users = List(UserDTO) + else: + self._users = users @property def id(self) -> int: @@ -77,6 +91,18 @@ class AuthUserDTO(DtoABC): def auth_role(self, value: AuthRoleEnum): self._auth_role = value + @property + def users(self) -> List[UserDTO]: + return self._users + + @property + def created_at(self) -> datetime: + return self._created_at + + @property + def modified_at(self) -> datetime: + return self._modified_at + def from_dict(self, values: dict): self._id = values["id"] self._first_name = values["firstName"] @@ -85,6 +111,15 @@ class AuthUserDTO(DtoABC): self._password = values["password"] self._is_confirmed = values["isConfirmed"] self._auth_role = AuthRoleEnum(values["authRole"]) + if "users" in values: + self._users = List(UserDTO) + for u in values["users"]: + user = UserDTO() + user.from_dict(u) + self._users.add(user) + + self._created_at = values["createdAt"] + self._modified_at = values["modifiedAt"] def to_dict(self) -> dict: return { @@ -95,4 +130,7 @@ class AuthUserDTO(DtoABC): "password": self._password, "isConfirmed": self._is_confirmed, "authRole": self._auth_role.value, + "users": self._users.select(lambda u: u.to_dict()).to_list(), + "createdAt": self._created_at, + "modifiedAt": self._modified_at, } diff --git a/kdb-bot/src/bot_api/model/discord/__init__.py b/kdb-bot/src/bot_api/model/discord/__init__.py index 39043a01..fb48ddb0 100644 --- a/kdb-bot/src/bot_api/model/discord/__init__.py +++ b/kdb-bot/src/bot_api/model/discord/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.model.discord" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/model/token_dto.py b/kdb-bot/src/bot_api/model/token_dto.py index d4a73f2f..88ff8501 100644 --- a/kdb-bot/src/bot_api/model/token_dto.py +++ b/kdb-bot/src/bot_api/model/token_dto.py @@ -1,16 +1,13 @@ -import traceback - -from cpl_core.console import Console - from bot_api.abc.dto_abc import DtoABC class TokenDTO(DtoABC): - def __init__(self, token: str, refresh_token: str): + def __init__(self, token: str, refresh_token: str, first_login: bool = False): DtoABC.__init__(self) self._token = token self._refresh_token = refresh_token + self._first_login = first_login @property def token(self) -> str: @@ -20,9 +17,14 @@ class TokenDTO(DtoABC): def refresh_token(self) -> str: return self._refresh_token + @property + def first_login(self) -> bool: + return self._first_login + def from_dict(self, values: dict): self._token = values["token"] self._refresh_token = values["refreshToken"] + self._first_login = values["firstLogin"] def to_dict(self) -> dict: - return {"token": self._token, "refreshToken": self._refresh_token} + return {"token": self._token, "refreshToken": self._refresh_token, "firstLogin": self._first_login} diff --git a/kdb-bot/src/bot_api/model/user_dto.py b/kdb-bot/src/bot_api/model/user_dto.py new file mode 100644 index 00000000..38dd28a1 --- /dev/null +++ b/kdb-bot/src/bot_api/model/user_dto.py @@ -0,0 +1,76 @@ +from typing import Optional + +from bot_api.abc.dto_abc import DtoABC +from bot_data.model.server import Server + + +class UserDTO(DtoABC): + def __init__( + self, + id: int = None, + dc_id: int = None, + xp: int = None, + server: Optional[Server] = None, + is_technician: Optional[bool] = None, + is_admin: Optional[bool] = None, + is_moderator: Optional[bool] = None, + ): + DtoABC.__init__(self) + + self._user_id = id + self._discord_id = dc_id + self._xp = xp + self._server = server + + self._is_technician = is_technician + self._is_admin = is_admin + self._is_moderator = is_moderator + + @property + def user_id(self) -> int: + return self._user_id + + @property + def discord_id(self) -> int: + return self._discord_id + + @property + def xp(self) -> int: + return self._xp + + @xp.setter + def xp(self, value: int): + self._xp = value + + @property + def server(self) -> Optional[Server]: + return self._server + + @property + def is_technician(self) -> bool: + return self._is_technician if self._is_technician is not None else False + + @property + def is_admin(self) -> bool: + return self._is_admin if self._is_admin is not None else False + + @property + def is_moderator(self) -> bool: + return self._is_moderator if self._is_moderator is not None else False + + def from_dict(self, values: dict): + self._user_id = values["id"] + self._discord_id = values["dcId"] + self._xp = values["xp"] + self._server = values["server"] + + def to_dict(self) -> dict: + return { + "id": self._user_id, + "dcId": self._discord_id, + "xp": self._xp, + "server": self._server.id, + "isTechnician": self.is_technician, + "isAdmin": self.is_admin, + "isModerator": self.is_moderator, + } diff --git a/kdb-bot/src/bot_api/route/__init__.py b/kdb-bot/src/bot_api/route/__init__.py index ee94830a..b8106f0f 100644 --- a/kdb-bot/src/bot_api/route/__init__.py +++ b/kdb-bot/src/bot_api/route/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.route" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/route/route.py b/kdb-bot/src/bot_api/route/route.py index 63c01016..74278f28 100644 --- a/kdb-bot/src/bot_api/route/route.py +++ b/kdb-bot/src/bot_api/route/route.py @@ -1,7 +1,9 @@ import functools from functools import wraps -from typing import Optional, Callable +from typing import Optional, Callable, Union +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_core.environment import ApplicationEnvironmentABC from flask import request, jsonify from flask_cors import cross_origin @@ -11,6 +13,7 @@ from bot_api.exception.service_exception import ServiceException from bot_api.model.error_dto import ErrorDTO from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.model.auth_role_enum import AuthRoleEnum +from bot_data.model.auth_user import AuthUser class Route: @@ -18,23 +21,77 @@ class Route: _auth_users: Optional[AuthUserRepositoryABC] = None _auth: Optional[AuthServiceABC] = None + _env = "production" @classmethod - def init_authorize(cls, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC): + @ServiceProviderABC.inject + def init_authorize(cls, env: ApplicationEnvironmentABC, auth_users: AuthUserRepositoryABC, auth: AuthServiceABC): cls._auth_users = auth_users cls._auth = auth + cls._env = env.environment_name @classmethod - def authorize(cls, f: Callable = None, role: AuthRoleEnum = None): + def get_user(cls) -> Optional[Union[str, AuthUser]]: + token = None + api_key = None + authorization = request.headers.get("Authorization").split() + match authorization[0]: + case "Bearer": + token = authorization[1] + case "API-Key": + api_key = authorization[1] + + if api_key is not None: + return "system" + + if token is None: + return None + + jwt = cls._auth.decode_token(token) + user = cls._auth_users.get_auth_user_by_email(jwt["email"]) + return user + + @classmethod + def authorize(cls, f: Callable = None, role: AuthRoleEnum = None, skip_in_dev=False, by_api_key=False): if f is None: - return functools.partial(cls.authorize, role=role) + return functools.partial(cls.authorize, role=role, skip_in_dev=skip_in_dev, by_api_key=by_api_key) @wraps(f) async def decorator(*args, **kwargs): + if skip_in_dev and cls._env == "development": + return await f(*args, **kwargs) + token = None + api_key = None if "Authorization" in request.headers: - bearer = request.headers.get("Authorization") - token = bearer.split()[1] + if " " not in request.headers.get("Authorization"): + ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set") + error = ErrorDTO(ex.error_code, ex.message) + return jsonify(error.to_dict()), 401 + + authorization = request.headers.get("Authorization").split() + match authorization[0]: + case "Bearer": + token = authorization[1] + case "API-Key": + api_key = authorization[1] + + if api_key is not None: + valid = False + try: + valid = cls._auth.verify_api_key(api_key) + except ServiceException as e: + error = ErrorDTO(e.error_code, e.message) + return jsonify(error.to_dict()), 403 + except Exception as e: + return jsonify(e), 500 + + if not valid: + ex = ServiceException(ServiceErrorCode.Unauthorized, f"API-Key invalid") + error = ErrorDTO(ex.error_code, ex.message) + return jsonify(error.to_dict()), 401 + + return await f(*args, **kwargs) if token is None: ex = ServiceException(ServiceErrorCode.Unauthorized, f"Token not set") diff --git a/kdb-bot/src/bot_api/service/__init__.py b/kdb-bot/src/bot_api/service/__init__.py index 915fae33..6073696d 100644 --- a/kdb-bot/src/bot_api/service/__init__.py +++ b/kdb-bot/src/bot_api/service/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.service" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/service/auth_service.py b/kdb-bot/src/bot_api/service/auth_service.py index 1ba01206..03fe78a5 100644 --- a/kdb-bot/src/bot_api/service/auth_service.py +++ b/kdb-bot/src/bot_api/service/auth_service.py @@ -31,9 +31,11 @@ from bot_api.model.reset_password_dto import ResetPasswordDTO from bot_api.model.token_dto import TokenDTO from bot_api.model.update_auth_user_dto import UpdateAuthUserDTO from bot_api.transformer.auth_user_transformer import AuthUserTransformer as AUT +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.api_key import ApiKey from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_user import AuthUser from bot_data.model.auth_user_users_relation import AuthUserUsersRelation @@ -49,9 +51,9 @@ class AuthService(AuthServiceABC): bot: DiscordBotServiceABC, db: DatabaseContextABC, auth_users: AuthUserRepositoryABC, + api_keys: ApiKeyRepositoryABC, users: UserRepositoryABC, servers: ServerRepositoryABC, - # mailer: MailThread, mailer: EMailClientABC, t: TranslatePipe, auth_settings: AuthenticationSettings, @@ -64,6 +66,7 @@ class AuthService(AuthServiceABC): self._bot = bot self._db = db self._auth_users = auth_users + self._api_keys = api_keys self._users = users self._servers = servers self._mailer = mailer @@ -77,11 +80,19 @@ class AuthService(AuthServiceABC): @staticmethod def _is_email_valid(email: str) -> bool: + if email is None: + raise False + if re.fullmatch(_email_regex, email) is not None: return True return False + def _get_api_key_str(self, api_key: ApiKey) -> str: + return hashlib.sha256( + f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8") + ).hexdigest() + def generate_token(self, user: AuthUser) -> str: token = jwt.encode( payload={ @@ -215,7 +226,7 @@ class AuthService(AuthServiceABC): user = self._auth_users.find_auth_user_by_email(email) return AUT.to_dto(user) if user is not None else None - async def add_auth_user_async(self, user_dto: AuthUserDTO): + def add_auth_user(self, user_dto: AuthUserDTO): db_user = self._auth_users.find_auth_user_by_email(user_dto.email) if db_user is not None: raise ServiceException(ServiceErrorCode.InvalidUser, "User already exists") @@ -264,51 +275,6 @@ class AuthService(AuthServiceABC): self._db.save_changes() - async def add_auth_user_by_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> OAuthDTO: - db_auth_user = self._auth_users.find_auth_user_by_email(user_dto.email) - - # user exists - if db_auth_user is not None and db_auth_user.users.count() > 0: - # raise ServiceException(ServiceErrorCode.InvalidUser, 'User already exists') - self._logger.debug(__name__, f"Discord user already exists") - return OAuthDTO(AUT.to_dto(db_auth_user), None) - - # user exists but discord user id not set - elif db_auth_user is not None and db_auth_user.users.count() == 0: - self._logger.debug(__name__, f"Auth user exists but not linked with discord") - # users = self._users.get_users_by_discord_id(user_dto.user_id) - # add auth_user to user refs - db_auth_user.oauth_id = None - - else: - # user does not exists - self._logger.debug(__name__, f"Auth user does not exist") - try: - user_dto.user_id = self._users.get_users_by_discord_id(user_dto.user_id).single().user_id - except Exception as e: - self._logger.error(__name__, f"User not found") - user_dto.user_id = None - - await self.add_auth_user_async(user_dto) - db_auth_user = self._auth_users.get_auth_user_by_email(user_dto.email) - db_auth_user.oauth_id = uuid.uuid4() - - for g in self._bot.guilds: - member = g.get_member(int(dc_id)) - if member is None: - continue - - server = self._servers.get_server_by_discord_id(g.id) - users = self._users.get_users_by_discord_id(dc_id) - for user in users: - if user.server.server_id != server.server_id: - continue - self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_auth_user, user)) - - self._auth_users.update_auth_user(db_auth_user) - self._db.save_changes() - return OAuthDTO(AUT.to_dto(db_auth_user), db_auth_user.oauth_id) - async def update_user_async(self, update_user_dto: UpdateAuthUserDTO): if update_user_dto is None: raise ServiceException(ServiceErrorCode.InvalidData, f"User is empty") @@ -478,6 +444,18 @@ class AuthService(AuthServiceABC): return True + def verify_api_key(self, api_key: str) -> bool: + try: + keys = self._api_keys.get_api_keys().select(self._get_api_key_str) + + if not keys.contains(api_key): + raise ServiceException(ServiceErrorCode.InvalidData, "API-Key invalid") + except Exception as e: + self._logger.error(__name__, f"API-Key invalid", e) + return False + + return True + async def login_async(self, user_dto: AuthUser) -> TokenDTO: if user_dto is None: raise ServiceException(ServiceErrorCode.InvalidData, "User not set") @@ -490,6 +468,9 @@ class AuthService(AuthServiceABC): if db_user.password != user_dto.password: raise ServiceException(ServiceErrorCode.InvalidUser, "Wrong password") + if db_user.confirmation_id is not None: + raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified") + token = self.generate_token(db_user) refresh_token = self._create_and_save_refresh_token(db_user) if db_user.forgot_password_id is not None: @@ -498,23 +479,34 @@ class AuthService(AuthServiceABC): self._db.save_changes() return TokenDTO(token, refresh_token) - async def login_discord_async(self, user_dto: AuthUserDTO) -> TokenDTO: + async def login_discord_async(self, user_dto: AuthUserDTO, dc_id: int) -> TokenDTO: if user_dto is None: raise ServiceException(ServiceErrorCode.InvalidData, "User not set") + members = self._users.get_users_by_discord_id(dc_id) + if members.count() == 0: + raise ServiceException(ServiceErrorCode.InvalidUser, f"Member not found") + + added_user = False db_user = self._auth_users.find_auth_user_by_email(user_dto.email) if db_user is None: - await self.add_auth_user_async(user_dto) - # raise ServiceException(ServiceErrorCode.InvalidUser, f'User not found') + self.add_auth_user(user_dto) + added_user = True db_user = self._auth_users.get_auth_user_by_email(user_dto.email) + if db_user.users.count() == 0: + members.for_each(lambda x: self._auth_users.add_auth_user_user_rel(AuthUserUsersRelation(db_user, x))) + + if db_user.confirmation_id is not None and not added_user: + raise ServiceException(ServiceErrorCode.Forbidden, "E-Mail not verified") + token = self.generate_token(db_user) refresh_token = self._create_and_save_refresh_token(db_user) if db_user.forgot_password_id is not None: db_user.forgot_password_id = None self._db.save_changes() - return TokenDTO(token, refresh_token) + return TokenDTO(token, refresh_token, first_login=added_user) async def refresh_async(self, token_dto: TokenDTO) -> TokenDTO: if token_dto is None: diff --git a/kdb-bot/src/bot_api/service/discord_service.py b/kdb-bot/src/bot_api/service/discord_service.py index 4770930a..386b3046 100644 --- a/kdb-bot/src/bot_api/service/discord_service.py +++ b/kdb-bot/src/bot_api/service/discord_service.py @@ -2,7 +2,6 @@ from typing import Optional from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List -from flask import jsonify from bot_api.abc.auth_service_abc import AuthServiceABC from bot_api.exception.service_error_code_enum import ServiceErrorCode @@ -10,7 +9,6 @@ from bot_api.exception.service_exception import ServiceException from bot_api.filter.discord.server_select_criteria import ServerSelectCriteria from bot_api.model.discord.server_dto import ServerDTO from bot_api.model.discord.server_filtered_result_dto import ServerFilteredResultDTO -from bot_api.model.error_dto import ErrorDTO from bot_api.transformer.server_transformer import ServerTransformer from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC @@ -35,7 +33,7 @@ class DiscordService: self._users = users def _to_dto(self, x: Server) -> Optional[ServerDTO]: - guild = self._bot.get_guild(x.discord_server_id) + guild = self._bot.get_guild(x.discord_id) if guild is None: return ServerTransformer.to_dto(x, "", 0, None) @@ -55,8 +53,8 @@ class DiscordService: if role != AuthRoleEnum.admin: auth_user = self._auth_users.find_auth_user_by_email(token["email"]) if auth_user is not None: - user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) - servers = servers.where(lambda x: x.server_id in user_ids) + user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id) + servers = servers.where(lambda x: x.id in user_ids) servers = List(ServerDTO, servers) return servers.select(self._to_dto).where(lambda x: x.name != "") @@ -72,8 +70,8 @@ class DiscordService: if role != AuthRoleEnum.admin: auth_user = self._auth_users.find_auth_user_by_email(token["email"]) if auth_user is not None: - user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.server_id) - filtered_result.result = filtered_result.result.where(lambda x: x.server_id in user_ids) + user_ids = auth_user.users.select(lambda x: x.server is not None and x.server.id) + filtered_result.result = filtered_result.result.where(lambda x: x.id in user_ids) servers: List = filtered_result.result.select(self._to_dto).where(lambda x: x.name != "") result = List(ServerDTO, servers) @@ -87,7 +85,7 @@ class DiscordService: async def get_server_by_id_async(self, id: int) -> ServerDTO: server = self._servers.get_server_by_id(id) - guild = self._bot.get_guild(server.discord_server_id) + guild = self._bot.get_guild(server.discord_id) server_dto = ServerTransformer.to_dto(server, guild.name, guild.member_count, guild.icon) return server_dto diff --git a/kdb-bot/src/bot_api/transformer/__init__.py b/kdb-bot/src/bot_api/transformer/__init__.py index bb9d1aba..5333cd7a 100644 --- a/kdb-bot/src/bot_api/transformer/__init__.py +++ b/kdb-bot/src/bot_api/transformer/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_api.transformer" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_api/transformer/auth_user_transformer.py b/kdb-bot/src/bot_api/transformer/auth_user_transformer.py index 56b35504..9e52fec3 100644 --- a/kdb-bot/src/bot_api/transformer/auth_user_transformer.py +++ b/kdb-bot/src/bot_api/transformer/auth_user_transformer.py @@ -1,9 +1,16 @@ -from datetime import datetime, timezone +from datetime import datetime + +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List from bot_api.abc.transformer_abc import TransformerABC from bot_api.model.auth_user_dto import AuthUserDTO +from bot_api.model.user_dto import UserDTO from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_user import AuthUser +from bot_data.model.user import User +from modules.permission.abc.permission_service_abc import PermissionServiceABC class AuthUserTransformer(TransformerABC): @@ -25,7 +32,28 @@ class AuthUserTransformer(TransformerABC): ) @staticmethod - def to_dto(db: AuthUser, password: str = None) -> AuthUserDTO: + @ServiceProviderABC.inject + def _is_technician(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): + guild = bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return permissions.is_member_technician(member) + + @staticmethod + @ServiceProviderABC.inject + def _is_admin(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): + guild = bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return permissions.is_member_admin(member) + + @staticmethod + @ServiceProviderABC.inject + def _is_moderator(user: User, bot: DiscordBotServiceABC, permissions: PermissionServiceABC): + guild = bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return permissions.is_member_moderator(member) + + @classmethod + def to_dto(cls, db: AuthUser, password: str = None) -> AuthUserDTO: return AuthUserDTO( db.id, db.first_name, @@ -34,4 +62,20 @@ class AuthUserTransformer(TransformerABC): "" if password is None else password, db.confirmation_id, db.auth_role, + List( + UserDTO, + db.users.select( + lambda u: UserDTO( + u.id, + u.discord_id, + u.xp, + u.server, + cls._is_technician(u), + cls._is_admin(u), + cls._is_moderator(u), + ) + ), + ), + db.created_at, + db.modified_at, ) diff --git a/kdb-bot/src/bot_api/transformer/server_transformer.py b/kdb-bot/src/bot_api/transformer/server_transformer.py index bc4c5eeb..bffba8e1 100644 --- a/kdb-bot/src/bot_api/transformer/server_transformer.py +++ b/kdb-bot/src/bot_api/transformer/server_transformer.py @@ -15,8 +15,8 @@ class ServerTransformer(TransformerABC): @staticmethod def to_dto(db: Server, name: str, member_count: int, icon_url: Optional[discord.Asset]) -> ServerDTO: return ServerDTO( - db.server_id, - db.discord_server_id, + db.id, + db.discord_id, name, member_count, icon_url.url if icon_url is not None else None, diff --git a/kdb-bot/src/bot_core/__init__.py b/kdb-bot/src/bot_core/__init__.py index ae80e11c..82d28f71 100644 --- a/kdb-bot/src/bot_core/__init__.py +++ b/kdb-bot/src/bot_core/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/abc/__init__.py b/kdb-bot/src/bot_core/abc/__init__.py index f4e94fab..ab040e04 100644 --- a/kdb-bot/src/bot_core/abc/__init__.py +++ b/kdb-bot/src/bot_core/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.abc" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/bot-core.json b/kdb-bot/src/bot_core/bot-core.json index 2dfa0fdd..89deafc0 100644 --- a/kdb-bot/src/bot_core/bot-core.json +++ b/kdb-bot/src/bot_core/bot-core.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "bot-core", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/kdb-bot/src/bot_core/configuration/__init__.py b/kdb-bot/src/bot_core/configuration/__init__.py index 44e18912..757c7d40 100644 --- a/kdb-bot/src/bot_core/configuration/__init__.py +++ b/kdb-bot/src/bot_core/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.configuration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/configuration/feature_flags_enum.py b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py index c5312cdf..aeb18a99 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_enum.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_enum.py @@ -10,12 +10,12 @@ class FeatureFlagsEnum(Enum): boot_log_module = "BootLogModule" core_module = "CoreModule" core_extension_module = "CoreExtensionModule" - data_module = ("DataModule",) - database_module = ("DatabaseModule",) + data_module = "DataModule" + database_module = "DatabaseModule" level_module = "LevelModule" moderator_module = "ModeratorModule" permission_module = "PermissionModule" - stats_module = "StatsModule" # features api_only = "ApiOnly" presence = "Presence" + version_in_presence = "VersionInPresence" diff --git a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py index 966b746e..777e256b 100644 --- a/kdb-bot/src/bot_core/configuration/feature_flags_settings.py +++ b/kdb-bot/src/bot_core/configuration/feature_flags_settings.py @@ -1,5 +1,4 @@ import traceback -from typing import Optional, Callable from cpl_core.configuration.configuration_model_abc import ConfigurationModelABC from cpl_core.console import Console @@ -24,10 +23,10 @@ class FeatureFlagsSettings(ConfigurationModelABC): FeatureFlagsEnum.database_module.value: True, # 02.10.2022 #48 FeatureFlagsEnum.moderator_module.value: False, # 02.10.2022 #48 FeatureFlagsEnum.permission_module.value: True, # 02.10.2022 #48 - FeatureFlagsEnum.stats_module.value: True, # 08.11.2022 #46 # features FeatureFlagsEnum.api_only.value: False, # 13.10.2022 #70 FeatureFlagsEnum.presence.value: True, # 03.10.2022 #56 + FeatureFlagsEnum.version_in_presence.value: False, # 21.03.2023 #253 } def get_flag(self, key: FeatureFlagsEnum) -> bool: diff --git a/kdb-bot/src/bot_core/core_extension/__init__.py b/kdb-bot/src/bot_core/core_extension/__init__.py index f0b64462..07830ca1 100644 --- a/kdb-bot/src/bot_core/core_extension/__init__.py +++ b/kdb-bot/src/bot_core/core_extension/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.core_extension" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/events/__init__.py b/kdb-bot/src/bot_core/events/__init__.py index 6dfe3aa6..de5bfaf5 100644 --- a/kdb-bot/src/bot_core/events/__init__.py +++ b/kdb-bot/src/bot_core/events/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.events" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/exception/__init__.py b/kdb-bot/src/bot_core/exception/__init__.py index ba8991ba..af0da44f 100644 --- a/kdb-bot/src/bot_core/exception/__init__.py +++ b/kdb-bot/src/bot_core/exception/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.exception" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/helper/__init__.py b/kdb-bot/src/bot_core/helper/__init__.py index 1a4def5d..5e40943d 100644 --- a/kdb-bot/src/bot_core/helper/__init__.py +++ b/kdb-bot/src/bot_core/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.helper" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/logging/__init__.py b/kdb-bot/src/bot_core/logging/__init__.py index 83907227..f67b17a2 100644 --- a/kdb-bot/src/bot_core/logging/__init__.py +++ b/kdb-bot/src/bot_core/logging/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.logging" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/pipes/__init__.py b/kdb-bot/src/bot_core/pipes/__init__.py index 6f925684..47ea6665 100644 --- a/kdb-bot/src/bot_core/pipes/__init__.py +++ b/kdb-bot/src/bot_core/pipes/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.pipes" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/service/__init__.py b/kdb-bot/src/bot_core/service/__init__.py index 30a597d0..d41c0f27 100644 --- a/kdb-bot/src/bot_core/service/__init__.py +++ b/kdb-bot/src/bot_core/service/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_core.service" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_core/service/client_utils_service.py b/kdb-bot/src/bot_core/service/client_utils_service.py index 414b62e2..deab648d 100644 --- a/kdb-bot/src/bot_core/service/client_utils_service.py +++ b/kdb-bot/src/bot_core/service/client_utils_service.py @@ -60,28 +60,28 @@ class ClientUtilsService(ClientUtilsABC): def received_command(self, guild_id: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) client.received_command_count += 1 self._clients.update_client(client) self._db.save_changes() def moved_user(self, guild_id: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) client.moved_users_count += 1 self._clients.update_client(client) self._db.save_changes() def moved_users(self, guild_id: int, count: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) client.moved_users_count += count self._clients.update_client(client) self._db.save_changes() def get_client(self, dc_ic: int, guild_id: int): server = self._servers.get_server_by_discord_id(guild_id) - client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.server_id) + client = self._clients.find_client_by_discord_id_and_server_id(self._bot.user.id, server.id) return client async def check_if_bot_is_ready_yet(self) -> bool: @@ -111,7 +111,11 @@ class ClientUtilsService(ClientUtilsABC): import bot - name = self._t.transform(t_key).format(bot.__version__) + if self._feature_flags.get_flag(FeatureFlagsEnum.version_in_presence): + name = f"{bot.__version__} {self._t.transform(t_key)}" + else: + name = self._t.transform(t_key) + await self._bot.change_presence(activity=discord.Game(name=name)) self._logger.info(__name__, f"Set presence {name}") @@ -138,7 +142,7 @@ class ClientUtilsService(ClientUtilsABC): ) -> bool: umcph = None try: - umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.user_id, created_at) + umcph = self._umcphs.find_user_message_count_per_hour_by_user_id_and_date(user.id, created_at) if umcph is None: self._umcphs.add_user_message_count_per_hour( UserMessageCountPerHour( @@ -151,7 +155,7 @@ class ClientUtilsService(ClientUtilsABC): self._db.save_changes() - umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.user_id, created_at) + umcph = self._umcphs.get_user_message_count_per_hour_by_user_id_and_date(user.id, created_at) except Exception as e: self._logger.error( __name__, @@ -183,7 +187,7 @@ class ClientUtilsService(ClientUtilsABC): def get_ontime_for_user(self, user: User) -> float: return round( - self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.user_id) + self._user_joined_voice_channel.get_user_joined_voice_channels_by_user_id(user.id) .where(lambda x: x.leaved_on is not None and x.joined_on is not None) .sum(lambda join: (join.leaved_on - join.joined_on).total_seconds() / 3600), 2, diff --git a/kdb-bot/src/bot_data/__init__.py b/kdb-bot/src/bot_data/__init__.py index 62c66f89..fa5f8649 100644 --- a/kdb-bot/src/bot_data/__init__.py +++ b/kdb-bot/src/bot_data/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_data" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_data/abc/__init__.py b/kdb-bot/src/bot_data/abc/__init__.py index 2991e1e7..3263edb3 100644 --- a/kdb-bot/src/bot_data/abc/__init__.py +++ b/kdb-bot/src/bot_data/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_data.abc" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_data/abc/api_key_repository_abc.py b/kdb-bot/src/bot_data/abc/api_key_repository_abc.py new file mode 100644 index 00000000..aaa22dbe --- /dev/null +++ b/kdb-bot/src/bot_data/abc/api_key_repository_abc.py @@ -0,0 +1,39 @@ +from abc import ABC, abstractmethod + +from cpl_query.extension import List + +from bot_data.model.api_key import ApiKey + + +class ApiKeyRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_api_keys(self) -> List[ApiKey]: + pass + + @abstractmethod + def get_api_key(self, identifier: str, key: str) -> ApiKey: + pass + + @abstractmethod + def get_api_key_by_id(self, id: int) -> ApiKey: + pass + + @abstractmethod + def get_api_key_by_key(self, key: str) -> ApiKey: + pass + + @abstractmethod + def add_api_key(self, api_key: ApiKey): + pass + + @abstractmethod + def update_api_key(self, api_key: ApiKey): + pass + + @abstractmethod + def delete_api_key(self, api_key: ApiKey): + pass diff --git a/kdb-bot/src/bot_data/abc/client_repository_abc.py b/kdb-bot/src/bot_data/abc/client_repository_abc.py index 97d34e13..3b9f9132 100644 --- a/kdb-bot/src/bot_data/abc/client_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/client_repository_abc.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from typing import Optional from cpl_query.extension import List + from bot_data.model.client import Client @@ -22,6 +23,10 @@ class ClientRepositoryABC(ABC): def get_client_by_discord_id(self, discord_id: int) -> Client: pass + @abstractmethod + def get_clients_by_server_id(self, server_id: int) -> List[Client]: + pass + @abstractmethod def find_client_by_discord_id(self, discord_id: int) -> Optional[Client]: pass diff --git a/kdb-bot/src/bot_data/abc/game_server_repository_abc.py b/kdb-bot/src/bot_data/abc/game_server_repository_abc.py new file mode 100644 index 00000000..50e6fe7a --- /dev/null +++ b/kdb-bot/src/bot_data/abc/game_server_repository_abc.py @@ -0,0 +1,39 @@ +from abc import ABC, abstractmethod + +from cpl_query.extension import List + +from bot_data.model.game_server import GameServer + + +class GameServerRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_game_servers(self) -> List[GameServer]: + pass + + @abstractmethod + def get_game_server_by_id(self, id: int) -> GameServer: + pass + + @abstractmethod + def get_game_servers_by_server_id(self, id: int) -> List[GameServer]: + pass + + @abstractmethod + def get_game_server_by_api_key_id(self, id: int) -> GameServer: + pass + + @abstractmethod + def add_game_server(self, game_server: GameServer): + pass + + @abstractmethod + def update_game_server(self, game_server: GameServer): + pass + + @abstractmethod + def delete_game_server(self, game_server: GameServer): + pass diff --git a/kdb-bot/src/bot_data/abc/history_table_abc.py b/kdb-bot/src/bot_data/abc/history_table_abc.py new file mode 100644 index 00000000..4f96da31 --- /dev/null +++ b/kdb-bot/src/bot_data/abc/history_table_abc.py @@ -0,0 +1,27 @@ +from abc import ABC, abstractmethod +from datetime import datetime + + +class HistoryTableABC(ABC): + @abstractmethod + def __init__(self): + self._id = 0 + self._deleted = False + self._date_from = datetime.now().isoformat() + self._date_to = datetime.now().isoformat() + + @property + def id(self) -> int: + return self._id + + @property + def deleted(self) -> bool: + return self._deleted + + @property + def date_from(self) -> str: + return self._date_from + + @property + def date_to(self) -> str: + return self._date_to diff --git a/kdb-bot/src/bot_data/abc/migration_abc.py b/kdb-bot/src/bot_data/abc/migration_abc.py index f6af458c..e44e0bc2 100644 --- a/kdb-bot/src/bot_data/abc/migration_abc.py +++ b/kdb-bot/src/bot_data/abc/migration_abc.py @@ -3,6 +3,7 @@ from abc import ABC, abstractmethod class MigrationABC(ABC): name = None + prio = 0 @abstractmethod def __init__(self): diff --git a/kdb-bot/src/bot_data/abc/statistic_repository_abc.py b/kdb-bot/src/bot_data/abc/statistic_repository_abc.py deleted file mode 100644 index c901ba43..00000000 --- a/kdb-bot/src/bot_data/abc/statistic_repository_abc.py +++ /dev/null @@ -1,44 +0,0 @@ -from abc import ABC, abstractmethod -from typing import Optional - -from cpl_query.extension import List - -from bot_data.model.statistic import Statistic - - -class StatisticRepositoryABC(ABC): - @abstractmethod - def __init__(self): - pass - - @abstractmethod - def get_statistics(self) -> List[Statistic]: - pass - - @abstractmethod - def get_statistics_by_server_id(self, server_id: int) -> List[Statistic]: - pass - - @abstractmethod - def get_statistic_by_id(self, id: int) -> Statistic: - pass - - @abstractmethod - def get_statistic_by_name(self, name: str, server_id: int) -> Statistic: - pass - - @abstractmethod - def find_statistic_by_name(self, name: str, server_id: int) -> Optional[Statistic]: - pass - - @abstractmethod - def add_statistic(self, statistic: Statistic): - pass - - @abstractmethod - def update_statistic(self, statistic: Statistic): - pass - - @abstractmethod - def delete_statistic(self, statistic: Statistic): - pass diff --git a/kdb-bot/src/bot_data/abc/table_with_id_abc.py b/kdb-bot/src/bot_data/abc/table_with_id_abc.py new file mode 100644 index 00000000..720941cf --- /dev/null +++ b/kdb-bot/src/bot_data/abc/table_with_id_abc.py @@ -0,0 +1,15 @@ +from abc import abstractmethod + +from cpl_core.database import TableABC + + +class TableWithIdABC(TableABC): + @abstractmethod + def __init__(self): + self.__init__() + + self._id = 0 + + @property + def id(self) -> int: + return self._id diff --git a/kdb-bot/src/bot_data/abc/user_game_ident_repository_abc.py b/kdb-bot/src/bot_data/abc/user_game_ident_repository_abc.py new file mode 100644 index 00000000..fbaa0831 --- /dev/null +++ b/kdb-bot/src/bot_data/abc/user_game_ident_repository_abc.py @@ -0,0 +1,47 @@ +from abc import ABC, abstractmethod + +from cpl_query.extension import List + +from bot_data.model.user_game_ident import UserGameIdent + + +class UserGameIdentRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_user_game_idents(self) -> List[UserGameIdent]: + pass + + @abstractmethod + def get_user_game_ident_by_id(self, id: int) -> UserGameIdent: + pass + + @abstractmethod + def get_user_game_ident_by_ident(self, ident: str) -> UserGameIdent: + pass + + @abstractmethod + def find_user_game_ident_by_ident(self, ident: str) -> UserGameIdent: + pass + + @abstractmethod + def get_user_game_idents_by_user_id(self, user_id: int) -> List[UserGameIdent]: + pass + + @abstractmethod + def add_user_game_ident(self, user_game_ident: UserGameIdent): + pass + + @abstractmethod + def update_user_game_ident(self, user_game_ident: UserGameIdent): + pass + + @abstractmethod + def delete_user_game_ident(self, user_game_ident: UserGameIdent): + pass + + @abstractmethod + def delete_user_game_ident_by_user_id(self, user_id: int): + pass diff --git a/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py b/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py new file mode 100644 index 00000000..97a0358b --- /dev/null +++ b/kdb-bot/src/bot_data/abc/user_joined_game_server_repository_abc.py @@ -0,0 +1,52 @@ +from abc import ABC, abstractmethod +from typing import Optional + +from cpl_query.extension import List + +from bot_data.model.user_joined_game_server import UserJoinedGameServer + + +class UserJoinedGameServerRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]: + pass + + @abstractmethod + def get_user_joined_game_server_by_id(self, id: int) -> UserJoinedGameServer: + pass + + @abstractmethod + def get_user_joined_game_servers_by_user_id(self, user_id: int) -> List[UserJoinedGameServer]: + pass + + @abstractmethod + def get_active_user_joined_game_server_by_user_id(self, user_id: int) -> UserJoinedGameServer: + pass + + @abstractmethod + def find_active_user_joined_game_server_by_user_id(self, user_id: int) -> Optional[UserJoinedGameServer]: + pass + + @abstractmethod + def find_active_user_joined_game_servers_by_user_id(self, user_id: int) -> List[Optional[UserJoinedGameServer]]: + pass + + @abstractmethod + def add_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): + pass + + @abstractmethod + def update_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): + pass + + @abstractmethod + def delete_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): + pass + + @abstractmethod + def delete_user_joined_game_server_by_user_id(self, user_id: int): + pass diff --git a/kdb-bot/src/bot_data/abc/user_joined_server_repository_abc.py b/kdb-bot/src/bot_data/abc/user_joined_server_repository_abc.py index 2b8dcc5f..cbc3a718 100644 --- a/kdb-bot/src/bot_data/abc/user_joined_server_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/user_joined_server_repository_abc.py @@ -2,6 +2,7 @@ from abc import ABC, abstractmethod from typing import Optional from cpl_query.extension import List + from bot_data.model.user_joined_server import UserJoinedServer @@ -18,6 +19,10 @@ class UserJoinedServerRepositoryABC(ABC): def get_user_joined_server_by_id(self, id: int) -> UserJoinedServer: pass + @abstractmethod + def get_user_joined_server_by_server_id(self, server_id: int) -> UserJoinedServer: + pass + @abstractmethod def get_user_joined_servers_by_user_id(self, user_id: int) -> list[UserJoinedServer]: pass diff --git a/kdb-bot/src/bot_data/abc/user_repository_abc.py b/kdb-bot/src/bot_data/abc/user_repository_abc.py index c40f20e5..0e3ced21 100644 --- a/kdb-bot/src/bot_data/abc/user_repository_abc.py +++ b/kdb-bot/src/bot_data/abc/user_repository_abc.py @@ -27,6 +27,10 @@ class UserRepositoryABC(ABC): def get_users_by_discord_id(self, discord_id: int) -> List[User]: pass + @abstractmethod + def get_users_by_server_id(self, server_id: int) -> List[User]: + pass + @abstractmethod def get_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> User: pass diff --git a/kdb-bot/src/bot_data/abc/user_warnings_repository_abc.py b/kdb-bot/src/bot_data/abc/user_warnings_repository_abc.py new file mode 100644 index 00000000..bb5d9e9b --- /dev/null +++ b/kdb-bot/src/bot_data/abc/user_warnings_repository_abc.py @@ -0,0 +1,35 @@ +from abc import ABC, abstractmethod + +from cpl_query.extension import List + +from bot_data.model.user_warnings import UserWarnings + + +class UserWarningsRepositoryABC(ABC): + @abstractmethod + def __init__(self): + pass + + @abstractmethod + def get_user_warnings(self) -> List[UserWarnings]: + pass + + @abstractmethod + def get_user_warnings_by_id(self, id: int) -> UserWarnings: + pass + + @abstractmethod + def get_user_warnings_by_user_id(self, user_id: int) -> List[UserWarnings]: + pass + + @abstractmethod + def add_user_warnings(self, user_warnings: UserWarnings): + pass + + @abstractmethod + def update_user_warnings(self, user_warnings: UserWarnings): + pass + + @abstractmethod + def delete_user_warnings(self, user_warnings: UserWarnings): + pass diff --git a/kdb-bot/src/bot_data/bot-data.json b/kdb-bot/src/bot_data/bot-data.json index 5fd0d0e1..4a634420 100644 --- a/kdb-bot/src/bot_data/bot-data.json +++ b/kdb-bot/src/bot_data/bot-data.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "bot-data", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/kdb-bot/src/bot_data/data_module.py b/kdb-bot/src/bot_data/data_module.py index 87152541..fb37c20d 100644 --- a/kdb-bot/src/bot_data/data_module.py +++ b/kdb-bot/src/bot_data/data_module.py @@ -5,13 +5,16 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC from bot_data.abc.auth_user_repository_abc import AuthUserRepositoryABC from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC from bot_data.abc.level_repository_abc import LevelRepositoryABC from bot_data.abc.server_repository_abc import ServerRepositoryABC -from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC +from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC +from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import ( UserJoinedVoiceChannelRepositoryABC, @@ -20,14 +23,18 @@ from bot_data.abc.user_message_count_per_hour_repository_abc import ( UserMessageCountPerHourRepositoryABC, ) from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC +from bot_data.service.api_key_repository_service import ApiKeyRepositoryService from bot_data.service.auth_user_repository_service import AuthUserRepositoryService from bot_data.service.auto_role_repository_service import AutoRoleRepositoryService from bot_data.service.client_repository_service import ClientRepositoryService +from bot_data.service.game_server_repository_service import GameServerRepositoryService from bot_data.service.known_user_repository_service import KnownUserRepositoryService from bot_data.service.level_repository_service import LevelRepositoryService from bot_data.service.seeder_service import SeederService from bot_data.service.server_repository_service import ServerRepositoryService -from bot_data.service.statistic_repository_service import StatisticRepositoryService +from bot_data.service.user_game_ident_repository_service import UserGameIdentRepositoryService +from bot_data.service.user_joined_game_server_repository_service import UserJoinedGameServerRepositoryService from bot_data.service.user_joined_server_repository_service import ( UserJoinedServerRepositoryService, ) @@ -38,6 +45,7 @@ from bot_data.service.user_message_count_per_hour_repository_service import ( UserMessageCountPerHourRepositoryService, ) from bot_data.service.user_repository_service import UserRepositoryService +from bot_data.service.user_warnings_repository_service import UserWarningsRepositoryService class DataModule(ModuleABC): @@ -48,6 +56,7 @@ class DataModule(ModuleABC): pass def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services.add_transient(ApiKeyRepositoryABC, ApiKeyRepositoryService) services.add_transient(AuthUserRepositoryABC, AuthUserRepositoryService) services.add_transient(ServerRepositoryABC, ServerRepositoryService) services.add_transient(UserRepositoryABC, UserRepositoryService) @@ -55,12 +64,15 @@ class DataModule(ModuleABC): services.add_transient(KnownUserRepositoryABC, KnownUserRepositoryService) services.add_transient(UserJoinedServerRepositoryABC, UserJoinedServerRepositoryService) services.add_transient(UserJoinedVoiceChannelRepositoryABC, UserJoinedVoiceChannelRepositoryService) + services.add_transient(UserJoinedGameServerRepositoryABC, UserJoinedGameServerRepositoryService) services.add_transient(AutoRoleRepositoryABC, AutoRoleRepositoryService) services.add_transient(LevelRepositoryABC, LevelRepositoryService) - services.add_transient(StatisticRepositoryABC, StatisticRepositoryService) + services.add_transient(UserWarningsRepositoryABC, UserWarningsRepositoryService) services.add_transient( UserMessageCountPerHourRepositoryABC, UserMessageCountPerHourRepositoryService, ) + services.add_transient(GameServerRepositoryABC, GameServerRepositoryService) + services.add_transient(UserGameIdentRepositoryABC, UserGameIdentRepositoryService) services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_data/db_context.py b/kdb-bot/src/bot_data/db_context.py index 6e208ed9..6e11f284 100644 --- a/kdb-bot/src/bot_data/db_context.py +++ b/kdb-bot/src/bot_data/db_context.py @@ -6,7 +6,6 @@ from bot_core.logging.database_logger import DatabaseLogger class DBContext(DatabaseContext): def __init__(self, logger: DatabaseLogger): - self._logger = logger DatabaseContext.__init__(self) diff --git a/kdb-bot/src/bot_data/migration/__init__.py b/kdb-bot/src/bot_data/migration/__init__.py index 0bc7eecc..ea1b7668 100644 --- a/kdb-bot/src/bot_data/migration/__init__.py +++ b/kdb-bot/src/bot_data/migration/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_data.migration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_data/migration/api_key_migration.py b/kdb-bot/src/bot_data/migration/api_key_migration.py new file mode 100644 index 00000000..0712974b --- /dev/null +++ b/kdb-bot/src/bot_data/migration/api_key_migration.py @@ -0,0 +1,38 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class ApiKeyMigration(MigrationABC): + name = "1.0.0_ApiKeyMigration" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `ApiKeys` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `Identifier` VARCHAR(255) NOT NULL, + `Key` VARCHAR(255) NOT NULL, + `CreatorId` BIGINT NULL, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`Id`), + FOREIGN KEY (`CreatorId`) REFERENCES `Users`(`UserId`), + CONSTRAINT UC_Identifier_Key UNIQUE (`Identifier`,`Key`), + CONSTRAINT UC_Key UNIQUE (`Key`) + ); + """ + ) + ) + + def downgrade(self): + self._cursor.execute("DROP TABLE `ApiKeys`;") diff --git a/kdb-bot/src/bot_data/migration/auto_role_fix1_migration.py b/kdb-bot/src/bot_data/migration/auto_role_fix1_migration.py index 7a5766c2..70a8e30e 100644 --- a/kdb-bot/src/bot_data/migration/auto_role_fix1_migration.py +++ b/kdb-bot/src/bot_data/migration/auto_role_fix1_migration.py @@ -4,7 +4,7 @@ from bot_data.db_context import DBContext class AutoRoleFix1Migration(MigrationABC): - name = "0.3.0_AutoRoleMigration" + name = "0.3.0_AutoRoleFixMigration" def __init__(self, logger: DatabaseLogger, db: DBContext): MigrationABC.__init__(self) diff --git a/kdb-bot/src/bot_data/migration/db_history_migration.py b/kdb-bot/src/bot_data/migration/db_history_migration.py new file mode 100644 index 00000000..e7322ad9 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_migration.py @@ -0,0 +1,65 @@ +import os + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class DBHistoryMigration(MigrationABC): + name = "1.0.0_DBHistoryMigration" + prio = 1 + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def _exec(self, file: str): + path = f"{os.path.dirname(os.path.realpath(__file__))}/db_history_scripts" + sql = open(f"{path}/{file}").read() + + for statement in sql.split("\n\n"): + self._cursor.execute(statement + ";") + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._exec("api_keys.sql") + self._exec("auth_users.sql") + self._exec("auth_user_users_relation.sql") + self._exec("auto_role_rules.sql") + self._exec("auto_roles.sql") + self._exec("clients.sql") + self._exec("game_servers.sql") + self._exec("known_users.sql") + self._exec("levels.sql") + self._exec("servers.sql") + self._exec("user_game_idents.sql") + self._exec("user_joined_game_servers.sql") + self._exec("user_joined_servers.sql") + self._exec("user_joined_voice_channel.sql") + self._exec("user_message_count_per_hour.sql") + self._exec("users.sql") + self._exec("user_warnings.sql") + + self._logger.debug(__name__, "Finished history upgrade") + + def downgrade(self): + self._cursor.execute("DROP TABLE `ApiKeysHistory`;") + self._cursor.execute("DROP TABLE `AuthUsersHistory`;") + self._cursor.execute("DROP TABLE `AuthUserUsersRelationsHistory`;") + self._cursor.execute("DROP TABLE `AutoRoleRulesHistory`;") + self._cursor.execute("DROP TABLE `AutoRolesHistory`;") + self._cursor.execute("DROP TABLE `ClientsHistory`;") + self._cursor.execute("DROP TABLE `GameServersHistory`;") + self._cursor.execute("DROP TABLE `KnownUsersHistory`;") + self._cursor.execute("DROP TABLE `LevelsHistory`;") + self._cursor.execute("DROP TABLE `ServersHistory`;") + self._cursor.execute("DROP TABLE `UserGameIdentsHistory`;") + self._cursor.execute("DROP TABLE `UserJoinedGameServerHistory`;") + self._cursor.execute("DROP TABLE `UserJoinedServersHistory`;") + self._cursor.execute("DROP TABLE `UserJoinedVoiceChannelHistory`;") + self._cursor.execute("DROP TABLE `UserMessageCountPerHourHistory`;") + self._cursor.execute("DROP TABLE `UsersHistory`;") + self._cursor.execute("DROP TABLE `UserWarningsHistory`;") diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/api_keys.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/api_keys.sql new file mode 100644 index 00000000..10285da4 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/api_keys.sql @@ -0,0 +1,46 @@ +ALTER TABLE `ApiKeys` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `ApiKeys` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `ApiKeysHistory` +( + `Id` BIGINT(20) NOT NULL, + `Identifier` VARCHAR(255) NOT NULL, + `Key` VARCHAR(255) NOT NULL, + `CreatorId` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_ApiKeysUpdate`; + +CREATE TRIGGER `TR_ApiKeysUpdate` + AFTER UPDATE + ON `ApiKeys` + FOR EACH ROW +BEGIN + INSERT INTO `ApiKeysHistory` ( + `Id`, `Identifier`, `Key`, `CreatorId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Identifier, OLD.Key, OLD.CreatorId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_ApiKeysDelete`; + +CREATE TRIGGER `TR_ApiKeysDelete` + AFTER DELETE + ON `ApiKeys` + FOR EACH ROW +BEGIN + INSERT INTO `ApiKeysHistory` ( + `Id`, `Identifier`, `Key`, `CreatorId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Identifier, OLD.Key, OLD.CreatorId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/auth_user_users_relation.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/auth_user_users_relation.sql new file mode 100644 index 00000000..2ce0d762 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/auth_user_users_relation.sql @@ -0,0 +1,46 @@ +ALTER TABLE `AuthUserUsersRelations` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `AuthUserUsersRelations` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + + +CREATE TABLE IF NOT EXISTS `AuthUserUsersRelationsHistory` +( + `Id` BIGINT(20) NOT NULL, + `AuthUserId` BIGINT(20) DEFAULT NULL, + `UserId` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_AuthUserUsersRelationsUpdate`; + +CREATE TRIGGER `TR_AuthUserUsersRelationsUpdate` + AFTER UPDATE + ON `AuthUserUsersRelations` + FOR EACH ROW +BEGIN + INSERT INTO `AuthUserUsersRelationsHistory` ( + `Id`, `AuthUserId`, `UserId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.AuthUserId, OLD.UserId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_AuthUserUsersRelationsDelete`; + +CREATE TRIGGER `TR_AuthUserUsersRelationsDelete` + AFTER DELETE + ON `AuthUserUsersRelations` + FOR EACH ROW +BEGIN + INSERT INTO `AuthUserUsersRelationsHistory` ( + `Id`, `AuthUserId`, `UserId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.AuthUserId, OLD.UserId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/auth_users.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/auth_users.sql new file mode 100644 index 00000000..ab22cc65 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/auth_users.sql @@ -0,0 +1,62 @@ +ALTER TABLE `AuthUsers` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `AuthUsers` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `AuthUsersHistory` +( + `Id` BIGINT(20) NOT NULL, + `FirstName` VARCHAR(255) DEFAULT NULL, + `LastName` VARCHAR(255) DEFAULT NULL, + `EMail` VARCHAR(255) DEFAULT NULL, + `Password` VARCHAR(255) DEFAULT NULL, + `PasswordSalt` VARCHAR(255) DEFAULT NULL, + `RefreshToken` VARCHAR(255) DEFAULT NULL, + `ConfirmationId` VARCHAR(255) DEFAULT NULL, + `ForgotPasswordId` VARCHAR(255) DEFAULT NULL, + `OAuthId` VARCHAR(255) DEFAULT NULL, + `RefreshTokenExpiryTime` DATETIME(6) NOT NULL, + `AuthRole` BIGINT(11) NOT NULL DEFAULT 0, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_AuthUsersUpdate`; + +CREATE TRIGGER `TR_AuthUsersUpdate` + AFTER UPDATE + ON `AuthUsers` + FOR EACH ROW +BEGIN + INSERT INTO `AuthUsersHistory` ( + `Id`, `FirstName`, `LastName`, `EMail`, `Password`, `PasswordSalt`, + `RefreshToken`, `ConfirmationId`, `ForgotPasswordId`, `OAuthId`, + `RefreshTokenExpiryTime`, `AuthRole`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.FirstName, OLD.LastName, OLD.EMail, OLD.Password, OLD.PasswordSalt, OLD.RefreshToken, + OLD.ConfirmationId, OLD.ForgotPasswordId, OLD.OAuthId, OLD.RefreshTokenExpiryTime, OLD.AuthRole, + OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_AuthUsersDelete`; + +CREATE TRIGGER `TR_AuthUsersDelete` + AFTER DELETE + ON `AuthUsers` + FOR EACH ROW +BEGIN + INSERT INTO `AuthUsersHistory` ( + `Id`, `FirstName`, `LastName`, `EMail`, `Password`, `PasswordSalt`, `RefreshToken`, + `ConfirmationId`, `ForgotPasswordId`, `OAuthId`, `RefreshTokenExpiryTime`, + `AuthRole`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.FirstName, OLD.LastName, OLD.EMail, OLD.Password, OLD.PasswordSalt, OLD.RefreshToken, + OLD.ConfirmationId, OLD.ForgotPasswordId, OLD.OAuthId, OLD.RefreshTokenExpiryTime, OLD.AuthRole, TRUE, + OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/auto_role_rules.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/auto_role_rules.sql new file mode 100644 index 00000000..bcfa5f77 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/auto_role_rules.sql @@ -0,0 +1,46 @@ +ALTER TABLE `AutoRoleRules` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `AutoRoleRules` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `AutoRoleRulesHistory` +( + `Id` BIGINT(20) NOT NULL, + `AutoRoleId` BIGINT(20) DEFAULT NULL, + `DiscordEmojiName` VARCHAR(64) DEFAULT NULL, + `DiscordRoleId` BIGINT(20) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_AutoRoleRulesUpdate`; + +CREATE TRIGGER `TR_AutoRoleRulesUpdate` + AFTER UPDATE + ON `AutoRoleRules` + FOR EACH ROW +BEGIN + INSERT INTO `AutoRoleRulesHistory` ( + `Id`, `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.AutoRoleRuleId, OLD.AutoRoleId, OLD.DiscordEmojiName, OLD.DiscordRoleId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_AutoRoleRulesDelete`; + +CREATE TRIGGER `TR_AutoRoleRulesDelete` + AFTER DELETE + ON `AutoRoleRules` + FOR EACH ROW +BEGIN + INSERT INTO `AutoRoleRulesHistory` ( + `Id`, `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.AutoRoleRuleId, OLD.AutoRoleId, OLD.DiscordEmojiName, OLD.DiscordRoleId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/auto_roles.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/auto_roles.sql new file mode 100644 index 00000000..7b78ea02 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/auto_roles.sql @@ -0,0 +1,48 @@ +ALTER TABLE `AutoRoles` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `AutoRoles` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `AutoRolesHistory` +( + `Id` BIGINT(20) NOT NULL, + `ServerId` BIGINT(20) DEFAULT NULL, + `DiscordChannelId` BIGINT(20) NOT NULL, + `DiscordMessageId` BIGINT(20) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_AutoRolesUpdate`; + +CREATE TRIGGER `TR_AutoRolesUpdate` + AFTER UPDATE + ON `AutoRoles` + FOR EACH ROW +BEGIN + INSERT INTO `AutoRolesHistory` ( + `Id`, `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.AutoRoleId, OLD.ServerId, OLD.DiscordChannelId, OLD.DiscordMessageId, OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_AutoRolesDelete`; + +CREATE TRIGGER `TR_AutoRolesDelete` + AFTER DELETE + ON `AutoRoles` + FOR EACH ROW +BEGIN + INSERT INTO `AutoRolesHistory` ( + `Id`, `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.AutoRoleId, OLD.ServerId, OLD.DiscordChannelId, OLD.DiscordMessageId, TRUE, OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/clients.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/clients.sql new file mode 100644 index 00000000..b1048785 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/clients.sql @@ -0,0 +1,54 @@ +ALTER TABLE `Clients` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `Clients` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `ClientsHistory` +( + `Id` BIGINT(20) NOT NULL, + `DiscordId` BIGINT(20) NOT NULL, + `SentMessageCount` BIGINT(20) NOT NULL DEFAULT 0, + `ReceivedMessageCount` BIGINT(20) NOT NULL DEFAULT 0, + `DeletedMessageCount` BIGINT(20) NOT NULL DEFAULT 0, + `ReceivedCommandsCount` BIGINT(20) NOT NULL DEFAULT 0, + `MovedUsersCount` BIGINT(20) NOT NULL DEFAULT 0, + `ServerId` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_ClientsUpdate`; + +CREATE TRIGGER `TR_ClientsUpdate` + AFTER UPDATE + ON `Clients` + FOR EACH ROW +BEGIN + INSERT INTO `ClientsHistory` ( + `Id`, `DiscordId`, `SentMessageCount`, `ReceivedMessageCount`, `DeletedMessageCount`, + `ReceivedCommandsCount`, `MovedUsersCount`, `ServerId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.ClientId, OLD.DiscordClientId, OLD.SentMessageCount, OLD.ReceivedMessageCount, OLD.DeletedMessageCount, + OLD.ReceivedCommandsCount, OLD.MovedUsersCount, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_ClientsDelete`; + +CREATE TRIGGER `TR_ClientsDelete` + AFTER DELETE + ON `Clients` + FOR EACH ROW +BEGIN + INSERT INTO `ClientsHistory` ( + `Id`, `DiscordId`, `SentMessageCount`, `ReceivedMessageCount`, `DeletedMessageCount`, + `ReceivedCommandsCount`, `MovedUsersCount`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.ClientId, OLD.DiscordClientId, OLD.SentMessageCount, OLD.ReceivedMessageCount, OLD.DeletedMessageCount, + OLD.ReceivedCommandsCount, OLD.MovedUsersCount, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/game_servers.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/game_servers.sql new file mode 100644 index 00000000..091cbf51 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/game_servers.sql @@ -0,0 +1,46 @@ +ALTER TABLE `GameServers` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `GameServers` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `GameServersHistory` +( + `Id` BIGINT(20) NOT NULL, + `Name` VARCHAR(255) NOT NULL, + `ServerId` BIGINT(20) NOT NULL, + `ApiKeyId` BIGINT(20) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_GameServersUpdate`; + +CREATE TRIGGER `TR_GameServersUpdate` + AFTER UPDATE + ON `GameServers` + FOR EACH ROW +BEGIN + INSERT INTO `GameServersHistory` ( + `Id`, `Name`, `ServerId`, `ApiKeyId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Name, OLD.ServerId, OLD.ApiKeyId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_GameServersDelete`; + +CREATE TRIGGER `TR_GameServersDelete` + AFTER DELETE + ON `GameServers` + FOR EACH ROW +BEGIN + INSERT INTO `GameServersHistory` ( + `Id`, `Name`, `ServerId`, `ApiKeyId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Name, OLD.ServerId, OLD.ApiKeyId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/known_users.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/known_users.sql new file mode 100644 index 00000000..5263aa8d --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/known_users.sql @@ -0,0 +1,44 @@ +ALTER TABLE `KnownUsers` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `KnownUsers` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `KnownUsersHistory` +( + `Id` BIGINT(20) NOT NULL, + `DiscordId` BIGINT(20) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_KnownUsersUpdate`; + +CREATE TRIGGER `TR_KnownUsersUpdate` + AFTER UPDATE + ON `KnownUsers` + FOR EACH ROW +BEGIN + INSERT INTO `KnownUsersHistory` ( + `Id`, `DiscordId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.KnownUserId, OLD.DiscordId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_KnownUsersDelete`; + +CREATE TRIGGER `TR_KnownUsersDelete` + AFTER DELETE + ON `KnownUsers` + FOR EACH ROW +BEGIN + INSERT INTO `KnownUsersHistory` ( + `Id`, `DiscordId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.KnownUserId, OLD.DiscordId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/levels.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/levels.sql new file mode 100644 index 00000000..6ba534e2 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/levels.sql @@ -0,0 +1,50 @@ +ALTER TABLE `Levels` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `Levels` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `LevelsHistory` +( + `Id` BIGINT(20) NOT NULL, + `Name` VARCHAR(255) NOT NULL, + `Color` VARCHAR(8) NOT NULL, + `MinXp` BIGINT(20) NOT NULL, + `PermissionInt` BIGINT(20) NOT NULL, + `ServerId` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_LevelsUpdate`; + +CREATE TRIGGER `TR_LevelsUpdate` + AFTER UPDATE + ON `Levels` + FOR EACH ROW +BEGIN + INSERT INTO `LevelsHistory` ( + `Id`, `Name`, `Color`, `MinXp`, `PermissionInt`, `ServerId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Name, OLD.Color, OLD.MinXp, OLD.PermissionInt, OLD.ServerId, OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_LevelsDelete`; + +CREATE TRIGGER `TR_LevelsDelete` + AFTER DELETE + ON `Levels` + FOR EACH ROW +BEGIN + INSERT INTO `LevelsHistory` ( + `Id`, `Name`, `Color`, `MinXp`, `PermissionInt`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Name, OLD.Color, OLD.MinXp, OLD.PermissionInt, OLD.ServerId, TRUE, OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/servers.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/servers.sql new file mode 100644 index 00000000..2d9d6c49 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/servers.sql @@ -0,0 +1,44 @@ +ALTER TABLE `Servers` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `Servers` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `ServersHistory` +( + `Id` BIGINT(20) NOT NULL, + `DiscordId` BIGINT(20) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_ServersUpdate`; + +CREATE TRIGGER `TR_ServersUpdate` + AFTER UPDATE + ON `Servers` + FOR EACH ROW +BEGIN + INSERT INTO `ServersHistory` ( + `Id`, `DiscordId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.ServerId, OLD.DiscordServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_ServersDelete`; + +CREATE TRIGGER `TR_ServersDelete` + AFTER DELETE + ON `Servers` + FOR EACH ROW +BEGIN + INSERT INTO `ServersHistory` ( + `Id`, `DiscordId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.ServerId, OLD.DiscordServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/user_game_idents.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/user_game_idents.sql new file mode 100644 index 00000000..fab7a21b --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/user_game_idents.sql @@ -0,0 +1,46 @@ +ALTER TABLE `UserGameIdents` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `UserGameIdents` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UserGameIdentsHistory` +( + `Id` BIGINT(20) NOT NULL, + `UserId` BIGINT(20) NOT NULL, + `GameServerId` BIGINT(20) NOT NULL, + `Ident` VARCHAR(255) NOT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UserGameIdentsUpdate`; + +CREATE TRIGGER `TR_UserGameIdentsUpdate` + AFTER UPDATE + ON `UserGameIdents` + FOR EACH ROW +BEGIN + INSERT INTO `UserGameIdentsHistory` ( + `Id`, `UserId`, `GameServerId`, `Ident`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.UserId, OLD.GameServerId, OLD.Ident, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UserGameIdentsDelete`; + +CREATE TRIGGER `TR_UserGameIdentsDelete` + AFTER DELETE + ON `UserGameIdents` + FOR EACH ROW +BEGIN + INSERT INTO `UserGameIdentsHistory` ( + `Id`, `UserId`, `GameServerId`, `Ident`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.UserId, OLD.GameServerId, OLD.Ident, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_game_servers.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_game_servers.sql new file mode 100644 index 00000000..203df921 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_game_servers.sql @@ -0,0 +1,47 @@ +ALTER TABLE `UserJoinedGameServer` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `UserJoinedGameServer` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UserJoinedGameServerHistory` +( + `Id` BIGINT(20) NOT NULL, + `UserId` BIGINT(20) NOT NULL, + `GameServerId` BIGINT(20) NOT NULL, + `JoinedOn` DATETIME(6) NOT NULL, + `LeavedOn` DATETIME(6) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UserJoinedGameServerUpdate`; + +CREATE TRIGGER `TR_UserJoinedGameServerUpdate` + AFTER UPDATE + ON `UserJoinedGameServer` + FOR EACH ROW +BEGIN + INSERT INTO `UserJoinedGameServerHistory` ( + `Id`, `UserId`, `GameServerId`, `JoinedOn`, `LeavedOn`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.UserId, OLD.GameServerId, OLD.JoinedOn, OLD.LeavedOn, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UserJoinedGameServerDelete`; + +CREATE TRIGGER `TR_UserJoinedGameServerDelete` + AFTER DELETE + ON `UserJoinedGameServer` + FOR EACH ROW +BEGIN + INSERT INTO `UserJoinedGameServerHistory` ( + `Id`, `UserId`, `GameServerId`, `JoinedOn`, `LeavedOn`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.UserId, OLD.GameServerId, OLD.JoinedOn, OLD.LeavedOn, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_servers.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_servers.sql new file mode 100644 index 00000000..45bc7d1e --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_servers.sql @@ -0,0 +1,46 @@ +ALTER TABLE `UserJoinedServers` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `UserJoinedServers` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UserJoinedServersHistory` +( + `Id` BIGINT(20) NOT NULL, + `UserId` BIGINT(20) NOT NULL, + `JoinedOn` DATETIME(6) NOT NULL, + `LeavedOn` DATETIME(6) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UserJoinedServersUpdate`; + +CREATE TRIGGER `TR_UserJoinedServersUpdate` + AFTER UPDATE + ON `UserJoinedServers` + FOR EACH ROW +BEGIN + INSERT INTO `UserJoinedServersHistory` ( + `Id`, `UserId`, `JoinedOn`, `LeavedOn`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.JoinId, OLD.UserId, OLD.JoinedOn, OLD.LeavedOn, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UserJoinedServersDelete`; + +CREATE TRIGGER `TR_UserJoinedServersDelete` + AFTER DELETE + ON `UserJoinedServers` + FOR EACH ROW +BEGIN + INSERT INTO `UserJoinedServersHistory` ( + `Id`, `UserId`, `JoinedOn`, `LeavedOn`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.JoinId, OLD.UserId, OLD.JoinedOn, OLD.LeavedOn, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_voice_channel.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_voice_channel.sql new file mode 100644 index 00000000..8d439f7b --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/user_joined_voice_channel.sql @@ -0,0 +1,49 @@ +ALTER TABLE `UserJoinedVoiceChannel` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `UserJoinedVoiceChannel` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UserJoinedVoiceChannelHistory` +( + `Id` BIGINT(20) NOT NULL, + `UserId` BIGINT(20) NOT NULL, + `DiscordChannelId` BIGINT(20) NOT NULL, + `JoinedOn` DATETIME(6) NOT NULL, + `LeavedOn` DATETIME(6) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UserJoinedVoiceChannelUpdate`; + +CREATE TRIGGER `TR_UserJoinedVoiceChannelUpdate` + AFTER UPDATE + ON `UserJoinedVoiceChannel` + FOR EACH ROW +BEGIN + INSERT INTO `UserJoinedVoiceChannelHistory` ( + `Id`, `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.JoinId, OLD.UserId, OLD.DiscordChannelId, OLD.JoinedOn, OLD.LeavedOn, OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UserJoinedVoiceChannelDelete`; + +CREATE TRIGGER `TR_UserJoinedVoiceChannelDelete` + AFTER DELETE + ON `UserJoinedVoiceChannel` + FOR EACH ROW +BEGIN + INSERT INTO `UserJoinedVoiceChannelHistory` ( + `Id`, `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.JoinId, OLD.UserId, OLD.DiscordChannelId, OLD.JoinedOn, OLD.LeavedOn, TRUE, OLD.LastModifiedAt, + CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/user_message_count_per_hour.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/user_message_count_per_hour.sql new file mode 100644 index 00000000..a86841b8 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/user_message_count_per_hour.sql @@ -0,0 +1,47 @@ +ALTER TABLE `UserMessageCountPerHour` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `UserMessageCountPerHour` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UserMessageCountPerHourHistory` +( + `Id` BIGINT(20) NOT NULL, + `Date` DATETIME(6) NOT NULL, + `Hour` BIGINT(20) DEFAULT NULL, + `XPCount` BIGINT(20) DEFAULT NULL, + `UserId` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UserMessageCountPerHourUpdate`; + +CREATE TRIGGER `TR_UserMessageCountPerHourUpdate` + AFTER UPDATE + ON `UserMessageCountPerHour` + FOR EACH ROW +BEGIN + INSERT INTO `UserMessageCountPerHourHistory` ( + `Id`, `UserId`, `Date`, `Hour`, `XPCount`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.UserId, OLD.Date, OLD.Hour, OLD.XPCount, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UserMessageCountPerHourDelete`; + +CREATE TRIGGER `TR_UserMessageCountPerHourDelete` + AFTER DELETE + ON `UserMessageCountPerHour` + FOR EACH ROW +BEGIN + INSERT INTO `UserMessageCountPerHourHistory` ( + `Id`, `UserId`, `Date`, `Hour`, `XPCount`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.UserId, OLD.Date, OLD.Hour, OLD.XPCount, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/user_warnings.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/user_warnings.sql new file mode 100644 index 00000000..4371b207 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/user_warnings.sql @@ -0,0 +1,46 @@ +ALTER TABLE `UserWarnings` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `UserWarnings` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UserWarningsHistory` +( + `Id` BIGINT(20) NOT NULL, + `Description` VARCHAR(255) NOT NULL, + `UserId` BIGINT(20) NOT NULL, + `Author` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UserWarningsUpdate`; + +CREATE TRIGGER `TR_UserWarningsUpdate` + AFTER UPDATE + ON `UserWarnings` + FOR EACH ROW +BEGIN + INSERT INTO `UserWarningsHistory` ( + `Id`, `Description`, `UserId`, `Author`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Description, OLD.UserId, OLD.Author, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UserWarningsDelete`; + +CREATE TRIGGER `TR_UserWarningsDelete` + AFTER DELETE + ON `UserWarnings` + FOR EACH ROW +BEGIN + INSERT INTO `UserWarningsHistory` ( + `Id`, `Description`, `UserId`, `Author`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.Id, OLD.Description, OLD.UserId, OLD.Author, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/db_history_scripts/users.sql b/kdb-bot/src/bot_data/migration/db_history_scripts/users.sql new file mode 100644 index 00000000..8dfebf63 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/db_history_scripts/users.sql @@ -0,0 +1,46 @@ +ALTER TABLE `Users` + CHANGE `CreatedAt` `CreatedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6); + +ALTER TABLE `Users` + CHANGE `LastModifiedAt` `LastModifiedAt` DATETIME(6) NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); + +CREATE TABLE IF NOT EXISTS `UsersHistory` +( + `Id` BIGINT(20) NOT NULL, + `DiscordId` BIGINT(20) NOT NULL, + `XP` BIGINT(20) NOT NULL DEFAULT 0, + `ServerId` BIGINT(20) DEFAULT NULL, + `Deleted` BOOL DEFAULT FALSE, + `DateFrom` DATETIME(6) NOT NULL, + `DateTo` DATETIME(6) NOT NULL +); + +DROP TRIGGER IF EXISTS `TR_UsersUpdate`; + +CREATE TRIGGER `TR_UsersUpdate` + AFTER UPDATE + ON `Users` + FOR EACH ROW +BEGIN + INSERT INTO `UsersHistory` ( + `Id`, `DiscordId`, `XP`, `ServerId`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.UserId, OLD.DiscordId, OLD.XP, OLD.ServerId, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; + +DROP TRIGGER IF EXISTS `TR_UsersDelete`; + +CREATE TRIGGER `TR_UsersDelete` + AFTER DELETE + ON `Users` + FOR EACH ROW +BEGIN + INSERT INTO `UsersHistory` ( + `Id`, `DiscordId`, `XP`, `ServerId`, `Deleted`, `DateFrom`, `DateTo` + ) + VALUES ( + OLD.UserId, OLD.DiscordId, OLD.XP, OLD.ServerId, TRUE, OLD.LastModifiedAt, CURRENT_TIMESTAMP(6) + ); +END; \ No newline at end of file diff --git a/kdb-bot/src/bot_data/migration/remove_stats_migration.py b/kdb-bot/src/bot_data/migration/remove_stats_migration.py new file mode 100644 index 00000000..e5e621a5 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/remove_stats_migration.py @@ -0,0 +1,43 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class RemoveStatsMigration(MigrationABC): + name = "1.0.0_RemoveStatsMigration" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._cursor.execute( + str( + f""" + DROP TABLE IF EXISTS `Statistics`; + """ + ) + ) + + def downgrade(self): + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `Statistics` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `Name` VARCHAR(255) NOT NULL, + `Description` VARCHAR(255) NOT NULL, + `Code` LONGTEXT NOT NULL, + `ServerId` BIGINT, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`Id`), + FOREIGN KEY (`ServerId`) REFERENCES `Servers`(`ServerId`) + ); + """ + ) + ) diff --git a/kdb-bot/src/bot_data/migration/user_joined_game_server_migration.py b/kdb-bot/src/bot_data/migration/user_joined_game_server_migration.py new file mode 100644 index 00000000..bef8e5aa --- /dev/null +++ b/kdb-bot/src/bot_data/migration/user_joined_game_server_migration.py @@ -0,0 +1,77 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class UserJoinedGameServerMigration(MigrationABC): + name = "1.0.0_UserJoinedGameServerMigration" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `GameServers` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `Name` VARCHAR(255) NOT NULL, + `ServerId` BIGINT NOT NULL, + `ApiKeyId` BIGINT NOT NULL, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + FOREIGN KEY (`ServerId`) REFERENCES Servers(`ServerId`), + FOREIGN KEY (`ApiKeyId`) REFERENCES ApiKeys(`Id`), + PRIMARY KEY(`Id`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `UserJoinedGameServer` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `UserId` BIGINT NOT NULL, + `GameServerId` BIGINT NOT NULL, + `JoinedOn` DATETIME(6) NOT NULL, + `LeavedOn` DATETIME(6), + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), + FOREIGN KEY (`GameServerId`) REFERENCES GameServers(`Id`), + PRIMARY KEY(`Id`) + ); + """ + ) + ) + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `UserGameIdents` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `UserId` BIGINT NOT NULL, + `GameServerId` BIGINT NOT NULL, + `Ident` VARCHAR(255) NOT NULL, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + FOREIGN KEY (`UserId`) REFERENCES Users(`UserId`), + FOREIGN KEY (`GameServerId`) REFERENCES GameServers(`Id`), + CONSTRAINT UC_UserGameIdent UNIQUE (`GameServerId`,`Ident`), + PRIMARY KEY(`Id`) + ); + """ + ) + ) + + def downgrade(self): + self._cursor.execute("DROP TABLE `GameServers`;") + self._cursor.execute("DROP TABLE `UserJoinedGameServer`;") + self._cursor.execute("DROP TABLE `UserGameIdents`;") diff --git a/kdb-bot/src/bot_data/migration/user_warning_migration.py b/kdb-bot/src/bot_data/migration/user_warning_migration.py new file mode 100644 index 00000000..06e446a0 --- /dev/null +++ b/kdb-bot/src/bot_data/migration/user_warning_migration.py @@ -0,0 +1,37 @@ +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.migration_abc import MigrationABC +from bot_data.db_context import DBContext + + +class UserWarningMigration(MigrationABC): + name = "1.0.0_UserWarningMigration" + + def __init__(self, logger: DatabaseLogger, db: DBContext): + MigrationABC.__init__(self) + self._logger = logger + self._db = db + self._cursor = db.cursor + + def upgrade(self): + self._logger.debug(__name__, "Running upgrade") + + self._cursor.execute( + str( + f""" + CREATE TABLE IF NOT EXISTS `UserWarnings` ( + `Id` BIGINT NOT NULL AUTO_INCREMENT, + `Description` VARCHAR(255) NOT NULL, + `UserId` BIGINT NOT NULL, + `Author` BIGINT NULL, + `CreatedAt` DATETIME(6), + `LastModifiedAt` DATETIME(6), + PRIMARY KEY(`Id`), + FOREIGN KEY (`UserId`) REFERENCES `Users`(`UserId`), + FOREIGN KEY (`Author`) REFERENCES `Users`(`UserId`) + ); + """ + ) + ) + + def downgrade(self): + self._cursor.execute("DROP TABLE `UserWarnings`;") diff --git a/kdb-bot/src/bot_data/model/__init__.py b/kdb-bot/src/bot_data/model/__init__.py index 6172522e..eddb94fa 100644 --- a/kdb-bot/src/bot_data/model/__init__.py +++ b/kdb-bot/src/bot_data/model/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_data.model" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_data/model/api_key.py b/kdb-bot/src/bot_data/model/api_key.py new file mode 100644 index 00000000..d63c4d1b --- /dev/null +++ b/kdb-bot/src/bot_data/model/api_key.py @@ -0,0 +1,113 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + +from bot_data.model.user import User + + +class ApiKey(TableABC): + def __init__( + self, + identifier: str, + key: str, + creator: Optional[User], + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._identifier = identifier + self._key = key + self._creator = creator + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def identifier(self) -> str: + return self._identifier + + @property + def key(self) -> str: + return self._key + + @property + def creator(self) -> Optional[User]: + return self._creator + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `ApiKeys`; + """ + ) + + @staticmethod + def get_select_string(identifier: str, key: str) -> str: + return str( + f""" + SELECT * FROM `ApiKeys` + WHERE `Identifier` = '{identifier}' + AND `Key` = '{key}'; + """ + ) + + @staticmethod + def get_select_by_id(id: int) -> str: + return str( + f""" + SELECT * FROM `ApiKeys` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_key(key: str) -> str: + return str( + f""" + SELECT * FROM `ApiKeys` + WHERE `Key` = '{key}'; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `ApiKeys` ( + `Identifier`, `Key`, `CreatorId` + ) VALUES ( + '{self._identifier}', + '{self._key}', + {"NULL" if self._creator is None else f"'{self._creator.id}'"} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `ApiKeys` + SET `Identifier` = '{self._identifier}', + `Key` = '{self._key}', + `CreatorId` = {"NULL" if self._creator is None else f"'{self._creator.id}'"} + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `ApiKeys` + WHERE `Id` = {self._id}; + """ + ) diff --git a/kdb-bot/src/bot_data/model/auth_role_enum.py b/kdb-bot/src/bot_data/model/auth_role_enum.py index e1526136..8b93629b 100644 --- a/kdb-bot/src/bot_data/model/auth_role_enum.py +++ b/kdb-bot/src/bot_data/model/auth_role_enum.py @@ -2,6 +2,5 @@ from enum import Enum class AuthRoleEnum(Enum): - normal = 0 admin = 1 diff --git a/kdb-bot/src/bot_data/model/auth_user.py b/kdb-bot/src/bot_data/model/auth_user.py index 7a91373d..47bdf41a 100644 --- a/kdb-bot/src/bot_data/model/auth_user.py +++ b/kdb-bot/src/bot_data/model/auth_user.py @@ -1,11 +1,11 @@ import uuid from datetime import datetime from typing import Optional + from cpl_core.database import TableABC from cpl_query.extension import List from bot_data.model.auth_role_enum import AuthRoleEnum -from bot_data.model.server import Server from bot_data.model.user import User @@ -42,6 +42,8 @@ class AuthUser(TableABC): if users is None: self._users = List(User) + else: + self._users = users self._auth_role_id = auth_role @@ -218,25 +220,21 @@ class AuthUser(TableABC): `ForgotPasswordId`, `OAuthId`, `RefreshTokenExpiryTime`, - `AuthRole`, - `CreatedAt`, - `LastModifiedAt` - ) VALUES ( - {self._auth_user_id}, - '{self._first_name}', - '{self._last_name}', - '{self._email}', - '{self._password}', - '{self._password_salt}', - '{"NULL" if self._refresh_token is None else self._refresh_token}', - '{"NULL" if self._confirmation_id is None else self._confirmation_id}', - '{"NULL" if self._forgot_password_id is None else self._forgot_password_id}', - '{"NULL" if self._oauth_id is None else self._oauth_id}', - '{self._refresh_token_expire_time.isoformat()}', - {self._auth_role_id.value}, - '{self._created_at}', - '{self._modified_at}' - ) + `AuthRole` + ) VALUES ( + {self._auth_user_id}, + '{self._first_name}', + '{self._last_name}', + '{self._email}', + '{self._password}', + '{self._password_salt}', + {"NULL" if self._refresh_token is None else f"'{self._refresh_token}'"}, + {"NULL" if self._confirmation_id is None else f"'{self._confirmation_id}'"}, + {"NULL" if self._forgot_password_id is None else f"'{self._forgot_password_id}'"}, + {"NULL" if self._oauth_id is None else f"'{self._oauth_id}'"}, + '{self._refresh_token_expire_time.isoformat()}', + {self._auth_role_id.value} + ) """ ) @@ -250,13 +248,12 @@ class AuthUser(TableABC): `EMail` = '{self._email}', `Password` = '{self._password}', `PasswordSalt` = '{self._password_salt}', - `RefreshToken` = '{"NULL" if self._refresh_token is None else self._refresh_token}', - `ConfirmationId` = '{"NULL" if self._confirmation_id is None else self._confirmation_id}', - `ForgotPasswordId` = '{"NULL" if self._forgot_password_id is None else self._forgot_password_id}', - `OAuthId` = '{"NULL" if self._oauth_id is None else self._oauth_id}', + `RefreshToken` = {"NULL" if self._refresh_token is None else f"'{self._refresh_token}'"}, + `ConfirmationId` = {"NULL" if self._confirmation_id is None else f"'{self._confirmation_id}'"}, + `ForgotPasswordId` = {"NULL" if self._forgot_password_id is None else f"'{self._forgot_password_id}'"}, + `OAuthId` = {"NULL" if self._oauth_id is None else f"'{self._oauth_id}'"}, `RefreshTokenExpiryTime` = '{self._refresh_token_expire_time.isoformat()}', - `AuthRole` = {self._auth_role_id.value}, - `LastModifiedAt` = '{self._modified_at}' + `AuthRole` = {self._auth_role_id.value} WHERE `AuthUsers`.`Id` = {self._auth_user_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/auth_user_users_relation.py b/kdb-bot/src/bot_data/model/auth_user_users_relation.py index 1ef7e35d..23b9ceab 100644 --- a/kdb-bot/src/bot_data/model/auth_user_users_relation.py +++ b/kdb-bot/src/bot_data/model/auth_user_users_relation.py @@ -68,12 +68,10 @@ class AuthUserUsersRelation(TableABC): return str( f""" INSERT INTO `AuthUserUsersRelations` ( - `AuthUserId`, `UserId`, `CreatedAt`, `LastModifiedAt` + `AuthUserId`, `UserId` ) VALUES ( {self._auth_user.id}, - {self._user.user_id}, - '{self._created_at}', - '{self._modified_at}' + {self._user.id} ); """ ) @@ -83,11 +81,10 @@ class AuthUserUsersRelation(TableABC): return str( f""" UPDATE `AuthUserUsersRelations` - SET `AuthUserId` = '{self._auth_user.id}',, - `UserId` = '{self._user.user_id}' - `LastModifiedAt` = '{self._modified_at}' + SET `AuthUserId` = '{self._auth_user.id}', + `UserId` = '{self._user.id}' WHERE `AuthUserId` = {self._auth_user.id} - AND `UserId` = {self._user.user_id}; + AND `UserId` = {self._user.id}; """ ) @@ -97,6 +94,6 @@ class AuthUserUsersRelation(TableABC): f""" DELETE FROM `AuthUserUsersRelations` WHERE `AuthUserId` = {self._auth_user.id} - AND `UserId` = {self._user.user_id}; + AND `UserId` = {self._user.id}; """ ) diff --git a/kdb-bot/src/bot_data/model/auto_role.py b/kdb-bot/src/bot_data/model/auto_role.py index dfef0155..a1ff7934 100644 --- a/kdb-bot/src/bot_data/model/auto_role.py +++ b/kdb-bot/src/bot_data/model/auto_role.py @@ -2,21 +2,25 @@ from datetime import datetime from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.server import Server class AutoRole(TableABC): def __init__( self, - server_id: int, - dc_channel_id: int, + server: Optional[Server], + channel_id: int, dc_message_id: int, created_at: datetime = None, modified_at: datetime = None, id=0, ): self._auto_role_id = id - self._server_id = server_id - self._discord_channel_id = dc_channel_id + self._server = server + self._discord_channel_id = channel_id self._discord_message_id = dc_message_id TableABC.__init__(self) @@ -24,21 +28,35 @@ class AutoRole(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def auto_role_id(self) -> int: + def id(self) -> int: return self._auto_role_id @property - def server_id(self) -> int: - return self._server_id + def server(self) -> Server: + return self._server @property def discord_channel_id(self) -> int: return self._discord_channel_id + @discord_channel_id.setter + def discord_channel_id(self, value: int): + self._discord_channel_id = value + + @property + @ServiceProviderABC.inject + def discord_channel_name(self, bot: DiscordBotServiceABC) -> str: + channel = bot.get_channel(self.discord_channel_id) + return None if channel is None else channel.name + @property def discord_message_id(self) -> int: return self._discord_message_id + @discord_message_id.setter + def discord_message_id(self, value: int): + self._discord_message_id = value + @staticmethod def get_select_all_string() -> str: return str( @@ -79,13 +97,11 @@ class AutoRole(TableABC): return str( f""" INSERT INTO `AutoRoles` ( - `ServerId`, `DiscordChannelId`, `DiscordMessageId`, `CreatedAt`, `LastModifiedAt` + `ServerId`, `DiscordChannelId`, `DiscordMessageId` ) VALUES ( - {self._server_id}, + {self._server.id}, {self._discord_channel_id}, - {self._discord_message_id}, - '{self._created_at}', - '{self._modified_at}' + {self._discord_message_id} ); """ ) @@ -95,10 +111,9 @@ class AutoRole(TableABC): return str( f""" UPDATE `AutoRoles` - SET `ServerId` = {self._server_id}, + SET `ServerId` = {self._server.id}, `DiscordChannelId` = {self._discord_channel_id}, - `DiscordMessageId` = {self._discord_message_id}, - `LastModifiedAt` = '{self._modified_at}' + `DiscordMessageId` = {self._discord_message_id} WHERE `AutoRoleId` = {self._auto_role_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/auto_role_history.py b/kdb-bot/src/bot_data/model/auto_role_history.py new file mode 100644 index 00000000..0c9d7c5c --- /dev/null +++ b/kdb-bot/src/bot_data/model/auto_role_history.py @@ -0,0 +1,49 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class AutoRoleHistory(HistoryTableABC): + def __init__( + self, + server: int, + channel_id: int, + dc_message_id: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._auto_role_id = id + self._server = server + self._discord_channel_id = channel_id + self._discord_message_id = dc_message_id + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._auto_role_id + + @property + def server(self) -> int: + return self._server + + @property + def discord_channel_id(self) -> int: + return self._discord_channel_id + + @property + @ServiceProviderABC.inject + def discord_channel_name(self, bot: DiscordBotServiceABC) -> str: + channel = bot.get_channel(self.discord_channel_id) + return None if channel is None else channel.name + + @property + def discord_message_id(self) -> int: + return self._discord_message_id diff --git a/kdb-bot/src/bot_data/model/auto_role_rule.py b/kdb-bot/src/bot_data/model/auto_role_rule.py index 01d45ebe..8729b6ec 100644 --- a/kdb-bot/src/bot_data/model/auto_role_rule.py +++ b/kdb-bot/src/bot_data/model/auto_role_rule.py @@ -1,13 +1,16 @@ from datetime import datetime -from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.auto_role import AutoRole class AutoRoleRule(TableABC): def __init__( self, - auto_role_id: int, + auto_role: AutoRole, discord_emoji_name: str, discord_role_id: int, created_at: datetime = None, @@ -15,7 +18,7 @@ class AutoRoleRule(TableABC): id=0, ): self._auto_role_rule_id = id - self._auto_role_id = auto_role_id + self._auto_role = auto_role self._discord_emoji_name = discord_emoji_name self._discord_role_id = discord_role_id @@ -24,21 +27,35 @@ class AutoRoleRule(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def auto_role_rule_id(self) -> int: + def id(self) -> int: return self._auto_role_rule_id @property - def auto_role_id(self) -> int: - return self._auto_role_id + def auto_role(self) -> AutoRole: + return self._auto_role @property def emoji_name(self) -> str: return self._discord_emoji_name + @emoji_name.setter + def emoji_name(self, value: str): + self._discord_emoji_name = value + @property def role_id(self) -> int: return self._discord_role_id + @property + @ServiceProviderABC.inject + def role_name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.auto_role.server.discord_id) + return guild.get_role(self.role_id).name + + @role_id.setter + def role_id(self, value: int): + self._discord_role_id = value + @staticmethod def get_select_all_string() -> str: return str( @@ -70,13 +87,11 @@ class AutoRoleRule(TableABC): return str( f""" INSERT INTO `AutoRoleRules` ( - `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId`, `CreatedAt`, `LastModifiedAt` + `AutoRoleId`, `DiscordEmojiName`, `DiscordRoleId` ) VALUES ( - {self._auto_role_id}, + {self._auto_role.id}, '{self._discord_emoji_name}', - {self._discord_role_id}, - '{self._created_at}', - '{self._modified_at}' + {self._discord_role_id} ); """ ) @@ -86,10 +101,9 @@ class AutoRoleRule(TableABC): return str( f""" UPDATE `AutoRoleRules` - SET `AutoRoleId` = {self._auto_role_id}, - `DiscordEmojiName` = {self._discord_emoji_name}, - `DiscordRoleId` = {self._discord_role_id}, - `LastModifiedAt` = '{self._modified_at}' + SET `AutoRoleId` = {self._auto_role.id}, + `DiscordEmojiName` = '{self._discord_emoji_name}', + `DiscordRoleId` = {self._discord_role_id} WHERE `AutoRoleRuleId` = {self._auto_role_rule_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/auto_role_rule_history.py b/kdb-bot/src/bot_data/model/auto_role_rule_history.py new file mode 100644 index 00000000..c5a5ccd9 --- /dev/null +++ b/kdb-bot/src/bot_data/model/auto_role_rule_history.py @@ -0,0 +1,48 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class AutoRoleRuleHistory(HistoryTableABC): + def __init__( + self, + auto_role: int, + discord_emoji_name: str, + discord_role_id: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + self._auto_role_rule_id = id + self._auto_role = auto_role + self._discord_emoji_name = discord_emoji_name + self._discord_role_id = discord_role_id + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._auto_role_rule_id + + @property + def auto_role(self) -> int: + return self._auto_role + + @property + def emoji_name(self) -> str: + return self._discord_emoji_name + + @property + def role_id(self) -> int: + return self._discord_role_id + + @property + @ServiceProviderABC.inject + def role_name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.auto_role.server.discord_id) + return guild.get_role(self.role_id).name diff --git a/kdb-bot/src/bot_data/model/client.py b/kdb-bot/src/bot_data/model/client.py index db98caaf..b6c163c9 100644 --- a/kdb-bot/src/bot_data/model/client.py +++ b/kdb-bot/src/bot_data/model/client.py @@ -1,5 +1,8 @@ from datetime import datetime + from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from bot_data.model.server import Server @@ -32,20 +35,24 @@ class Client(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def client_id(self) -> int: + def id(self) -> int: return self._client_id @property def discord_id(self) -> int: return self._discord_client_id + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + return bot.user.name + @property def sent_message_count(self) -> int: return self._sent_message_count @sent_message_count.setter def sent_message_count(self, value: int): - self._modified_at = datetime.now().isoformat() self._sent_message_count = value @property @@ -54,7 +61,6 @@ class Client(TableABC): @received_message_count.setter def received_message_count(self, value: int): - self._modified_at = datetime.now().isoformat() self._received_message_count = value @property @@ -63,7 +69,6 @@ class Client(TableABC): @deleted_message_count.setter def deleted_message_count(self, value: int): - self._modified_at = datetime.now().isoformat() self._deleted_message_count = value @property @@ -72,7 +77,6 @@ class Client(TableABC): @received_command_count.setter def received_command_count(self, value: int): - self._modified_at = datetime.now().isoformat() self._received_command_count = value @property @@ -81,7 +85,6 @@ class Client(TableABC): @moved_users_count.setter def moved_users_count(self, value: int): - self._modified_at = datetime.now().isoformat() self._moved_users_count = value @property @@ -144,9 +147,7 @@ class Client(TableABC): `DeletedMessageCount`, `ReceivedCommandsCount`, `MovedUsersCount`, - `ServerId`, - `CreatedAt`, - `LastModifiedAt` + `ServerId` ) VALUES ( {self._discord_client_id}, {self._sent_message_count}, @@ -154,9 +155,7 @@ class Client(TableABC): {self._deleted_message_count}, {self._received_message_count}, {self._moved_users_count}, - {self._server.server_id}, - '{self._created_at}', - '{self._modified_at}' + {self._server.id} ); """ ) @@ -170,8 +169,7 @@ class Client(TableABC): `ReceivedMessageCount` = {self._received_message_count}, `DeletedMessageCount` = {self._deleted_message_count}, `ReceivedCommandsCount` = {self._received_command_count}, - `MovedUsersCount` = {self._moved_users_count}, - `LastModifiedAt` = '{self._modified_at}' + `MovedUsersCount` = {self._moved_users_count} WHERE `ClientId` = {self._client_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/client_history.py b/kdb-bot/src/bot_data/model/client_history.py new file mode 100644 index 00000000..c16a306b --- /dev/null +++ b/kdb-bot/src/bot_data/model/client_history.py @@ -0,0 +1,72 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class ClientHistory(HistoryTableABC): + def __init__( + self, + dc_id: int, + smc: int, + rmc: int, + dmc: int, + rcc: int, + muc: int, + server: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._client_id = id + self._discord_client_id = dc_id + self._sent_message_count = smc + self._received_message_count = rmc + self._deleted_message_count = dmc + self._received_command_count = rcc + self._moved_users_count = muc + self._server = server + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._client_id + + @property + def discord_id(self) -> int: + return self._discord_client_id + + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + return bot.user.name + + @property + def sent_message_count(self) -> int: + return self._sent_message_count + + @property + def received_message_count(self) -> int: + return self._received_message_count + + @property + def deleted_message_count(self) -> int: + return self._deleted_message_count + + @property + def received_command_count(self) -> int: + return self._received_command_count + + @property + def moved_users_count(self) -> int: + return self._moved_users_count + + @property + def server(self) -> int: + return self._server diff --git a/kdb-bot/src/bot_data/model/statistic.py b/kdb-bot/src/bot_data/model/game_server.py similarity index 52% rename from kdb-bot/src/bot_data/model/statistic.py rename to kdb-bot/src/bot_data/model/game_server.py index 0b4476a2..eeea20d8 100644 --- a/kdb-bot/src/bot_data/model/statistic.py +++ b/kdb-bot/src/bot_data/model/game_server.py @@ -1,27 +1,25 @@ from datetime import datetime from cpl_core.database import TableABC -from cpl_core.utils import CredentialManager +from bot_data.model.api_key import ApiKey from bot_data.model.server import Server -class Statistic(TableABC): +class GameServer(TableABC): def __init__( self, name: str, - description: str, - code: str, server: Server, + api_key: ApiKey, created_at: datetime = None, modified_at: datetime = None, id=0, ): self._id = id self._name = name - self._description = description - self._code = CredentialManager.encrypt(code) self._server = server + self._api_key = api_key TableABC.__init__(self) self._created_at = created_at if created_at is not None else self._created_at @@ -35,31 +33,31 @@ class Statistic(TableABC): def name(self) -> str: return self._name - @property - def description(self) -> str: - return self._description - - @description.setter - def description(self, value: str): - self._description = value - - @property - def code(self) -> str: - return CredentialManager.decrypt(self._code) - - @code.setter - def code(self, value: str): - self._code = CredentialManager.encrypt(value) + @name.setter + def name(self, value: str): + self._name = value @property def server(self) -> Server: return self._server + @server.setter + def server(self, value: Server): + self._server = value + + @property + def api_key(self) -> ApiKey: + return self._api_key + + @api_key.setter + def api_key(self, value: ApiKey): + self._api_key = value + @staticmethod def get_select_all_string() -> str: return str( f""" - SELECT * FROM `Statistics`; + SELECT * FROM `GameServers`; """ ) @@ -67,27 +65,35 @@ class Statistic(TableABC): def get_select_by_id_string(id: int) -> str: return str( f""" - SELECT * FROM `Statistics` + SELECT * FROM `GameServers` WHERE `Id` = {id}; """ ) @staticmethod - def get_select_by_name_string(name: str, s_id: int) -> str: + def get_select_by_api_key_id_string(id: int) -> str: return str( f""" - SELECT * FROM `Statistics` - WHERE `ServerId` = {s_id} - AND `Name` = '{name}'; + SELECT * FROM `GameServers` + WHERE `ApiKeyId` = {id}; """ ) @staticmethod - def get_select_by_server_string(s_id: int) -> str: + def get_select_by_server_id_string(id: int) -> str: return str( f""" - SELECT * FROM `Statistics` - WHERE `ServerId` = {s_id}; + SELECT * FROM `GameServers` + WHERE `ServerId` = {id}; + """ + ) + + @staticmethod + def get_select_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `GameServers` + WHERE `UserId` = {id}; """ ) @@ -95,15 +101,12 @@ class Statistic(TableABC): def insert_string(self) -> str: return str( f""" - INSERT INTO `Statistics` ( - `Name`, `Description`, `Code`, `ServerId`, `CreatedAt`, `LastModifiedAt` + INSERT INTO `GameServers` ( + `Name`, `ServerId`, `ApiKeyId` ) VALUES ( '{self._name}', - '{self._description}', - '{self._code}', - {self._server.server_id}, - '{self._created_at}', - '{self._modified_at}' + {self._server.id}, + {self._api_key.id} ); """ ) @@ -112,11 +115,8 @@ class Statistic(TableABC): def udpate_string(self) -> str: return str( f""" - UPDATE `Statistics` - SET `Name` = '{self._name}', - `Description` = '{self._description}', - `Code` = '{self._code}', - `LastModifiedAt` = '{self._modified_at}' + UPDATE `GameServers` + SET `Name` = '{self._name}' WHERE `Id` = {self._id}; """ ) @@ -125,7 +125,16 @@ class Statistic(TableABC): def delete_string(self) -> str: return str( f""" - DELETE FROM `Statistics` + DELETE FROM `GameServers` WHERE `Id` = {self._id}; """ ) + + @staticmethod + def delete_by_user_id_string(id: int) -> str: + return str( + f""" + DELETE FROM `GameServers` + WHERE `UserId` = {id} + """ + ) diff --git a/kdb-bot/src/bot_data/model/known_user.py b/kdb-bot/src/bot_data/model/known_user.py index be64d9d5..37d375f0 100644 --- a/kdb-bot/src/bot_data/model/known_user.py +++ b/kdb-bot/src/bot_data/model/known_user.py @@ -1,8 +1,6 @@ from datetime import datetime -from typing import Optional -from cpl_core.database import TableABC -from bot_data.model.server import Server +from cpl_core.database import TableABC class KnownUser(TableABC): @@ -21,7 +19,7 @@ class KnownUser(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def known_user_id(self) -> int: + def id(self) -> int: return self._known_user_id @property @@ -59,11 +57,9 @@ class KnownUser(TableABC): return str( f""" INSERT INTO `KnownUsers` ( - `DiscordId`, `CreatedAt`, `LastModifiedAt` + `DiscordId` ) VALUES ( - {self._discord_id}, - '{self._created_at}', - '{self._modified_at}' + {self._discord_id} ); """ ) diff --git a/kdb-bot/src/bot_data/model/known_user_history.py b/kdb-bot/src/bot_data/model/known_user_history.py new file mode 100644 index 00000000..35ced7dc --- /dev/null +++ b/kdb-bot/src/bot_data/model/known_user_history.py @@ -0,0 +1,28 @@ +from bot_data.abc.history_table_abc import HistoryTableABC + + +class KnownUserHistory(HistoryTableABC): + def __init__( + self, + dc_id: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._known_user_id = id + self._discord_id = dc_id + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._known_user_id + + @property + def discord_id(self) -> int: + return self._discord_id diff --git a/kdb-bot/src/bot_data/model/level.py b/kdb-bot/src/bot_data/model/level.py index fbea3634..a20d268b 100644 --- a/kdb-bot/src/bot_data/model/level.py +++ b/kdb-bot/src/bot_data/model/level.py @@ -1,5 +1,6 @@ from datetime import datetime from typing import Optional + from cpl_core.database import TableABC from bot_data.model.server import Server @@ -38,7 +39,6 @@ class Level(TableABC): @name.setter def name(self, value: str): - self._modified_at = datetime.now().isoformat() self._name = value @property @@ -47,7 +47,6 @@ class Level(TableABC): @color.setter def color(self, value: str): - self._modified_at = datetime.now().isoformat() self._color = value @property @@ -56,7 +55,6 @@ class Level(TableABC): @min_xp.setter def min_xp(self, value: int): - self._modified_at = datetime.now().isoformat() self._min_xp = value @property @@ -65,7 +63,6 @@ class Level(TableABC): @permissions.setter def permissions(self, value: int): - self._modified_at = datetime.now().isoformat() self._permissions = value @property @@ -74,7 +71,6 @@ class Level(TableABC): @server.setter def server(self, value: Server): - self._modified_at = datetime.now().isoformat() self._server = value @staticmethod @@ -108,15 +104,13 @@ class Level(TableABC): return str( f""" INSERT INTO `Levels` ( - `Name`, `Color`, `MinXp`, `PermissionInt`, `ServerId`, `CreatedAt`, `LastModifiedAt` + `Name`, `Color`, `MinXp`, `PermissionInt`, `ServerId` ) VALUES ( '{self._name}', '{self._color}', {self._min_xp}, {self._permissions}, - {self._server.server_id}, - '{self._created_at}', - '{self._modified_at}' + {self._server.id} ); """ ) @@ -129,8 +123,7 @@ class Level(TableABC): SET `Name` = '{self._name}', `Color` = '{self._color}', `MinXp` = {self._min_xp}, - `PermissionInt` = {self._permissions}, - `LastModifiedAt` = '{self._modified_at}' + `PermissionInt` = {self._permissions} WHERE `Id` = {self._id}; """ ) diff --git a/kdb-bot/src/bot_data/model/level_history.py b/kdb-bot/src/bot_data/model/level_history.py new file mode 100644 index 00000000..748acaf7 --- /dev/null +++ b/kdb-bot/src/bot_data/model/level_history.py @@ -0,0 +1,55 @@ +from typing import Optional + +from bot_data.abc.history_table_abc import HistoryTableABC +from bot_data.model.server import Server + + +class LevelHistory(HistoryTableABC): + def __init__( + self, + name: str, + color: str, + min_xp: int, + permissions: int, + server: Optional[Server], + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._name = name + self._color = color + self._min_xp = min_xp + self._permissions = permissions + self._server = server + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._id + + @property + def name(self) -> str: + return self._name + + @property + def color(self) -> str: + return self._color + + @property + def min_xp(self) -> int: + return self._min_xp + + @property + def permissions(self) -> int: + return self._permissions + + @property + def server(self) -> Server: + return self._server diff --git a/kdb-bot/src/bot_data/model/server.py b/kdb-bot/src/bot_data/model/server.py index 4f22ec1c..d86c6e97 100644 --- a/kdb-bot/src/bot_data/model/server.py +++ b/kdb-bot/src/bot_data/model/server.py @@ -1,7 +1,8 @@ from datetime import datetime -from typing import Optional from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC class Server(TableABC): @@ -20,13 +21,25 @@ class Server(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def server_id(self) -> int: + def id(self) -> int: return self._server_id @property - def discord_server_id(self) -> int: + def discord_id(self) -> int: return self._discord_server_id + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.discord_id) + return None if guild is None else guild.name + + @property + @ServiceProviderABC.inject + def icon_url(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.discord_id) + return None if guild is None else guild.icon.url + @staticmethod def get_select_all_string() -> str: return str( @@ -58,11 +71,9 @@ class Server(TableABC): return str( f""" INSERT INTO `Servers` ( - `DiscordServerId`, `CreatedAt`, `LastModifiedAt` + `DiscordServerId` ) VALUES ( - {self._discord_server_id}, - '{self._created_at}', - '{self._modified_at}' + {self._discord_server_id} ); """ ) @@ -72,8 +83,7 @@ class Server(TableABC): return str( f""" UPDATE `Servers` - SET `DiscordServerId` = {self._discord_server_id}, - `LastModifiedAt` = '{self._modified_at}' + SET `DiscordServerId` = {self._discord_server_id} WHERE `ServerId` = {self._server_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/server_history.py b/kdb-bot/src/bot_data/model/server_history.py new file mode 100644 index 00000000..e8c95934 --- /dev/null +++ b/kdb-bot/src/bot_data/model/server_history.py @@ -0,0 +1,43 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class ServerHistory(HistoryTableABC): + def __init__( + self, + dc_id: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._server_id = id + self._discord_server_id = dc_id + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._server_id + + @property + def discord_id(self) -> int: + return self._discord_server_id + + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.discord_id) + return None if guild is None else guild.name + + @property + @ServiceProviderABC.inject + def icon_url(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.discord_id) + return None if guild is None else guild.icon.url diff --git a/kdb-bot/src/bot_data/model/user.py b/kdb-bot/src/bot_data/model/user.py index 1592e471..7472e689 100644 --- a/kdb-bot/src/bot_data/model/user.py +++ b/kdb-bot/src/bot_data/model/user.py @@ -1,7 +1,12 @@ from datetime import datetime from typing import Optional -from cpl_core.database import TableABC +from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.level import Level from bot_data.model.server import Server @@ -25,26 +30,77 @@ class User(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def user_id(self) -> int: + def id(self) -> int: return self._user_id @property def discord_id(self) -> int: return self._discord_id + @property + @ServiceProviderABC.inject + def name(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.server.discord_id) + user = guild.get_member(self.discord_id) + return None if user is None else user.name + + @property + @ServiceProviderABC.inject + def icon_url(self, bot: DiscordBotServiceABC) -> str: + guild = bot.get_guild(self.server.discord_id) + user = guild.get_member(self.discord_id) + return None if user is None else user.display_icon + @property def xp(self) -> int: return self._xp @xp.setter def xp(self, value: int): - self._modified_at = datetime.now().isoformat() self._xp = value + @property + @ServiceProviderABC.inject + def ontime(self, services: ServiceProviderABC) -> float: + from bot_core.abc.client_utils_abc import ClientUtilsABC + + client_utils: ClientUtilsABC = services.get_service(ClientUtilsABC) + return client_utils.get_ontime_for_user(self) + + @property + @ServiceProviderABC.inject + def level(self, services: ServiceProviderABC) -> Level: + from modules.level.service.level_service import LevelService + + levels: LevelService = services.get_service(LevelService) + return levels.get_level(self) + @property def server(self) -> Optional[Server]: return self._server + @property + @ServiceProviderABC.inject + def left_server( + self, + services: ServiceProviderABC, + ) -> bool: + from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC + + ujs: UserJoinedServerRepositoryABC = services.get_service(UserJoinedServerRepositoryABC) + return ujs.find_active_user_joined_server_by_user_id(self.id) is None + + @property + @ServiceProviderABC.inject + def game_idents( + self, + services: ServiceProviderABC, + ) -> List["UserGameIdent"]: + from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC + + game_idents_repo: UserGameIdentRepositoryABC = services.get_service(UserGameIdentRepositoryABC) + return game_idents_repo.get_user_game_idents_by_user_id(self.id) + @staticmethod def get_select_all_string() -> str: return str( @@ -62,6 +118,15 @@ class User(TableABC): """ ) + @staticmethod + def get_select_by_server_id_string(server_id: int) -> str: + return str( + f""" + SELECT * FROM `Users` + WHERE `ServerId` = {server_id}; + """ + ) + @staticmethod def get_select_by_discord_id_string(id: int) -> str: return str( @@ -86,13 +151,11 @@ class User(TableABC): return str( f""" INSERT INTO `Users` ( - `DiscordId`, `XP`, `ServerId`, `CreatedAt`, `LastModifiedAt` + `DiscordId`, `XP`, `ServerId` ) VALUES ( {self._discord_id}, {self._xp}, - {self._server.server_id}, - '{self._created_at}', - '{self._modified_at}' + {self._server.id} ); """ ) @@ -102,8 +165,7 @@ class User(TableABC): return str( f""" UPDATE `Users` - SET `XP` = {self._xp}, - `LastModifiedAt` = '{self._modified_at}' + SET `XP` = {self._xp} WHERE `UserId` = {self._user_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/user_game_ident.py b/kdb-bot/src/bot_data/model/user_game_ident.py new file mode 100644 index 00000000..22e7946f --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_game_ident.py @@ -0,0 +1,123 @@ +from datetime import datetime + +from cpl_core.database import TableABC + +from bot_data.model.game_server import GameServer +from bot_data.model.user import User + + +class UserGameIdent(TableABC): + def __init__( + self, + user: User, + game_server: GameServer, + ident: str, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._user = user + self._game_server = game_server + self._ident = ident + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def user(self) -> User: + return self._user + + @property + def game_server(self) -> GameServer: + return self._game_server + + @property + def ident(self) -> str: + return self._ident + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `UserGameIdents`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserGameIdents` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_ident_string(ident: str) -> str: + return str( + f""" + SELECT * FROM `UserGameIdents` + WHERE `Ident` = '{ident}'; + """ + ) + + @staticmethod + def get_select_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserGameIdents` + WHERE `UserId` = {id}; + """ + ) + + @staticmethod + def get_select_active_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserGameIdents` + WHERE `UserId` = {id} + AND `LeavedOn` IS NULL; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `UserGameIdents` ( + `UserId`, `GameServerId`, `Ident` + ) VALUES ( + {self._user.id}, + '{self._game_server.id}', + '{self._ident}' + ); + """ + ) + + @property + def udpate_string(self) -> str: + return "" + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `UserGameIdents` + WHERE `Id` = {self._id}; + """ + ) + + @staticmethod + def delete_by_user_id_string(id: int) -> str: + return str( + f""" + DELETE FROM `UserGameIdents` + WHERE `UserId` = {id} + """ + ) diff --git a/kdb-bot/src/bot_data/model/user_history.py b/kdb-bot/src/bot_data/model/user_history.py new file mode 100644 index 00000000..d3b88ca7 --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_history.py @@ -0,0 +1,65 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_query.extension import List + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class UserHistory(HistoryTableABC): + def __init__( + self, + dc_id: int, + xp: int, + server: int, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._user_id = id + self._discord_id = dc_id + self._xp = xp + self._server = server + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._user_id + + @property + def discord_id(self) -> int: + return self._discord_id + + @property + def xp(self) -> int: + return self._xp + + @property + def server(self) -> int: + return self._server + + @property + @ServiceProviderABC.inject + def left_server( + self, + services: ServiceProviderABC, + ) -> bool: + from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC + + ujs: UserJoinedServerRepositoryABC = services.get_service(UserJoinedServerRepositoryABC) + return ujs.find_active_user_joined_server_by_user_id(self.id) is None + + @property + @ServiceProviderABC.inject + def game_idents( + self, + services: ServiceProviderABC, + ) -> List["UserGameIdent"]: + from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC + + game_idents_repo: UserGameIdentRepositoryABC = services.get_service(UserGameIdentRepositoryABC) + return game_idents_repo.get_user_game_idents_by_user_id(self.id) diff --git a/kdb-bot/src/bot_data/model/user_joined_game_server.py b/kdb-bot/src/bot_data/model/user_joined_game_server.py new file mode 100644 index 00000000..cf60229d --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_joined_game_server.py @@ -0,0 +1,143 @@ +from datetime import datetime + +from cpl_core.database import TableABC + +from bot_data.model.game_server import GameServer +from bot_data.model.user import User + + +class UserJoinedGameServer(TableABC): + def __init__( + self, + user: User, + game_server: GameServer, + joined_on: datetime, + leaved_on: datetime = None, + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._user = user + self._game_server = game_server + self._joined_on = joined_on + self._leaved_on = leaved_on + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def user(self) -> User: + return self._user + + @property + def game_server(self) -> GameServer: + return self._game_server + + @property + def time(self) -> float: + if self._leaved_on is None or self._joined_on is None: + return 0 + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + + @property + def joined_on(self) -> datetime: + return self._joined_on + + @joined_on.setter + def joined_on(self, value: datetime): + self._modified_at = datetime.now() + self.joined_on = value + + @property + def leaved_on(self) -> datetime: + return self._leaved_on + + @leaved_on.setter + def leaved_on(self, value: datetime): + self._modified_at = datetime.now() + self._leaved_on = value + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `UserJoinedGameServer`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserJoinedGameServer` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserJoinedGameServer` + WHERE `UserId` = {id}; + """ + ) + + @staticmethod + def get_select_active_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserJoinedGameServer` + WHERE `UserId` = {id} + AND `LeavedOn` IS NULL; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `UserJoinedGameServer` ( + `UserId`, `GameServerId`, `JoinedOn`, `LeavedOn` + ) VALUES ( + {self._user.id}, + '{self._game_server.id}', + '{self._joined_on}', + {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `UserJoinedGameServer` + SET `LeavedOn` = {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"} + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `UserJoinedGameServer` + WHERE `Id` = {self._id}; + """ + ) + + @staticmethod + def delete_by_user_id_string(id: int) -> str: + return str( + f""" + DELETE FROM `UserJoinedGameServer` + WHERE `UserId` = {id} + """ + ) diff --git a/kdb-bot/src/bot_data/model/user_joined_game_server_history.py b/kdb-bot/src/bot_data/model/user_joined_game_server_history.py new file mode 100644 index 00000000..24da148a --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_joined_game_server_history.py @@ -0,0 +1,54 @@ +from datetime import datetime + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class UserJoinedGameServerHistory(HistoryTableABC): + def __init__( + self, + user: int, + game_server: int, + joined_on: datetime, + leaved_on: datetime, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._id = id + self._user = user + self._game_server = game_server + self._joined_on = joined_on + self._leaved_on = leaved_on + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._id + + @property + def user(self) -> int: + return self._user + + @property + def game_server(self) -> int: + return self._game_server + + @property + def time(self) -> float: + if self._leaved_on is None or self._joined_on is None: + return 0 + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + + @property + def joined_on(self) -> datetime: + return self._joined_on + + @property + def leaved_on(self) -> datetime: + return self._leaved_on diff --git a/kdb-bot/src/bot_data/model/user_joined_server.py b/kdb-bot/src/bot_data/model/user_joined_server.py index 7c0764d1..e55cb60d 100644 --- a/kdb-bot/src/bot_data/model/user_joined_server.py +++ b/kdb-bot/src/bot_data/model/user_joined_server.py @@ -1,10 +1,8 @@ from datetime import datetime -from typing import Optional from cpl_core.database import TableABC from bot_data.model.user import User -from bot_data.model.server import Server class UserJoinedServer(TableABC): @@ -27,7 +25,7 @@ class UserJoinedServer(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def join_id(self) -> int: + def id(self) -> int: return self._join_id @property @@ -69,6 +67,15 @@ class UserJoinedServer(TableABC): """ ) + @staticmethod + def get_select_by_server_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserJoinedServers` + WHERE `ServerId` = {id}; + """ + ) + @staticmethod def get_select_by_user_id_string(id: int) -> str: return str( @@ -90,42 +97,25 @@ class UserJoinedServer(TableABC): @property def insert_string(self) -> str: - if self._leaved_on is not None: - return str( - f""" - INSERT INTO `UserJoinedServers` ( - `UserId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` - ) VALUES ( - {self._user.user_id}, - '{self._joined_on}', - '{self._leaved_on}', - '{self._created_at}', - '{self._modified_at}' - ); - """ - ) - else: - return str( - f""" - INSERT INTO `UserJoinedServers` ( - `UserId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` - ) VALUES ( - {self._user.user_id}, - '{self._joined_on}', - '{self._created_at}', - '{self._modified_at}' - ); - """ - ) + return str( + f""" + INSERT INTO `UserJoinedServers` ( + `UserId`, `JoinedOn`, `LeavedOn` + ) VALUES ( + {self._user.id}, + '{self._joined_on}', + {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"} + ); + """ + ) @property def udpate_string(self) -> str: return str( f""" UPDATE `UserJoinedServers` - SET `LeavedOn` = '{self._leaved_on}', - `LastModifiedAt` = '{self._modified_at}' - WHERE `UserId` = {self._user.user_id}; + SET `LeavedOn` = {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"} + WHERE `UserId` = {self._user.id}; """ ) diff --git a/kdb-bot/src/bot_data/model/user_joined_server_history.py b/kdb-bot/src/bot_data/model/user_joined_server_history.py new file mode 100644 index 00000000..639300a0 --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_joined_server_history.py @@ -0,0 +1,42 @@ +from datetime import datetime + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class UserJoinedServerHistory(HistoryTableABC): + def __init__( + self, + user: int, + joined_on: datetime, + leaved_on: datetime, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._join_id = id + self._user = user + self._joined_on = joined_on + self._leaved_on = leaved_on + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._join_id + + @property + def user(self) -> int: + return self._user + + @property + def joined_on(self) -> datetime: + return self._joined_on + + @property + def leaved_on(self) -> datetime: + return self._leaved_on diff --git a/kdb-bot/src/bot_data/model/user_joined_voice_channel.py b/kdb-bot/src/bot_data/model/user_joined_voice_channel.py index 59e46466..dda013e6 100644 --- a/kdb-bot/src/bot_data/model/user_joined_voice_channel.py +++ b/kdb-bot/src/bot_data/model/user_joined_voice_channel.py @@ -1,6 +1,8 @@ from datetime import datetime from cpl_core.database import TableABC +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC from bot_data.model.user import User @@ -9,7 +11,7 @@ class UserJoinedVoiceChannel(TableABC): def __init__( self, user: User, - dc_channel_id: int, + channel_id: int, joined_on: datetime, leaved_on: datetime = None, created_at: datetime = None, @@ -17,7 +19,7 @@ class UserJoinedVoiceChannel(TableABC): id=0, ): self._join_id = id - self._dc_channel_id = dc_channel_id + self._channel_id = channel_id self._user = user self._joined_on = joined_on self._leaved_on = leaved_on @@ -27,17 +29,28 @@ class UserJoinedVoiceChannel(TableABC): self._modified_at = modified_at if modified_at is not None else self._modified_at @property - def join_id(self) -> int: + def id(self) -> int: return self._join_id @property - def dc_channel_id(self) -> int: - return self._dc_channel_id + def channel_id(self) -> int: + return self._channel_id + + @property + @ServiceProviderABC.inject + def channel_name(self, bot: DiscordBotServiceABC) -> str: + return bot.get_channel(self.channel_id).name @property def user(self) -> User: return self._user + @property + def time(self) -> float: + if self._leaved_on is None or self._joined_on is None: + return 0 + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + @property def joined_on(self) -> datetime: return self._joined_on @@ -94,43 +107,25 @@ class UserJoinedVoiceChannel(TableABC): @property def insert_string(self) -> str: - if self._leaved_on is not None: - return str( - f""" - INSERT INTO `UserJoinedVoiceChannel` ( - `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn`, `CreatedAt`, `LastModifiedAt` - ) VALUES ( - {self._user.user_id}, - {self._dc_channel_id}, - '{self._joined_on}', - '{self._leaved_on}', - '{self._created_at}', - '{self._modified_at}' - ); - """ - ) - else: - return str( - f""" - INSERT INTO `UserJoinedVoiceChannel` ( - `UserId`, `DiscordChannelId`, `JoinedOn`, `CreatedAt`, `LastModifiedAt` - ) VALUES ( - {self._user.user_id}, - {self._dc_channel_id}, - '{self._joined_on}', - '{self._created_at}', - '{self._modified_at}' - ); - """ - ) + return str( + f""" + INSERT INTO `UserJoinedVoiceChannel` ( + `UserId`, `DiscordChannelId`, `JoinedOn`, `LeavedOn` + ) VALUES ( + {self._user.id}, + {self._channel_id}, + '{self._joined_on}', + {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"} + ); + """ + ) @property def udpate_string(self) -> str: return str( f""" UPDATE `UserJoinedVoiceChannel` - SET `LeavedOn` = '{self._leaved_on}', - `LastModifiedAt` = '{self._modified_at}' + SET `LeavedOn` = {"NULL" if self._leaved_on is None else f"'{self._leaved_on}'"} WHERE `JoinId` = {self._join_id}; """ ) diff --git a/kdb-bot/src/bot_data/model/user_joined_voice_channel_history.py b/kdb-bot/src/bot_data/model/user_joined_voice_channel_history.py new file mode 100644 index 00000000..5c1ee49a --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_joined_voice_channel_history.py @@ -0,0 +1,62 @@ +from datetime import datetime + +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.history_table_abc import HistoryTableABC + + +class UserJoinedVoiceChannelHistory(HistoryTableABC): + def __init__( + self, + user: int, + channel_id: int, + joined_on: datetime, + leaved_on: datetime, + deleted: bool, + date_from: str, + date_to: str, + id=0, + ): + HistoryTableABC.__init__(self) + + self._join_id = id + self._channel_id = channel_id + self._user = user + self._joined_on = joined_on + self._leaved_on = leaved_on + + self._deleted = deleted + self._date_from = date_from + self._date_to = date_to + + @property + def id(self) -> int: + return self._join_id + + @property + def channel_id(self) -> int: + return self._channel_id + + @property + @ServiceProviderABC.inject + def channel_name(self, bot: DiscordBotServiceABC) -> str: + return bot.get_channel(self.channel_id).name + + @property + def user(self) -> int: + return self._user + + @property + def time(self) -> float: + if self._leaved_on is None or self._joined_on is None: + return 0 + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + + @property + def joined_on(self) -> datetime: + return self._joined_on + + @property + def leaved_on(self) -> datetime: + return self._leaved_on diff --git a/kdb-bot/src/bot_data/model/user_message_count_per_hour.py b/kdb-bot/src/bot_data/model/user_message_count_per_hour.py index 6fdb7b9b..7815ffa4 100644 --- a/kdb-bot/src/bot_data/model/user_message_count_per_hour.py +++ b/kdb-bot/src/bot_data/model/user_message_count_per_hour.py @@ -44,7 +44,6 @@ class UserMessageCountPerHour(TableABC): @xp_count.setter def xp_count(self, value: int): - self._modified_at = datetime.now().isoformat() self._xp_count = value @property @@ -95,14 +94,12 @@ class UserMessageCountPerHour(TableABC): return str( f""" INSERT INTO `UserMessageCountPerHour` ( - `UserId`, `Date`, `Hour`, `XPCount`, `CreatedAt`, `LastModifiedAt` + `UserId`, `Date`, `Hour`, `XPCount` ) VALUES ( - {self._user.user_id}, + {self._user.id}, '{self._date}', {self._hour}, - {self._xp_count}, - '{self._created_at}', - '{self._modified_at}' + {self._xp_count} ); """ ) @@ -112,8 +109,7 @@ class UserMessageCountPerHour(TableABC): return str( f""" UPDATE `UserMessageCountPerHour` - SET `XPCount` = '{self._xp_count}', - `LastModifiedAt` = '{self._modified_at}' + SET `XPCount` = '{self._xp_count}' WHERE `Id` = {self._id}; """ ) diff --git a/kdb-bot/src/bot_data/model/user_role_enum.py b/kdb-bot/src/bot_data/model/user_role_enum.py new file mode 100644 index 00000000..ad612e1d --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_role_enum.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class UserRoleEnum(Enum): + member = 0 + moderator = 1 + admin = 2 + technician = 3 diff --git a/kdb-bot/src/bot_data/model/user_warnings.py b/kdb-bot/src/bot_data/model/user_warnings.py new file mode 100644 index 00000000..99610a5f --- /dev/null +++ b/kdb-bot/src/bot_data/model/user_warnings.py @@ -0,0 +1,102 @@ +from datetime import datetime +from typing import Optional + +from cpl_core.database import TableABC + +from bot_data.model.user import User + + +# had to name it UserWarnings instead of UserWarning because UserWarning is a builtin class +class UserWarnings(TableABC): + def __init__( + self, + description: str, + user: User, + author: Optional[User], + created_at: datetime = None, + modified_at: datetime = None, + id=0, + ): + self._id = id + self._description = description + self._user = user + self._author = author + + TableABC.__init__(self) + self._created_at = created_at if created_at is not None else self._created_at + self._modified_at = modified_at if modified_at is not None else self._modified_at + + @property + def id(self) -> int: + return self._id + + @property + def description(self) -> str: + return self._description + + @property + def user(self) -> User: + return self._user + + @property + def author(self) -> Optional[User]: + return self._author + + @staticmethod + def get_select_all_string() -> str: + return str( + f""" + SELECT * FROM `UserWarnings`; + """ + ) + + @staticmethod + def get_select_by_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserWarnings` + WHERE `Id` = {id}; + """ + ) + + @staticmethod + def get_select_by_user_id_string(id: int) -> str: + return str( + f""" + SELECT * FROM `UserWarnings` + WHERE `UserId` = {id}; + """ + ) + + @property + def insert_string(self) -> str: + return str( + f""" + INSERT INTO `UserWarnings` ( + `Description`, `UserId`, `Author` + ) VALUES ( + '{self._description}', + {self._user.id}, + {"NULL" if self._author is None else f"{self._author.id}"} + ); + """ + ) + + @property + def udpate_string(self) -> str: + return str( + f""" + UPDATE `UserWarnings` + SET `Description` = '{self._description}' + WHERE `Id` = {self._id}; + """ + ) + + @property + def delete_string(self) -> str: + return str( + f""" + DELETE FROM `UserWarnings` + WHERE `Id` = {self._id}; + """ + ) diff --git a/kdb-bot/src/bot_data/service/__init__.py b/kdb-bot/src/bot_data/service/__init__.py index 9fdedbe6..0e0b81e3 100644 --- a/kdb-bot/src/bot_data/service/__init__.py +++ b/kdb-bot/src/bot_data/service/__init__.py @@ -15,7 +15,7 @@ __title__ = "bot_data.service" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_data/service/api_key_repository_service.py b/kdb-bot/src/bot_data/service/api_key_repository_service.py new file mode 100644 index 00000000..d4f57dfc --- /dev/null +++ b/kdb-bot/src/bot_data/service/api_key_repository_service.py @@ -0,0 +1,77 @@ +from typing import Optional + +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.api_key import ApiKey + + +class ApiKeyRepositoryService(ApiKeyRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + users: UserRepositoryABC, + ): + self._logger = logger + self._context = db_context + + self._users = users + + ApiKeyRepositoryABC.__init__(self) + + @staticmethod + def _get_value_from_result(value: any) -> Optional[any]: + if isinstance(value, str) and "NULL" in value: + return None + + return value + + def _api_key_from_result(self, sql_result: tuple) -> ApiKey: + creator = self._get_value_from_result(sql_result[3]) + api_key = ApiKey( + self._get_value_from_result(sql_result[1]), + self._get_value_from_result(sql_result[2]), + None if creator is None else self._users.get_user_by_id(int(creator)), + self._get_value_from_result(sql_result[4]), + self._get_value_from_result(sql_result[5]), + id=self._get_value_from_result(sql_result[0]), + ) + + return api_key + + def get_api_keys(self) -> List[ApiKey]: + api_keys = List(ApiKey) + self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_all_string()}") + results = self._context.select(ApiKey.get_select_all_string()) + for result in results: + api_keys.append(self._api_key_from_result(result)) + + return api_keys + + def get_api_key(self, identifier: str, key: str) -> ApiKey: + self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_string(identifier, key)}") + return self._api_key_from_result(self._context.select(ApiKey.get_select_string(identifier, key))[0]) + + def get_api_key_by_id(self, id: int) -> ApiKey: + self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_by_id(id)}") + return self._api_key_from_result(self._context.select(ApiKey.get_select_by_id(id))[0]) + + def get_api_key_by_key(self, key: str) -> ApiKey: + self._logger.trace(__name__, f"Send SQL command: {ApiKey.get_select_by_key(key)}") + return self._api_key_from_result(self._context.select(ApiKey.get_select_by_key(key))[0]) + + def add_api_key(self, api_key: ApiKey): + self._logger.trace(__name__, f"Send SQL command: {api_key.insert_string}") + self._context.cursor.execute(api_key.insert_string) + + def update_api_key(self, api_key: ApiKey): + self._logger.trace(__name__, f"Send SQL command: {api_key.udpate_string}") + self._context.cursor.execute(api_key.udpate_string) + + def delete_api_key(self, api_key: ApiKey): + self._logger.trace(__name__, f"Send SQL command: {api_key.delete_string}") + self._context.cursor.execute(api_key.delete_string) diff --git a/kdb-bot/src/bot_data/service/auth_user_repository_service.py b/kdb-bot/src/bot_data/service/auth_user_repository_service.py index 15592b4c..295e3c2f 100644 --- a/kdb-bot/src/bot_data/service/auth_user_repository_service.py +++ b/kdb-bot/src/bot_data/service/auth_user_repository_service.py @@ -11,7 +11,6 @@ from bot_data.filtered_result import FilteredResult from bot_data.model.auth_role_enum import AuthRoleEnum from bot_data.model.auth_user import AuthUser from bot_data.model.auth_user_users_relation import AuthUserUsersRelation -from bot_data.model.user import User class AuthUserRepositoryService(AuthUserRepositoryABC): diff --git a/kdb-bot/src/bot_data/service/auto_role_repository_service.py b/kdb-bot/src/bot_data/service/auto_role_repository_service.py index b9d51e12..d1599341 100644 --- a/kdb-bot/src/bot_data/service/auto_role_repository_service.py +++ b/kdb-bot/src/bot_data/service/auto_role_repository_service.py @@ -5,14 +5,16 @@ from cpl_query.extension import List from bot_core.logging.database_logger import DatabaseLogger from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC from bot_data.model.auto_role import AutoRole from bot_data.model.auto_role_rule import AutoRoleRule class AutoRoleRepositoryService(AutoRoleRepositoryABC): - def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC): + def __init__(self, logger: DatabaseLogger, db_context: DatabaseContextABC, servers: ServerRepositoryABC): self._logger = logger self._context = db_context + self._servers = servers AutoRoleRepositoryABC.__init__(self) @@ -21,14 +23,20 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC): self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_all_string()}") results = self._context.select(AutoRole.get_select_all_string()) for result in results: - auto_roles.append(AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0])) + auto_roles.append( + AutoRole( + self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) + ) return auto_roles def get_auto_role_by_id(self, id: int) -> AutoRole: self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}") result = self._context.select(AutoRole.get_select_by_id_string(id))[0] - return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) + return AutoRole( + self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) def find_auto_role_by_id(self, id: int) -> Optional[AutoRole]: self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_id_string(id)}") @@ -38,14 +46,20 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC): result = result[0] - return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) + return AutoRole( + self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) def get_auto_roles_by_server_id(self, id: int) -> List[AutoRole]: self._logger.trace(__name__, f"Send SQL command: {AutoRole.get_select_by_server_id_string(id)}") auto_roles = List(AutoRole) results = self._context.select(AutoRole.get_select_by_server_id_string(id)) for result in results: - auto_roles.append(AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0])) + auto_roles.append( + AutoRole( + self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) + ) return auto_roles @@ -55,7 +69,9 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC): f"Send SQL command: {AutoRole.get_select_by_message_id_string(id)}", ) result = self._context.select(AutoRole.get_select_by_message_id_string(id))[0] - return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) + return AutoRole( + self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) def find_auto_role_by_message_id(self, id: int) -> Optional[AutoRole]: self._logger.trace( @@ -68,7 +84,9 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC): result = result[0] - return AutoRole(result[1], result[2], result[3], result[4], result[5], id=result[0]) + return AutoRole( + self._servers.get_server_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) def add_auto_role(self, auto_role: AutoRole): self._logger.trace(__name__, f"Send SQL command: {auto_role.insert_string}") @@ -87,14 +105,20 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC): self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_all_string()}") results = self._context.select(AutoRoleRule.get_select_all_string()) for result in results: - auto_role_rules.append(AutoRoleRule(result[1], result[2], result[3], result[4], result[5], id=result[0])) + auto_role_rules.append( + AutoRoleRule( + self.get_auto_role_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) + ) return auto_role_rules def get_auto_role_rule_by_id(self, id: int) -> AutoRoleRule: self._logger.trace(__name__, f"Send SQL command: {AutoRoleRule.get_select_by_id_string(id)}") result = self._context.select(AutoRoleRule.get_select_by_id_string(id))[0] - return AutoRoleRule(result[1], result[2], result[3], result[4], result[5], id=result[0]) + return AutoRoleRule( + self.get_auto_role_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) def get_auto_role_rules_by_auto_role_id(self, id: int) -> List[AutoRoleRule]: auto_role_rules = List(AutoRoleRule) @@ -104,7 +128,11 @@ class AutoRoleRepositoryService(AutoRoleRepositoryABC): ) results = self._context.select(AutoRoleRule.get_select_by_auto_role_id_string(id)) for result in results: - auto_role_rules.append(AutoRoleRule(result[1], result[2], result[3], result[4], result[5], id=result[0])) + auto_role_rules.append( + AutoRoleRule( + self.get_auto_role_by_id(result[1]), result[2], result[3], result[4], result[5], id=result[0] + ) + ) return auto_role_rules diff --git a/kdb-bot/src/bot_data/service/client_repository_service.py b/kdb-bot/src/bot_data/service/client_repository_service.py index 85a4f51e..587569a0 100644 --- a/kdb-bot/src/bot_data/service/client_repository_service.py +++ b/kdb-bot/src/bot_data/service/client_repository_service.py @@ -38,6 +38,8 @@ class ClientRepositoryService(ClientRepositoryABC): result[5], result[6], self._servers.get_server_by_id(result[7]), + result[8], + result[9], id=result[0], ) ) @@ -55,9 +57,33 @@ class ClientRepositoryService(ClientRepositoryABC): result[5], result[6], self._servers.get_server_by_id(result[7]), + result[8], + result[9], id=result[0], ) + def get_clients_by_server_id(self, server_id: int) -> List[Client]: + clients = List(Client) + self._logger.trace(__name__, f"Send SQL command: {Client.get_select_by_server_id_string(server_id)}") + results = self._context.select(Client.get_select_by_server_id_string(server_id)) + for result in results: + clients.append( + Client( + result[1], + result[2], + result[3], + result[4], + result[5], + result[6], + self._servers.get_server_by_id(result[7]), + result[8], + result[9], + id=result[0], + ) + ) + + return clients + def get_client_by_discord_id(self, discord_id: int) -> Client: self._logger.trace( __name__, @@ -72,6 +98,8 @@ class ClientRepositoryService(ClientRepositoryABC): result[5], result[6], self._servers.get_server_by_id(result[7]), + result[8], + result[9], id=result[0], ) @@ -94,6 +122,8 @@ class ClientRepositoryService(ClientRepositoryABC): result[5], result[6], self._servers.get_server_by_id(result[7]), + result[8], + result[9], id=result[0], ) @@ -116,6 +146,8 @@ class ClientRepositoryService(ClientRepositoryABC): result[5], result[6], self._servers.get_server_by_id(result[7]), + result[8], + result[9], id=result[0], ) @@ -138,6 +170,8 @@ class ClientRepositoryService(ClientRepositoryABC): result[5], result[6], self._servers.get_server_by_id(result[7]), + result[8], + result[9], id=result[0], ) @@ -159,9 +193,9 @@ class ClientRepositoryService(ClientRepositoryABC): self._logger.warn(__name__, f"Cannot find server by id {server_id}") raise Exception("Value not found") - client = self.find_client_by_discord_id_and_server_id(id, server.server_id) + client = self.find_client_by_discord_id_and_server_id(id, server.id) if client is None: - self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.server_id}") + self._logger.warn(__name__, f"Cannot find client by ids {id}@{server.id}") raise Exception("Value not found") return client diff --git a/kdb-bot/src/bot_data/service/game_server_repository_service.py b/kdb-bot/src/bot_data/service/game_server_repository_service.py new file mode 100644 index 00000000..20f89433 --- /dev/null +++ b/kdb-bot/src/bot_data/service/game_server_repository_service.py @@ -0,0 +1,89 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.game_server import GameServer + + +class GameServerRepositoryService(GameServerRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + servers: ServerRepositoryABC, + api_keys: ApiKeyRepositoryABC, + ): + self._logger = logger + + self._context = db_context + self._servers = servers + self._api_keys = api_keys + + GameServerRepositoryABC.__init__(self) + + def _from_result(self, result: tuple): + return GameServer( + result[1], + self._servers.get_server_by_id(result[2]), + self._api_keys.get_api_key_by_id(result[3]), + result[4], + result[5], + id=result[0], + ) + + def get_game_servers(self) -> List[GameServer]: + game_servers = List(GameServer) + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_all_string()}", + ) + results = self._context.select(GameServer.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}") + game_servers.append(self._from_result(result)) + + return game_servers + + def get_game_servers_by_server_id(self, id: int) -> List[GameServer]: + game_servers = List(GameServer) + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_by_server_id_string(id)}", + ) + results = self._context.select(GameServer.get_select_by_server_id_string(id)) + for result in results: + self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}") + game_servers.append(self._from_result(result)) + + return game_servers + + def get_game_server_by_id(self, id: int) -> GameServer: + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_by_id_string(id)}", + ) + result = self._context.select(GameServer.get_select_by_id_string(id))[0] + return self._from_result(result) + + def get_game_server_by_api_key_id(self, id: int) -> GameServer: + self._logger.trace( + __name__, + f"Send SQL command: {GameServer.get_select_by_api_key_id_string(id)}", + ) + result = self._context.select(GameServer.get_select_by_api_key_id_string(id))[0] + return self._from_result(result) + + def add_game_server(self, game_server: GameServer): + self._logger.trace(__name__, f"Send SQL command: {game_server.insert_string}") + self._context.cursor.execute(game_server.insert_string) + + def update_game_server(self, game_server: GameServer): + self._logger.trace(__name__, f"Send SQL command: {game_server.udpate_string}") + self._context.cursor.execute(game_server.udpate_string) + + def delete_game_server(self, game_server: GameServer): + self._logger.trace(__name__, f"Send SQL command: {game_server.delete_string}") + self._context.cursor.execute(game_server.delete_string) diff --git a/kdb-bot/src/bot_data/service/migration_service.py b/kdb-bot/src/bot_data/service/migration_service.py index 7b924f90..dc6436a7 100644 --- a/kdb-bot/src/bot_data/service/migration_service.py +++ b/kdb-bot/src/bot_data/service/migration_service.py @@ -1,5 +1,3 @@ -from typing import Type - from cpl_core.database.context import DatabaseContextABC from cpl_core.dependency_injection import ServiceProviderABC from cpl_query.extension import List @@ -22,7 +20,9 @@ class MigrationService: self._db = db self._cursor = db.cursor - self._migrations = List(type, MigrationABC.__subclasses__()).order_by(lambda x: x.name) + self._migrations: List[MigrationABC] = ( + List(type, MigrationABC.__subclasses__()).order_by(lambda x: x.name).order_by(lambda x: x.prio) + ) def migrate(self): self._logger.info(__name__, f"Running Migrations") diff --git a/kdb-bot/src/bot_data/service/seeder_service.py b/kdb-bot/src/bot_data/service/seeder_service.py index 04e999cc..feada479 100644 --- a/kdb-bot/src/bot_data/service/seeder_service.py +++ b/kdb-bot/src/bot_data/service/seeder_service.py @@ -1,6 +1,5 @@ from cpl_core.database.context import DatabaseContextABC from cpl_core.dependency_injection import ServiceProviderABC -from cpl_query.extension import List from bot_core.logging.database_logger import DatabaseLogger from bot_data.abc.data_seeder_abc import DataSeederABC @@ -18,12 +17,10 @@ class SeederService: self._db = db - self._seeder = List(type, DataSeederABC.__subclasses__()) - async def seed(self): self._logger.info(__name__, f"Seed data") - for seeder in self._seeder: - seeder_as_service: DataSeederABC = self._services.get_service(seeder) - self._logger.debug(__name__, f"Starting seeder {seeder.__name__}") - await seeder_as_service.seed() + for seeder in self._services.get_services(list[DataSeederABC]): + seeder: DataSeederABC = seeder + self._logger.debug(__name__, f"Starting seeder {type(seeder).__name__}") + await seeder.seed() self._db.save_changes() diff --git a/kdb-bot/src/bot_data/service/server_repository_service.py b/kdb-bot/src/bot_data/service/server_repository_service.py index ab6fbe84..3291ceaa 100644 --- a/kdb-bot/src/bot_data/service/server_repository_service.py +++ b/kdb-bot/src/bot_data/service/server_repository_service.py @@ -22,7 +22,7 @@ class ServerRepositoryService(ServerRepositoryABC): self._logger.trace(__name__, f"Send SQL command: {Server.get_select_all_string()}") results = self._context.select(Server.get_select_all_string()) for result in results: - servers.append(Server(result[1], id=result[0])) + servers.append(Server(result[1], result[2], result[3], id=result[0])) return servers @@ -54,7 +54,7 @@ class ServerRepositoryService(ServerRepositoryABC): def get_server_by_id(self, server_id: int) -> Server: self._logger.trace(__name__, f"Send SQL command: {Server.get_select_by_id_string(server_id)}") result = self._context.select(Server.get_select_by_id_string(server_id))[0] - return Server(result[1], id=result[0]) + return Server(result[1], result[2], result[3], id=result[0]) def get_server_by_discord_id(self, discord_id: int) -> Server: self._logger.trace( @@ -62,7 +62,7 @@ class ServerRepositoryService(ServerRepositoryABC): f"Send SQL command: {Server.get_select_by_discord_id_string(discord_id)}", ) result = self._context.select(Server.get_select_by_discord_id_string(discord_id))[0] - return Server(result[1], id=result[0]) + return Server(result[1], result[2], result[3], id=result[0]) def find_server_by_discord_id(self, discord_id: int) -> Optional[Server]: self._logger.trace( diff --git a/kdb-bot/src/bot_data/service/statistic_repository_service.py b/kdb-bot/src/bot_data/service/statistic_repository_service.py deleted file mode 100644 index b425605e..00000000 --- a/kdb-bot/src/bot_data/service/statistic_repository_service.py +++ /dev/null @@ -1,106 +0,0 @@ -from typing import Optional - -from cpl_core.database.context import DatabaseContextABC -from cpl_core.utils import CredentialManager -from cpl_query.extension import List - -from bot_core.logging.database_logger import DatabaseLogger -from bot_data.abc.server_repository_abc import ServerRepositoryABC -from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC -from bot_data.model.statistic import Statistic - - -class StatisticRepositoryService(StatisticRepositoryABC): - def __init__( - self, - logger: DatabaseLogger, - db_context: DatabaseContextABC, - statistics: ServerRepositoryABC, - ): - self._logger = logger - self._context = db_context - - self._statistics = statistics - - StatisticRepositoryABC.__init__(self) - - @staticmethod - def _get_value_from_result(value: any) -> Optional[any]: - if isinstance(value, str) and "NULL" in value: - return None - - return value - - def _statistic_from_result(self, sql_result: tuple) -> Statistic: - code = self._get_value_from_result(sql_result[3]) - if code is not None: - code = CredentialManager.decrypt(code) - - statistic = Statistic( - self._get_value_from_result(sql_result[1]), - self._get_value_from_result(sql_result[2]), - code, - self._statistics.get_server_by_id(sql_result[4]), - id=self._get_value_from_result(sql_result[0]), - ) - - return statistic - - def get_statistics(self) -> List[Statistic]: - statistics = List(Statistic) - self._logger.trace(__name__, f"Send SQL command: {Statistic.get_select_all_string()}") - results = self._context.select(Statistic.get_select_all_string()) - for result in results: - statistics.append(self._statistic_from_result(result)) - - return statistics - - def get_statistics_by_server_id(self, server_id: int) -> List[Statistic]: - statistics = List(Statistic) - self._logger.trace( - __name__, - f"Send SQL command: {Statistic.get_select_by_server_string(server_id)}", - ) - results = self._context.select(Statistic.get_select_by_server_string(server_id)) - for result in results: - statistics.append(self._statistic_from_result(result)) - - return statistics - - def get_statistic_by_id(self, id: int) -> Statistic: - self._logger.trace(__name__, f"Send SQL command: {Statistic.get_select_by_id_string(id)}") - result = self._context.select(Statistic.get_select_by_id_string(id))[0] - return self._statistic_from_result(result) - - def get_statistic_by_name(self, name: str, server_id: int) -> Statistic: - self._logger.trace( - __name__, - f"Send SQL command: {Statistic.get_select_by_name_string(name, server_id)}", - ) - result = self._context.select(Statistic.get_select_by_name_string(name, server_id))[0] - return self._statistic_from_result(result) - - def find_statistic_by_name(self, name: str, server_id: int) -> Optional[Statistic]: - self._logger.trace( - __name__, - f"Send SQL command: {Statistic.get_select_by_name_string(name, server_id)}", - ) - result = self._context.select(Statistic.get_select_by_name_string(name, server_id)) - if result is None or len(result) == 0: - return None - - result = result[0] - - return self._statistic_from_result(result) - - def add_statistic(self, statistic: Statistic): - self._logger.trace(__name__, f"Send SQL command: {statistic.insert_string}") - self._context.cursor.execute(statistic.insert_string) - - def update_statistic(self, statistic: Statistic): - self._logger.trace(__name__, f"Send SQL command: {statistic.udpate_string}") - self._context.cursor.execute(statistic.udpate_string) - - def delete_statistic(self, statistic: Statistic): - self._logger.trace(__name__, f"Send SQL command: {statistic.delete_string}") - self._context.cursor.execute(statistic.delete_string) diff --git a/kdb-bot/src/bot_data/service/user_game_ident_repository_service.py b/kdb-bot/src/bot_data/service/user_game_ident_repository_service.py new file mode 100644 index 00000000..5967d78b --- /dev/null +++ b/kdb-bot/src/bot_data/service/user_game_ident_repository_service.py @@ -0,0 +1,111 @@ +from typing import Optional + +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.user_game_ident_repository_abc import ( + UserGameIdentRepositoryABC, +) +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.user_game_ident import UserGameIdent + + +class UserGameIdentRepositoryService(UserGameIdentRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + users: UserRepositoryABC, + game_servers: GameServerRepositoryABC, + ): + self._logger = logger + self._context = db_context + + self._users = users + self._game_servers = game_servers + + UserGameIdentRepositoryABC.__init__(self) + + def _from_result(self, result: tuple) -> UserGameIdent: + return UserGameIdent( + self._users.get_user_by_id(result[1]), + self._game_servers.get_game_server_by_id(result[2]), + result[3], + result[4], + result[5], + id=result[0], + ) + + def get_user_game_idents(self) -> List[UserGameIdent]: + joins = List(UserGameIdent) + self._logger.trace( + __name__, + f"Send SQL command: {UserGameIdent.get_select_all_string()}", + ) + results = self._context.select(UserGameIdent.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Get UserGameIdent with id {result[0]}") + joins.append(self._from_result(result)) + + return joins + + def get_user_game_ident_by_id(self, id: int) -> UserGameIdent: + self._logger.trace( + __name__, + f"Send SQL command: {UserGameIdent.get_select_by_id_string(id)}", + ) + result = self._context.select(UserGameIdent.get_select_by_id_string(id))[0] + return self._from_result(result) + + def get_user_game_ident_by_ident(self, ident: str) -> UserGameIdent: + self._logger.trace( + __name__, + f"Send SQL command: {UserGameIdent.get_select_by_ident_string(ident)}", + ) + result = self._context.select(UserGameIdent.get_select_by_ident_string(ident))[0] + return self._from_result(result) + + def find_user_game_ident_by_ident(self, ident: str) -> Optional[UserGameIdent]: + self._logger.trace( + __name__, + f"Send SQL command: {UserGameIdent.get_select_by_ident_string(ident)}", + ) + result = self._context.select(UserGameIdent.get_select_by_ident_string(ident)) + if len(result) == 0: + return None + + result = result[0] + return self._from_result(result) + + def get_user_game_idents_by_user_id(self, user_id: int) -> List[UserGameIdent]: + joins = List(UserGameIdent) + self._logger.trace( + __name__, + f"Send SQL command: {UserGameIdent.get_select_by_user_id_string(user_id)}", + ) + results = self._context.select(UserGameIdent.get_select_by_user_id_string(user_id)) + for result in results: + joins.append(self._from_result(result)) + + return joins + + def add_user_game_ident(self, user_game_ident: UserGameIdent): + self._logger.trace(__name__, f"Send SQL command: {user_game_ident.insert_string}") + self._context.cursor.execute(user_game_ident.insert_string) + + def update_user_game_ident(self, user_game_ident: UserGameIdent): + self._logger.trace(__name__, f"Send SQL command: {user_game_ident.udpate_string}") + self._context.cursor.execute(user_game_ident.udpate_string) + + def delete_user_game_ident(self, user_game_ident: UserGameIdent): + self._logger.trace(__name__, f"Send SQL command: {user_game_ident.delete_string}") + self._context.cursor.execute(user_game_ident.delete_string) + + def delete_user_game_ident_by_user_id(self, user_id: int): + self._logger.trace( + __name__, + f"Send SQL command: {UserGameIdent.delete_by_user_id_string}", + ) + self._context.cursor.execute(UserGameIdent.delete_by_user_id_string(user_id)) diff --git a/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py b/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py new file mode 100644 index 00000000..e9ded8ba --- /dev/null +++ b/kdb-bot/src/bot_data/service/user_joined_game_server_repository_service.py @@ -0,0 +1,125 @@ +from typing import Optional + +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.user_joined_game_server_repository_abc import ( + UserJoinedGameServerRepositoryABC, +) +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.user_joined_game_server import UserJoinedGameServer + + +class UserJoinedGameServerRepositoryService(UserJoinedGameServerRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + users: UserRepositoryABC, + game_servers: GameServerRepositoryABC, + ): + self._logger = logger + self._context = db_context + + self._users = users + self._game_servers = game_servers + + UserJoinedGameServerRepositoryABC.__init__(self) + + def _from_result(self, result: tuple) -> UserJoinedGameServer: + return UserJoinedGameServer( + self._users.get_user_by_id(result[1]), + self._game_servers.get_game_server_by_id(result[2]), + result[3], + result[4], + result[5], + id=result[0], + ) + + def get_user_joined_game_servers(self) -> List[UserJoinedGameServer]: + joins = List(UserJoinedGameServer) + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.get_select_all_string()}", + ) + results = self._context.select(UserJoinedGameServer.get_select_all_string()) + for result in results: + self._logger.trace(__name__, f"Get user-joined-game-server with id {result[0]}") + joins.append(self._from_result(result)) + + return joins + + def get_user_joined_game_server_by_id(self, id: int) -> UserJoinedGameServer: + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.get_select_by_id_string(id)}", + ) + result = self._context.select(UserJoinedGameServer.get_select_by_id_string(id))[0] + return self._from_result(result) + + def get_user_joined_game_servers_by_user_id(self, user_id: int) -> List[UserJoinedGameServer]: + joins = List(UserJoinedGameServer) + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}", + ) + results = self._context.select(UserJoinedGameServer.get_select_by_user_id_string(user_id)) + for result in results: + joins.append(self._from_result(result)) + + return joins + + def get_active_user_joined_game_server_by_user_id(self, user_id: int) -> UserJoinedGameServer: + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}", + ) + result = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id))[0] + return self._from_result(result) + + def find_active_user_joined_game_server_by_user_id(self, user_id: int) -> Optional[UserJoinedGameServer]: + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.get_select_by_user_id_string(user_id)}", + ) + result = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id)) + if result is None or len(result) == 0: + return None + + result = result[0] + + return self._from_result(result) + + def find_active_user_joined_game_servers_by_user_id(self, user_id: int) -> List[Optional[UserJoinedGameServer]]: + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.get_select_active_by_user_id_string(user_id)}", + ) + result = List(UserJoinedGameServer) + db_results = self._context.select(UserJoinedGameServer.get_select_active_by_user_id_string(user_id)) + + for db_result in db_results: + result.append(self._from_result(db_result)) + + return result + + def add_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): + self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.insert_string}") + self._context.cursor.execute(user_joined_game_server.insert_string) + + def update_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): + self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.udpate_string}") + self._context.cursor.execute(user_joined_game_server.udpate_string) + + def delete_user_joined_game_server(self, user_joined_game_server: UserJoinedGameServer): + self._logger.trace(__name__, f"Send SQL command: {user_joined_game_server.delete_string}") + self._context.cursor.execute(user_joined_game_server.delete_string) + + def delete_user_joined_game_server_by_user_id(self, user_id: int): + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedGameServer.delete_by_user_id_string}", + ) + self._context.cursor.execute(UserJoinedGameServer.delete_by_user_id_string(user_id)) diff --git a/kdb-bot/src/bot_data/service/user_joined_server_repository_service.py b/kdb-bot/src/bot_data/service/user_joined_server_repository_service.py index 3c8a9d4b..abd0a17b 100644 --- a/kdb-bot/src/bot_data/service/user_joined_server_repository_service.py +++ b/kdb-bot/src/bot_data/service/user_joined_server_repository_service.py @@ -57,6 +57,21 @@ class UserJoinedServerRepositoryService(UserJoinedServerRepositoryABC): id=result[0], ) + def get_user_joined_server_by_server_id(self, server_id: int) -> UserJoinedServer: + self._logger.trace( + __name__, + f"Send SQL command: {UserJoinedServer.get(id)}", + ) + result = self._context.select(UserJoinedServer.get_select_by_id_string(id))[0] + return UserJoinedServer( + self._users.get_user_by_id(result[1]), + result[2], + result[3], + result[4], + result[5], + id=result[0], + ) + def get_user_joined_servers_by_user_id(self, user_id: int) -> List[UserJoinedServer]: joins = List(UserJoinedServer) self._logger.trace( diff --git a/kdb-bot/src/bot_data/service/user_repository_service.py b/kdb-bot/src/bot_data/service/user_repository_service.py index 00ee4a64..adc9685c 100644 --- a/kdb-bot/src/bot_data/service/user_repository_service.py +++ b/kdb-bot/src/bot_data/service/user_repository_service.py @@ -23,20 +23,23 @@ class UserRepositoryService(UserRepositoryABC): UserRepositoryABC.__init__(self) + def _from_result(self, result: tuple): + return User( + result[1], + result[2], + self._servers.get_server_by_id(result[3]), + result[4], + result[5], + id=result[0], + ) + def get_users(self) -> List[User]: users = List(User) self._logger.trace(__name__, f"Send SQL command: {User.get_select_all_string()}") results = self._context.select(User.get_select_all_string()) for result in results: self._logger.trace(__name__, f"Get user with id {result[0]}") - users.append( - User( - result[1], - result[2], - self._servers.get_server_by_id(result[3]), - id=result[0], - ) - ) + users.append(self._from_result(result)) return users @@ -44,12 +47,7 @@ class UserRepositoryService(UserRepositoryABC): self._logger.trace(__name__, f"Send SQL command: {User.get_select_by_id_string(id)}") result = self._context.select(User.get_select_by_id_string(id))[0] - return User( - result[1], - result[2], - self._servers.get_server_by_id(result[3]), - id=result[0], - ) + return self._from_result(result) def find_user_by_id(self, id: int) -> Optional[User]: self._logger.trace(__name__, f"Send SQL command: {User.get_select_by_id_string(id)}") @@ -59,12 +57,7 @@ class UserRepositoryService(UserRepositoryABC): result = result[0] - return User( - result[1], - result[2], - self._servers.get_server_by_id(result[3]), - id=result[0], - ) + return self._from_result(result) def get_users_by_discord_id(self, discord_id: int) -> List[User]: users = List(User) @@ -74,14 +67,19 @@ class UserRepositoryService(UserRepositoryABC): ) results = self._context.select(User.get_select_by_discord_id_string(discord_id)) for result in results: - users.append( - User( - result[1], - result[2], - self._servers.get_server_by_id(result[3]), - id=result[0], - ) - ) + users.append(self._from_result(result)) + + return users + + def get_users_by_server_id(self, server_id: int) -> List[User]: + users = List(User) + self._logger.trace( + __name__, + f"Send SQL command: {User.get_select_by_server_id_string(server_id)}", + ) + results = self._context.select(User.get_select_by_server_id_string(server_id)) + for result in results: + users.append(self._from_result(result)) return users @@ -92,12 +90,7 @@ class UserRepositoryService(UserRepositoryABC): ) result = self._context.select(User.get_select_by_discord_id_and_server_id_string(discord_id, server_id))[0] - return User( - result[1], - result[2], - self._servers.get_server_by_id(result[3]), - id=result[0], - ) + return self._from_result(result) def find_user_by_discord_id_and_server_id(self, discord_id: int, server_id: int) -> Optional[User]: self._logger.trace( @@ -110,14 +103,7 @@ class UserRepositoryService(UserRepositoryABC): result = result[0] - return User( - result[1], - result[2], - self._servers.get_server_by_id(result[3]), - result[4], - result[5], - id=result[0], - ) + return self._from_result(result) def add_user(self, user: User): self._logger.trace(__name__, f"Send SQL command: {user.insert_string}") diff --git a/kdb-bot/src/bot_data/service/user_warnings_repository_service.py b/kdb-bot/src/bot_data/service/user_warnings_repository_service.py new file mode 100644 index 00000000..ff19d61f --- /dev/null +++ b/kdb-bot/src/bot_data/service/user_warnings_repository_service.py @@ -0,0 +1,81 @@ +from typing import Optional + +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC +from bot_data.model.user_warnings import UserWarnings + + +class UserWarningsRepositoryService(UserWarningsRepositoryABC): + def __init__( + self, + logger: DatabaseLogger, + db_context: DatabaseContextABC, + users: UserRepositoryABC, + ): + self._logger = logger + self._context = db_context + + self._users = users + UserWarningsRepositoryABC.__init__(self) + + @staticmethod + def _get_value_from_result(value: any) -> Optional[any]: + if isinstance(value, str) and "NULL" in value: + return None + + return value + + def _from_result(self, sql_result: tuple) -> UserWarnings: + user = self._users.get_user_by_id(self._get_value_from_result(sql_result[2])) + author = None + author_id = self._get_value_from_result(sql_result[2]) + if author_id is not None: + author = self._users.get_user_by_id(author_id) + + return UserWarnings( + self._get_value_from_result(sql_result[1]), + user, + author, + self._get_value_from_result(sql_result[4]), + self._get_value_from_result(sql_result[5]), + id=self._get_value_from_result(sql_result[0]), + ) + + def get_user_warnings(self) -> List[UserWarnings]: + warnings = List(UserWarnings) + self._logger.trace(__name__, f"Send SQL command: {UserWarnings.get_select_all_string()}") + results = self._context.select(UserWarnings.get_select_all_string()) + for result in results: + warnings.append(self._from_result(result)) + + return warnings + + def get_user_warnings_by_id(self, id: int) -> UserWarnings: + self._logger.trace(__name__, f"Send SQL command: {UserWarnings.get_select_by_id_string(id)}") + result = self._context.select(UserWarnings.get_select_by_id_string(id))[0] + return self._from_result(result) + + def get_user_warnings_by_user_id(self, user_id: int) -> List[UserWarnings]: + warnings = List(UserWarnings) + self._logger.trace(__name__, f"Send SQL command: {UserWarnings.get_select_by_user_id_string(user_id)}") + results = self._context.select(UserWarnings.get_select_by_user_id_string(user_id)) + for result in results: + warnings.append(self._from_result(result)) + + return warnings + + def add_user_warnings(self, user_warnings: UserWarnings): + self._logger.trace(__name__, f"Send SQL command: {user_warnings.insert_string}") + self._context.cursor.execute(user_warnings.insert_string) + + def update_user_warnings(self, user_warnings: UserWarnings): + self._logger.trace(__name__, f"Send SQL command: {user_warnings.udpate_string}") + self._context.cursor.execute(user_warnings.udpate_string) + + def delete_user_warnings(self, user_warnings: UserWarnings): + self._logger.trace(__name__, f"Send SQL command: {user_warnings.delete_string}") + self._context.cursor.execute(user_warnings.delete_string) diff --git a/kdb-bot/src/modules/stats/ui/__init__.py b/kdb-bot/src/bot_graphql/__init__.py similarity index 77% rename from kdb-bot/src/modules/stats/ui/__init__.py rename to kdb-bot/src/bot_graphql/__init__.py index 2440a6d3..f55997ca 100644 --- a/kdb-bot/src/modules/stats/ui/__init__.py +++ b/kdb-bot/src/bot_graphql/__init__.py @@ -11,11 +11,11 @@ Discord bot for the Keksdose discord Server """ -__title__ = "modules.stats.ui" +__title__ = "bot_graphql" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/stats/__init__.py b/kdb-bot/src/bot_graphql/abc/__init__.py similarity index 77% rename from kdb-bot/src/modules/stats/__init__.py rename to kdb-bot/src/bot_graphql/abc/__init__.py index bfa8b9da..a1386d47 100644 --- a/kdb-bot/src/modules/stats/__init__.py +++ b/kdb-bot/src/bot_graphql/abc/__init__.py @@ -11,11 +11,11 @@ Discord bot for the Keksdose discord Server """ -__title__ = "modules.stats" +__title__ = "bot_graphql.abc" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_graphql/abc/data_query_abc.py b/kdb-bot/src/bot_graphql/abc/data_query_abc.py new file mode 100644 index 00000000..7603a4d2 --- /dev/null +++ b/kdb-bot/src/bot_graphql/abc/data_query_abc.py @@ -0,0 +1,19 @@ +from cpl_core.database import TableABC + +from bot_graphql.abc.query_abc import QueryABC + + +class DataQueryABC(QueryABC): + def __init__(self, name: str): + QueryABC.__init__(self, name) + + self.set_field("createdAt", self.resolve_created_at) + self.set_field("modifiedAt", self.resolve_modified_at) + + @staticmethod + def resolve_created_at(entry: TableABC, *_): + return entry.created_at + + @staticmethod + def resolve_modified_at(entry: TableABC, *_): + return entry.modified_at diff --git a/kdb-bot/src/bot_graphql/abc/data_query_with_history_abc.py b/kdb-bot/src/bot_graphql/abc/data_query_with_history_abc.py new file mode 100644 index 00000000..71ec3318 --- /dev/null +++ b/kdb-bot/src/bot_graphql/abc/data_query_with_history_abc.py @@ -0,0 +1,42 @@ +from typing import Type + +from cpl_core.database.context import DatabaseContextABC +from cpl_query.extension import List + +from bot_data.abc.history_table_abc import HistoryTableABC +from bot_data.abc.table_with_id_abc import TableWithIdABC +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class DataQueryWithHistoryABC(DataQueryABC): + def __init__( + self, + name: str, + table_name: str, + history_type: Type[HistoryTableABC], + db: DatabaseContextABC, + ): + self._table_name = table_name + self._history_type = history_type + self._db = db + + DataQueryABC.__init__(self, name) + + self.set_field("history", self.resolve_history) + + def resolve_history(self, entry: TableWithIdABC, *_): + history = List(self._history_type) + + results = self._db.select( + f""" + SELECT * + FROM {self._table_name} + WHERE Id = {entry.id} + ORDER BY DateTo DESC; + """ + ) + + for result in results: + history.add(self._history_type(*result[1:], result[0])) + + return history diff --git a/kdb-bot/src/bot_graphql/abc/filter_abc.py b/kdb-bot/src/bot_graphql/abc/filter_abc.py new file mode 100644 index 00000000..e0d5ff8d --- /dev/null +++ b/kdb-bot/src/bot_graphql/abc/filter_abc.py @@ -0,0 +1,54 @@ +import functools +from abc import ABC, abstractmethod +from inspect import signature, Parameter + +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_query.extension import List + + +class FilterABC(ABC): + def __init__(self): + ABC.__init__(self) + + @abstractmethod + def from_dict(self, values: dict): + pass + + @abstractmethod + def filter(self, query: List, *args) -> List: + pass + + @staticmethod + @ServiceProviderABC.inject + def get_filter(f, values: dict, services: ServiceProviderABC): + sig = signature(f) + for param in sig.parameters.items(): + parameter = param[1] + if parameter.name == "self" or parameter.name == "cls" or parameter.annotation == Parameter.empty: + continue + + if issubclass(parameter.annotation, FilterABC): + filter = services.get_service(parameter.annotation) + filter.from_dict(values) + return filter @ staticmethod + + @staticmethod + @ServiceProviderABC.inject + def get_collection_filter(filter_type: type, values: dict, services: ServiceProviderABC): + filter: FilterABC = services.get_service(filter_type) + filter.from_dict(values) + return filter + + @classmethod + def resolve_filter_annotation(cls, f=None): + if f is None: + return functools.partial(cls.resolve_filter_annotation) + + @functools.wraps(f) + def decorator(*args, **kwargs): + if "filter" in kwargs: + kwargs["filter"] = cls.get_filter(f, kwargs["filter"]) + + return f(*args, **kwargs) + + return decorator diff --git a/kdb-bot/src/bot_graphql/abc/history_query_abc.py b/kdb-bot/src/bot_graphql/abc/history_query_abc.py new file mode 100644 index 00000000..b60541cd --- /dev/null +++ b/kdb-bot/src/bot_graphql/abc/history_query_abc.py @@ -0,0 +1,10 @@ +from bot_graphql.abc.query_abc import QueryABC + + +class HistoryQueryABC(QueryABC): + def __init__(self, name: str): + QueryABC.__init__(self, f"{name}History") + + self.set_field("deleted", lambda x, *_: x.deleted) + self.set_field("dateFrom", lambda x, *_: x.date_from) + self.set_field("dateTo", lambda x, *_: x.date_to) diff --git a/kdb-bot/src/bot_graphql/abc/query_abc.py b/kdb-bot/src/bot_graphql/abc/query_abc.py new file mode 100644 index 00000000..5115cbfa --- /dev/null +++ b/kdb-bot/src/bot_graphql/abc/query_abc.py @@ -0,0 +1,199 @@ +from typing import Callable + +from ariadne import ObjectType +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_api.exception.service_error_code_enum import ServiceErrorCode +from bot_api.exception.service_exception import ServiceException +from bot_api.route.route import Route +from bot_data.model.auth_role_enum import AuthRoleEnum +from bot_data.model.auth_user import AuthUser +from bot_data.model.auto_role import AutoRole +from bot_data.model.auto_role_rule import AutoRoleRule +from bot_data.model.client import Client +from bot_data.model.known_user import KnownUser +from bot_data.model.level import Level +from bot_data.model.server import Server +from bot_data.model.user import User +from bot_data.model.user_joined_game_server import UserJoinedGameServer +from bot_data.model.user_joined_server import UserJoinedServer +from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.filter_abc import FilterABC +from bot_graphql.filter.page import Page +from bot_graphql.filter.sort import Sort +from modules.permission.service.permission_service import PermissionService + + +class QueryABC(ObjectType): + __abstract__ = True + + def __init__(self, name: str): + ObjectType.__init__(self, name) + + def add_collection(self, name: str, get_collection: Callable, filter_type: type = None): + def wrapper(*args, **kwargs): + if filter_type is not None and "filter" in kwargs: + kwargs["filter"] = FilterABC.get_collection_filter(filter_type, kwargs["filter"]) + else: + kwargs["filter"] = None + + if "page" in kwargs: + page = Page() + page.from_dict(kwargs["page"]) + kwargs["page"] = page + + if "sort" in kwargs: + sort = Sort() + sort.from_dict(kwargs["sort"]) + kwargs["sort"] = sort + + collection: List = get_collection(*args) + user = Route.get_user() + + if user == "system" or user.auth_role == AuthRoleEnum.admin: + return self._resolve_collection(collection, *args, **kwargs) + + for x in collection.to_list(): + if not self._can_user_see_element(user, x): + collection.remove(x) + + return self._resolve_collection(collection, *args, **kwargs) + + self.set_field(f"{name}s", wrapper) + self.set_field(f"{name}Count", lambda *args: wrapper(*args).count()) + + @ServiceProviderABC.inject + def _can_user_see_element(self, user: AuthUser, element, services: ServiceProviderABC) -> bool: + permissions: PermissionService = services.get_service(PermissionService) + bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) + + access = False + if type(element) == AutoRole: + element: AutoRole = element + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if permissions.is_member_moderator(member) and u.server.id == element.server.id: + access = True + break + + elif type(element) == AutoRoleRule: + element: AutoRole = element + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if permissions.is_member_moderator(member) and u.server.id == element.server.id: + access = True + break + + elif type(element) == Client: + for u in user.users: + u: User = u + if u.server.id == element.server.id: + access = True + break + + elif type(element) == KnownUser: + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if permissions.is_member_moderator(member): + access = True + break + + elif type(element) == Level: + for u in user.users: + u: User = u + if u.server.id == element.server.id: + access = True + break + + elif type(element) == Server: + for u in user.users: + u: User = u + if u.server.id == element.id: + access = True + break + + elif type(element) == User: + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if u.id == element.id or permissions.is_member_moderator(member): + access = True + break + + elif type(element) == UserJoinedServer: + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if u.id == element.id or permissions.is_member_moderator(member): + access = True + break + + elif type(element) == UserJoinedVoiceChannel: + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if u.id == element.id or permissions.is_member_moderator(member): + access = True + break + + elif type(element) == UserJoinedGameServer: + for u in user.users: + u: User = u + guild = bot.get_guild(u.server.discord_id) + member = guild.get_member(u.discord_id) + if u.id == element.id or permissions.is_member_moderator(member): + access = True + break + + return access + + @ServiceProviderABC.inject + def _can_user_mutate_data(self, server: Server, permission: UserRoleEnum, services: ServiceProviderABC): + permissions: PermissionService = services.get_service(PermissionService) + bot: DiscordBotServiceABC = services.get_service(DiscordBotServiceABC) + + auth_user = Route.get_user() + if auth_user == "system" or auth_user.auth_role == AuthRoleEnum.admin: + return + + member = bot.get_guild(server.discord_id).get_member( + auth_user.users.where(lambda x: x.server.id == server.id).single().discord_id + ) + + check_perm = lambda x: True + match permission: + case UserRoleEnum.moderator: + check_perm = lambda x: permissions.is_member_moderator(x) + case UserRoleEnum.admin: + check_perm = lambda x: permissions.is_member_admin(x) + case UserRoleEnum.technician: + check_perm = lambda x: permissions.is_member_technician(x) + + if not check_perm(member): + ex = ServiceException(ServiceErrorCode.Forbidden, f"User not allowed to mutate data") + raise ex + + # @FilterABC.resolve_filter_annotation + def _resolve_collection(self, collection: List, *_, filter: FilterABC = None, page: Page = None, sort: Sort = None): + if filter is not None: + collection = filter.filter(collection) + + if sort is not None: + collection = sort.filter(collection) + + if page is not None: + collection = page.filter(collection) + + return collection diff --git a/kdb-bot/src/bot_graphql/bot-graphql.json b/kdb-bot/src/bot_graphql/bot-graphql.json new file mode 100644 index 00000000..880ed834 --- /dev/null +++ b/kdb-bot/src/bot_graphql/bot-graphql.json @@ -0,0 +1,44 @@ +{ + "ProjectSettings": { + "Name": "bot-data", + "Version": { + "Major": "1", + "Minor": "0", + "Micro": "0" + }, + "Author": "Sven Heidemann", + "AuthorEmail": "sven.heidemann@sh-edraft.de", + "Description": "Keksdose bot - graphql", + "LongDescription": "Discord bot for the Keksdose discord Server - graphql package", + "URL": "https://www.sh-edraft.de", + "CopyrightDate": "2023", + "CopyrightName": "sh-edraft.de", + "LicenseName": "MIT", + "LicenseDescription": "MIT, see LICENSE for more details.", + "Dependencies": [ + "cpl-core>=1.0.0" + ], + "DevDependencies": [ + "cpl-cli>=1.0.0" + ], + "PythonVersion": ">=3.10.4", + "PythonPath": {}, + "Classifiers": [] + }, + "BuildSettings": { + "ProjectType": "library", + "SourcePath": "", + "OutputPath": "../../dist", + "Main": "", + "EntryPoint": "", + "IncludePackageData": false, + "Included": [], + "Excluded": [ + "*/__pycache__", + "*/logs", + "*/tests" + ], + "PackageData": {}, + "ProjectReferences": [] + } +} \ No newline at end of file diff --git a/kdb-bot/src/bot_api/controller/discord/__init__.py b/kdb-bot/src/bot_graphql/filter/__init__.py similarity index 75% rename from kdb-bot/src/bot_api/controller/discord/__init__.py rename to kdb-bot/src/bot_graphql/filter/__init__.py index f5741907..7b606218 100644 --- a/kdb-bot/src/bot_api/controller/discord/__init__.py +++ b/kdb-bot/src/bot_graphql/filter/__init__.py @@ -11,11 +11,11 @@ Discord bot for the Keksdose discord Server """ -__title__ = "bot_api.controller.discord" +__title__ = "bot_graphql.filter" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_graphql/filter/auto_role_filter.py b/kdb-bot/src/bot_graphql/filter/auto_role_filter.py new file mode 100644 index 00000000..6f17dd59 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/auto_role_filter.py @@ -0,0 +1,66 @@ +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.auto_role import AutoRole +from bot_graphql.abc.filter_abc import FilterABC + + +class AutoRoleFilter(FilterABC): + def __init__( + self, + bot: DiscordBotServiceABC, + ): + FilterABC.__init__(self) + + self._bot = bot + + self._id = None + self._channel_id = None + self._channel_name = None + self._message_id = None + self._server = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "channelId" in values: + self._channel_id = int(values["channelId"]) + + if "channelName" in values: + self._channel_name = values["channelName"] + + if "messageId" in values: + self._message_id = int(values["messageId"]) + + if "server" in values: + from bot_graphql.filter.server_filter import ServerFilter + + server = ServerFilter() + server.from_dict(values["server"]) + self._server = server + + def filter(self, query: List[AutoRole]) -> List[AutoRole]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._channel_id is not None: + query = query.where( + lambda x: x.discord_channel_id == self._channel_id or str(self._channel_id) in str(x.discord_channel_id) + ) + + if self._channel_name is not None: + query = query.where( + lambda x: x.discord_channel_name == self._channel_name or self._channel_name in x.discord_channel_name + ) + + if self._message_id is not None: + query = query.where( + lambda x: x.discord_message_id == self._message_id or str(self._message_id) in str(x.discord_message_id) + ) + + if self._server is not None: + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py b/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py new file mode 100644 index 00000000..b9571d8f --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/auto_role_rule_filter.py @@ -0,0 +1,63 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.auto_role_rule import AutoRoleRule +from bot_graphql.abc.filter_abc import FilterABC + + +class AutoRoleRuleFilter(FilterABC): + def __init__(self, services: ServiceProviderABC, bot: DiscordBotServiceABC): + FilterABC.__init__(self) + self._services = services + self._bot = bot + + self._id = None + self._emoji_name = None + self._role_id = None + self._role_name = None + self._auto_role = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "emojiName" in values: + self._emoji_name = values["emojiName"] + + if "roleId" in values: + self._role_id = int(values["roleId"]) + + if "roleName" in values: + self._role_name = values["roleName"] + + if "autoRole" in values: + from bot_graphql.filter.auto_role_filter import AutoRoleFilter + + self._auto_role: AutoRoleFilter = self._services.get_service(AutoRoleFilter) + self._auto_role.from_dict(values["auto_role"]) + + def filter(self, query: List[AutoRoleRule]) -> List[AutoRoleRule]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._emoji_name is not None: + query = query.where(lambda x: x.emoji_name == self._emoji_name) + + if self._role_id is not None: + query = query.where(lambda x: x.role_id == self._role_id) + + if self._role_name is not None and self._role_id is not None: + + def get_role_name(x: AutoRoleRule): + guild = self._bot.get_guild(x.auto_role.server.discord_id) + name = guild.get_role(x.role_id).name + return name == self._role_name or self._role_name in name + + query = query.where(get_role_name) + + if self._auto_role is not None: + auto_roles = self._auto_role.filter(query.select(lambda x: x.game_server)).select(lambda x: x.id) + query = query.where(lambda x: x.game_server.id in auto_roles) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/client_filter.py b/kdb-bot/src/bot_graphql/filter/client_filter.py new file mode 100644 index 00000000..29563600 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/client_filter.py @@ -0,0 +1,47 @@ +from cpl_query.extension import List + +from bot_data.model.client import Client +from bot_graphql.abc.filter_abc import FilterABC + + +class ClientFilter(FilterABC): + def __init__(self): + FilterABC.__init__(self) + + self._id = None + self._discord_id = None + self._name = None + self._server = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "discordId" in values: + self._id = int(values["discordId"]) + + if "name" in values: + self._name = values["name"] + + if "server" in values: + from bot_graphql.filter.server_filter import ServerFilter + + server = ServerFilter() + server.from_dict(values["server"]) + self._server = server + + def filter(self, query: List[Client]) -> List[Client]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._discord_id is not None: + query = query.where(lambda x: x.id == self._discord_id) + + if self._name is not None: + query = query.where(lambda x: self._name.lower() == x.name.lower() or self._name.lower() in x.name.lower()) + + if self._server is not None: + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/level_filter.py b/kdb-bot/src/bot_graphql/filter/level_filter.py new file mode 100644 index 00000000..2ded4ad8 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/level_filter.py @@ -0,0 +1,42 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_query.extension import List + +from bot_data.model.level import Level +from bot_graphql.abc.filter_abc import FilterABC + + +class LevelFilter(FilterABC): + def __init__(self, services: ServiceProviderABC): + FilterABC.__init__(self) + + self._services = services + + self._id = None + self._name = None + self._server = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "name" in values: + self._name = values["name"] + + if "server" in values: + from bot_graphql.filter.server_filter import ServerFilter + + self._server: ServerFilter = self._services.get_service(ServerFilter) + self._server.from_dict(values["server"]) + + def filter(self, query: List[Level]) -> List[Level]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._name is not None: + query = query.where(lambda x: self._name.lower() == x.name.lower() or self._name.lower() in x.name.lower()) + + if self._server is not None: + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/page.py b/kdb-bot/src/bot_graphql/filter/page.py new file mode 100644 index 00000000..b54080c9 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/page.py @@ -0,0 +1,25 @@ +from cpl_query.extension import List + +from bot_graphql.abc.filter_abc import FilterABC + + +class Page(FilterABC): + def __init__(self): + FilterABC.__init__(self) + self._page_index = None + self._page_size = None + + def from_dict(self, values: dict): + if "pageIndex" in values: + self._page_index = int(values["pageIndex"]) + + if "pageSize" in values: + self._page_size = int(values["pageSize"]) + + def filter(self, query: List, *args) -> List: + if self._page_size is not None and self._page_index is not None: + skip = self._page_size * self._page_index + result = query.skip(skip).take(self._page_size) + return result + + return query diff --git a/kdb-bot/src/bot_graphql/filter/server_filter.py b/kdb-bot/src/bot_graphql/filter/server_filter.py new file mode 100644 index 00000000..e090323e --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/server_filter.py @@ -0,0 +1,48 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.container import Guild +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.server import Server +from bot_graphql.abc.filter_abc import FilterABC + + +class ServerFilter(FilterABC): + def __init__(self): + FilterABC.__init__(self) + + self._id = None + self._discord_id = None + self._name = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "discordId" in values: + self._discord_id = int(values["discordId"]) + + if "name" in values: + self._name = values["name"] + + @ServiceProviderABC.inject + def filter(self, query: List[Server], bot: DiscordBotServiceABC) -> List[Server]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._discord_id is not None: + query = query.where( + lambda x: x.discord_id == self._discord_id or str(self._discord_id) in str(x.discord_id) + ) + + if self._name is not None: + + def where_guild(x: Guild): + guild = bot.get_guild(x.discord_id) + return guild is not None and ( + self._name.lower() == guild.name.lower() or self._name.lower() in guild.name.lower() + ) + + query = query.where(where_guild) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/sort.py b/kdb-bot/src/bot_graphql/filter/sort.py new file mode 100644 index 00000000..5901987e --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/sort.py @@ -0,0 +1,46 @@ +import functools + +from cpl_core.utils import String +from cpl_query.extension import List + +from bot_graphql.abc.filter_abc import FilterABC + + +class Sort(FilterABC): + def __init__(self): + FilterABC.__init__(self) + + self._sort_direction = None + self._sort_column = None + + def from_dict(self, values: dict): + if "sortDirection" in values: + self._sort_direction = values["sortDirection"] + + if "sortColumn" in values: + self._sort_column = values["sortColumn"] + + @staticmethod + def _rgetattr(obj, attr, *args): + def _getattr(obj, attr): + return getattr(obj, attr, *args) + + return functools.reduce(_getattr, [obj] + attr.split(".")) + + def _by_column(self, x): + atr = self._rgetattr(x, String.convert_to_snake_case(self._sort_column), None) + if atr is None: + return "" + return atr + + def filter(self, query: List, *args) -> List: + if self._sort_column is None: + return query + + match self._sort_direction.lower() if self._sort_direction is not None else "ASC": + case "asc": + query = query.order_by(self._by_column) + case "desc": + query = query.order_by_descending(self._by_column) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/user_filter.py b/kdb-bot/src/bot_graphql/filter/user_filter.py new file mode 100644 index 00000000..53c130d5 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/user_filter.py @@ -0,0 +1,110 @@ +from typing import Optional + +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC +from bot_data.model.user import User +from bot_graphql.abc.filter_abc import FilterABC +from bot_graphql.filter.level_filter import LevelFilter +from modules.level.service.level_service import LevelService + + +class UserFilter(FilterABC): + def __init__( + self, + services: ServiceProviderABC, + bot: DiscordBotServiceABC, + client_utils: ClientUtilsABC, + levels: LevelService, + user_joined_servers: UserJoinedServerRepositoryABC, + ): + FilterABC.__init__(self) + + self._services = services + self._bot = bot + self._client_utils = client_utils + self._levels = levels + self._user_joined_servers = user_joined_servers + + self._id = None + self._discord_id = None + self._name = None + self._xp = None + self._ontime = None + self._level: Optional[LevelFilter] = None + self._server = None + self._left_server = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "discordId" in values: + self._discord_id = int(values["discordId"]) + + if "name" in values: + self._name = values["name"] + + if "xp" in values: + self._xp = int(values["xp"]) + + if "ontime" in values: + self._ontime = int(values["ontime"]) + + if "level" in values: + self._level: LevelFilter = self._services.get_service(LevelFilter) + self._level.from_dict(values["level"]) + + if "server" in values: + from bot_graphql.filter.server_filter import ServerFilter + + self._server: ServerFilter = self._services.get_service(ServerFilter) + self._server.from_dict(values["server"]) + + if "leftServer" in values: + self._left_server = values["leftServer"] + + def filter(self, query: List[User]) -> List[User]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._discord_id is not None: + query = query.where( + lambda x: x.discord_id == self._discord_id or str(self._discord_id) in str(x.discord_id) + ) + + if self._name is not None: + + def _get_member(user: User): + guild = self._bot.get_guild(user.server.discord_id) + member = guild.get_member(user.discord_id) + return member is not None and (member.name == self._name or self._name in member.name) + + query = query.where(_get_member) + + if self._xp is not None: + query = query.where(lambda x: x.xp == self._xp) + + if self._ontime is not None: + query = query.where(lambda x: self._client_utils.get_ontime_for_user(x) == self._ontime) + + if self._level is not None: + levels = self._level.filter(query.select(lambda x: self._levels.get_level(x))).select(lambda x: x.id) + query = query.where(lambda x: self._levels.get_level(x).id in levels) + + if self._server is not None: + servers = self._server.filter(query.select(lambda x: x.server)).select(lambda x: x.id) + query = query.where(lambda x: x.server.id in servers) + + if self._left_server is not None: + + def _has_user_left_server(user: User): + active_join = self._user_joined_servers.find_active_user_joined_server_by_user_id(user.id) + return (active_join is None) == self._left_server + + query = query.where(_has_user_left_server) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py b/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py new file mode 100644 index 00000000..1d266a70 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/user_joined_game_server_filter.py @@ -0,0 +1,48 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.user_joined_game_server import UserJoinedGameServer +from bot_graphql.abc.filter_abc import FilterABC + + +class UserJoinedGameServerFilter(FilterABC): + def __init__( + self, + services: ServiceProviderABC, + bot: DiscordBotServiceABC, + ): + FilterABC.__init__(self) + + self._services = services + self._bot = bot + + self._id = None + self._game_server = None + self._user = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "gameServer" in values: + self._game_server = values["gameServer"] + + if "user" in values: + from bot_graphql.filter.user_filter import UserFilter + + self._user: UserFilter = self._services.get_service(UserFilter) + self._user.from_dict(values["user"]) + + def filter(self, query: List[UserJoinedGameServer]) -> List[UserJoinedGameServer]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._game_server is not None: + query = query.where(lambda x: x.game_server == self._game_server) + + if self._user is not None: + users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) + query = query.where(lambda x: x.user.id in users) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py b/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py new file mode 100644 index 00000000..3aac7e25 --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/user_joined_server_filter.py @@ -0,0 +1,55 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.user_joined_server import UserJoinedServer +from bot_graphql.abc.filter_abc import FilterABC + + +class UserJoinedServerFilter(FilterABC): + def __init__( + self, + services: ServiceProviderABC, + bot: DiscordBotServiceABC, + ): + FilterABC.__init__(self) + + self._services = services + self._bot = bot + + self._id = None + self._user = None + self._joined_on = None + self._leaved_on = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "user" in values: + from bot_graphql.filter.user_filter import UserFilter + + self._user: UserFilter = self._services.get_service(UserFilter) + self._user.from_dict(values["user"]) + + if "joinedOn" in values: + self._joined_on = values["joinedOn"] + + if "leavedOn" in values: + self._leaved_on = values["leavedOn"] + + def filter(self, query: List[UserJoinedServer]) -> List[UserJoinedServer]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._user is not None: + users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) + query = query.where(lambda x: x.user.id in users) + + if self._joined_on is not None: + query = query.where(lambda x: x.joined_on == self._joined_on or self._joined_on in x.joined_on) + + if self._leaved_on is not None: + query = query.where(lambda x: x.leaved_on == self._leaved_on or self._leaved_on in x.leaved_on) + + return query diff --git a/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py b/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py new file mode 100644 index 00000000..51ba446a --- /dev/null +++ b/kdb-bot/src/bot_graphql/filter/user_joined_voice_channel_filter.py @@ -0,0 +1,74 @@ +from cpl_core.dependency_injection import ServiceProviderABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_query.extension import List + +from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_graphql.abc.filter_abc import FilterABC + + +class UserJoinedVoiceChannelFilter(FilterABC): + def __init__( + self, + services: ServiceProviderABC, + bot: DiscordBotServiceABC, + ): + FilterABC.__init__(self) + + self._services = services + self._bot = bot + + self._id = None + self._channel_id = None + self._channel_name = None + self._user = None + self._joined_on = None + self._leaved_on = None + + def from_dict(self, values: dict): + if "id" in values: + self._id = int(values["id"]) + + if "channelId" in values: + self._channel_id = int(values["channelId"]) + + if "channelName" in values: + self._channel_name = values["channelName"] + + if "user" in values: + from bot_graphql.filter.user_filter import UserFilter + + self._user: UserFilter = self._services.get_service(UserFilter) + self._user.from_dict(values["user"]) + + if "joinedOn" in values: + self._joined_on = values["joinedOn"] + + if "leavedOn" in values: + self._leaved_on = values["leavedOn"] + + def filter(self, query: List[UserJoinedVoiceChannel]) -> List[UserJoinedVoiceChannel]: + if self._id is not None: + query = query.where(lambda x: x.id == self._id) + + if self._channel_id is not None: + query = query.where(lambda x: x.channel_id == self._channel_id) + + if self._channel_name is not None and self._channel_id is not None: + + def get_channel_name(x: UserJoinedVoiceChannel): + name = self._bot.get_channel(x.channel_id).name + return name == self._channel_name or self._channel_name in name + + query = query.where(get_channel_name) + + if self._user is not None: + users = self._user.filter(query.select(lambda x: x.user)).select(lambda x: x.id) + query = query.where(lambda x: x.user.id in users) + + if self._joined_on is not None: + query = query.where(lambda x: x.joined_on == self._joined_on or self._joined_on in x.joined_on) + + if self._leaved_on is not None: + query = query.where(lambda x: x.leaved_on == self._leaved_on or self._leaved_on in x.leaved_on) + + return query diff --git a/kdb-bot/src/bot_graphql/graphql_module.py b/kdb-bot/src/bot_graphql/graphql_module.py new file mode 100644 index 00000000..5ef7df09 --- /dev/null +++ b/kdb-bot/src/bot_graphql/graphql_module.py @@ -0,0 +1,104 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.dependency_injection import ServiceCollectionABC +from cpl_core.environment import ApplicationEnvironmentABC +from cpl_discord.service.discord_collection_abc import DiscordCollectionABC + +from bot_core.abc.module_abc import ModuleABC +from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_data.service.seeder_service import SeederService +from bot_graphql.abc.filter_abc import FilterABC +from bot_graphql.abc.query_abc import QueryABC +from bot_graphql.filter.auto_role_filter import AutoRoleFilter +from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter +from bot_graphql.filter.client_filter import ClientFilter +from bot_graphql.filter.level_filter import LevelFilter +from bot_graphql.filter.server_filter import ServerFilter +from bot_graphql.filter.user_filter import UserFilter +from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter +from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter +from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter +from bot_graphql.graphql_service import GraphQLService +from bot_graphql.mutation import Mutation +from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation +from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation +from bot_graphql.mutations.level_mutation import LevelMutation +from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation +from bot_graphql.mutations.user_mutation import UserMutation +from bot_graphql.queries.auto_role_history_query import AutoRoleHistoryQuery +from bot_graphql.queries.auto_role_query import AutoRoleQuery +from bot_graphql.queries.auto_role_rule_history_query import AutoRoleRuleHistoryQuery +from bot_graphql.queries.auto_role_rule_query import AutoRoleRuleQuery +from bot_graphql.queries.client_history_query import ClientHistoryQuery +from bot_graphql.queries.client_query import ClientQuery +from bot_graphql.queries.known_user_history_query import KnownUserHistoryQuery +from bot_graphql.queries.known_user_query import KnownUserQuery +from bot_graphql.queries.level_history_query import LevelHistoryQuery +from bot_graphql.queries.level_query import LevelQuery +from bot_graphql.queries.server_history_query import ServerHistoryQuery +from bot_graphql.queries.server_query import ServerQuery +from bot_graphql.queries.user_history_query import UserHistoryQuery +from bot_graphql.queries.user_joined_game_server_history_query import UserJoinedGameServerHistoryQuery +from bot_graphql.queries.user_joined_game_server_query import UserJoinedGameServerQuery +from bot_graphql.queries.user_joined_server_history_query import UserJoinedServerHistoryQuery +from bot_graphql.queries.user_joined_server_query import UserJoinedServerQuery +from bot_graphql.queries.user_joined_voice_channel_history_query import UserJoinedVoiceChannelHistoryQuery +from bot_graphql.queries.user_joined_voice_channel_query import UserJoinedVoiceChannelQuery +from bot_graphql.queries.user_query import UserQuery +from bot_graphql.query import Query +from bot_graphql.schema import Schema + + +class GraphQLModule(ModuleABC): + def __init__(self, dc: DiscordCollectionABC): + ModuleABC.__init__(self, dc, FeatureFlagsEnum.data_module) + + def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): + pass + + def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services.add_singleton(Schema) + services.add_singleton(GraphQLService) + services.add_singleton(Query) + services.add_singleton(Mutation) + + # queries + services.add_transient(QueryABC, AutoRoleHistoryQuery) + services.add_transient(QueryABC, AutoRoleQuery) + services.add_transient(QueryABC, AutoRoleRuleHistoryQuery) + services.add_transient(QueryABC, AutoRoleRuleQuery) + services.add_transient(QueryABC, ClientHistoryQuery) + services.add_transient(QueryABC, ClientQuery) + services.add_transient(QueryABC, KnownUserHistoryQuery) + services.add_transient(QueryABC, KnownUserQuery) + services.add_transient(QueryABC, LevelHistoryQuery) + services.add_transient(QueryABC, LevelQuery) + services.add_transient(QueryABC, ServerHistoryQuery) + services.add_transient(QueryABC, ServerQuery) + services.add_transient(QueryABC, UserHistoryQuery) + services.add_transient(QueryABC, UserQuery) + services.add_transient(QueryABC, UserJoinedServerHistoryQuery) + services.add_transient(QueryABC, UserJoinedServerQuery) + services.add_transient(QueryABC, UserJoinedVoiceChannelHistoryQuery) + services.add_transient(QueryABC, UserJoinedVoiceChannelQuery) + services.add_transient(QueryABC, UserJoinedGameServerHistoryQuery) + services.add_transient(QueryABC, UserJoinedGameServerQuery) + + # filters + services.add_transient(FilterABC, AutoRoleFilter) + services.add_transient(FilterABC, AutoRoleRuleFilter) + services.add_transient(FilterABC, ClientFilter) + services.add_transient(FilterABC, LevelFilter) + services.add_transient(FilterABC, ServerFilter) + services.add_transient(FilterABC, UserFilter) + services.add_transient(FilterABC, UserJoinedServerFilter) + services.add_transient(FilterABC, UserJoinedVoiceChannelFilter) + services.add_transient(FilterABC, UserJoinedGameServerFilter) + + # mutations + services.add_transient(QueryABC, AutoRoleMutation) + services.add_transient(QueryABC, AutoRoleRuleMutation) + services.add_transient(QueryABC, LevelMutation) + services.add_transient(QueryABC, UserMutation) + services.add_transient(QueryABC, UserJoinedGameServerMutation) + + services.add_transient(SeederService) diff --git a/kdb-bot/src/bot_graphql/graphql_service.py b/kdb-bot/src/bot_graphql/graphql_service.py new file mode 100644 index 00000000..699b57c6 --- /dev/null +++ b/kdb-bot/src/bot_graphql/graphql_service.py @@ -0,0 +1,6 @@ +from bot_graphql.abc.query_abc import QueryABC + + +class GraphQLService: + def __init__(self, queries: list[QueryABC]): + self._queries = queries diff --git a/kdb-bot/src/bot_graphql/model/autoRole.gql b/kdb-bot/src/bot_graphql/model/autoRole.gql new file mode 100644 index 00000000..e859a364 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/autoRole.gql @@ -0,0 +1,49 @@ +type AutoRole implements TableWithHistoryQuery { + id: ID + channelId: String + channelName: String + messageId: String + + server: Server + + autoRoleRuleCount: Int + autoRoleRules(filter: AutoRoleRuleFilter, page: Page, sort: Sort): [AutoRoleRule] + + createdAt: String + modifiedAt: String + + history: [AutoRoleHistory] +} + +type AutoRoleHistory implements HistoryTableQuery { + id: ID + channelId: String + messageId: String + + server: ID + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input AutoRoleFilter { + id: ID + channelId: String + channelName: String + messageId: String + server: ServerFilter +} + +type AutoRoleMutation { + createAutoRole(input: AutoRoleInput!): AutoRole + updateAutoRole(input: AutoRoleInput!): AutoRole + deleteAutoRole(id: ID): AutoRole +} + +input AutoRoleInput { + id: ID + channelId: String + messageId: String + serverId: ID +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/autoRoleRule.gql b/kdb-bot/src/bot_graphql/model/autoRoleRule.gql new file mode 100644 index 00000000..2008424e --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/autoRoleRule.gql @@ -0,0 +1,46 @@ +type AutoRoleRule implements TableWithHistoryQuery { + id: ID + emojiName: String + roleId: String + roleName: String + + autoRole: AutoRole + + createdAt: String + modifiedAt: String + + history: [AutoRoleRuleHistory] +} + +type AutoRoleRuleHistory implements HistoryTableQuery { + id: ID + emojiName: String + roleId: String + + autoRole: ID + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input AutoRoleRuleFilter { + id: ID + emojiName: String + roleId: String + roleName: String + autoRole: AutoRoleFilter +} + +type AutoRoleRuleMutation { + createAutoRoleRule(input: AutoRoleRuleInput!): AutoRoleRule + updateAutoRoleRule(input: AutoRoleRuleInput!): AutoRoleRule + deleteAutoRoleRule(id: ID): AutoRoleRule +} + +input AutoRoleRuleInput { + id: ID + emojiName: String + roleId: String + autoRoleId: ID +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/base.gql b/kdb-bot/src/bot_graphql/model/base.gql new file mode 100644 index 00000000..2e664a4d --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/base.gql @@ -0,0 +1,31 @@ +interface TableQuery { + createdAt: String + modifiedAt: String +} + +interface TableWithHistoryQuery { + createdAt: String + modifiedAt: String + history: [HistoryTableQuery] +} + +interface HistoryTableQuery { + deleted: Boolean + dateFrom: String + dateTo: String +} + +input Page { + pageIndex: Int + pageSize: Int +} + +input Sort { + sortDirection: SortDirection + sortColumn: String +} + +enum SortDirection { + ASC + DESC +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/client.gql b/kdb-bot/src/bot_graphql/model/client.gql new file mode 100644 index 00000000..58a805b9 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/client.gql @@ -0,0 +1,41 @@ +type Client implements TableQuery { + id: ID + discordId: String + name: String + sentMessageCount: Int + receivedMessageCount: Int + deletedMessageCount: Int + receivedCommandCount: Int + movedUsersCount: Int + + server: Server + + createdAt: String + modifiedAt: String + + history: [ClientHistory] +} + +type ClientHistory implements HistoryTableQuery { + id: ID + discordId: String + name: String + sentMessageCount: Int + receivedMessageCount: Int + deletedMessageCount: Int + receivedCommandCount: Int + movedUsersCount: Int + + server: ID + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input ClientFilter { + id: ID + discordId: String + name: String + server: ServerFilter +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/discord.gql b/kdb-bot/src/bot_graphql/model/discord.gql new file mode 100644 index 00000000..1218b790 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/discord.gql @@ -0,0 +1,29 @@ +type Guild { + id: ID + name: String + + channels: [Channel] + roles: [Role] + emojis: [Emoji] +} + +input GuildFilter { + id: ID +} + +type Channel { + id: String + name: String + type: String +} + +type Role { + id: String + name: String +} + +type Emoji { + id: String + name: String + url: String +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/knownUser.gql b/kdb-bot/src/bot_graphql/model/knownUser.gql new file mode 100644 index 00000000..fe26dbe4 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/knownUser.gql @@ -0,0 +1,18 @@ +type KnownUser implements TableWithHistoryQuery { + id: ID + discordId: String + + createdAt: String + modifiedAt: String + + history: [KnownUserHistory] +} + +type KnownUserHistory implements HistoryTableQuery { + id: ID + discordId: String + + deleted: Boolean + dateFrom: String + dateTo: String +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/level.gql b/kdb-bot/src/bot_graphql/model/level.gql new file mode 100644 index 00000000..cc937291 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/level.gql @@ -0,0 +1,49 @@ +type Level implements TableWithHistoryQuery { + id: ID + name: String + color: String + minXp: Int + permissions: String + + server: Server + + createdAt: String + modifiedAt: String + + history: [LevelHistory] +} + +type LevelHistory implements HistoryTableQuery { + id: ID + name: String + color: String + minXp: Int + permissions: String + + server: ID + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input LevelFilter { + id: ID + name: String + server: ServerFilter +} + +type LevelMutation { + createLevel(input: LevelInput!): Level + updateLevel(input: LevelInput!): Level + deleteLevel(id: ID): Level +} + +input LevelInput { + id: ID + name: String + color: String + minXp: Int + permissions: String + serverId: ID +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/mutation.gql b/kdb-bot/src/bot_graphql/model/mutation.gql new file mode 100644 index 00000000..9631fd8d --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/mutation.gql @@ -0,0 +1,7 @@ +type Mutation { + autoRole: AutoRoleMutation + autoRoleRule: AutoRoleRuleMutation + level: LevelMutation + user: UserMutation + userJoinedGameServer: UserJoinedGameServerMutation +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/query.gql b/kdb-bot/src/bot_graphql/model/query.gql new file mode 100644 index 00000000..69b5a74a --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/query.gql @@ -0,0 +1,33 @@ +type Query { + autoRoleCount: Int + autoRoles(filter: AutoRoleFilter, page: Page, sort: Sort): [AutoRole] + + autoRoleRuleCount: Int + autoRoleRules(filter: AutoRoleRuleFilter, page: Page, sort: Sort): [AutoRoleRule] + + clientCount: Int + clients(filter: ClientFilter, page: Page, sort: Sort): [Client] + + knownUserCount: Int + knownUsers: [KnownUser] + + levelCount: Int + levels(filter: LevelFilter, page: Page, sort: Sort): [Level] + + serverCount: Int + servers(filter: ServerFilter, page: Page, sort: Sort): [Server] + + userJoinedServerCount: Int + userJoinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer] + + userJoinedVoiceChannelCount: Int + userJoinedVoiceChannels(filter: UserJoinedVoiceChannelFilter, page: Page, sort: Sort): [UserJoinedVoiceChannel] + + userJoinedGameServerCount: Int + userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer] + + userCount: Int + users(filter: UserFilter, page: Page, sort: Sort): [User] + + guilds(filter: GuildFilter): [Guild] +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/server.gql b/kdb-bot/src/bot_graphql/model/server.gql new file mode 100644 index 00000000..db94dc89 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/server.gql @@ -0,0 +1,40 @@ +type Server implements TableWithHistoryQuery { + id: ID + discordId: String + name: String + iconURL: String + + autoRoleCount: Int + autoRoles(filter: AutoRoleFilter, page: Page, sort: Sort): [AutoRole] + + clientCount: Int + clients(filter: ClientFilter, page: Page, sort: Sort): [Client] + + levelCount: Int + levels(filter: LevelFilter, page: Page, sort: Sort): [Level] + + userCount: Int + users(filter: UserFilter, page: Page, sort: Sort): [User] + + createdAt: String + modifiedAt: String + + history: [HistoryTableQuery] +} + +type ServerHistory implements HistoryTableQuery { + id: ID + discordId: String + name: String + iconURL: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input ServerFilter { + id: ID + discordId: String + name: String +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/user.gql b/kdb-bot/src/bot_graphql/model/user.gql new file mode 100644 index 00000000..e7f03f38 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/user.gql @@ -0,0 +1,58 @@ +type User implements TableWithHistoryQuery { + id: ID + discordId: String + name: String + xp: Int + ontime: Float + level: Level + + joinedServers(filter: UserJoinedServerFilter, page: Page, sort: Sort): [UserJoinedServer] + joinedServerCount: Int + + joinedVoiceChannels(filter: UserJoinedVoiceChannelFilter, page: Page, sort: Sort): [UserJoinedVoiceChannel] + joinedVoiceChannelCount: Int + + userJoinedGameServerCount: Int + userJoinedGameServers(filter: UserJoinedGameServerFilter, page: Page, sort: Sort): [UserJoinedGameServer] + + server: Server + leftServer: Boolean + + createdAt: String + modifiedAt: String + + history: [UserHistory] +} + +type UserHistory implements HistoryTableQuery { + id: ID + discordId: String + xp: Int + + server: ID + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input UserFilter { + id: ID + discordId: String + name: String + xp: Int + ontime: Float + level: LevelFilter + server: ServerFilter + leftServer: Boolean +} + +type UserMutation { + updateUser(input: UserInput!): User +} + +input UserInput { + id: ID + xp: Int + levelId: ID +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql b/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql new file mode 100644 index 00000000..93d344a2 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/userJoinedGameServer.gql @@ -0,0 +1,43 @@ +type UserJoinedGameServer implements TableWithHistoryQuery { + id: ID + gameServer: String + user: User + time: Float + joinedOn: String + leavedOn: String + + createdAt: String + modifiedAt: String + + history: [UserJoinedGameServerHistory] +} + +type UserJoinedGameServerHistory implements HistoryTableQuery { + id: ID + gameServer: String + user: ID + time: Float + joinedOn: String + leavedOn: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input UserJoinedGameServerFilter { + id: ID + gameServer: String + user: UserFilter + joinedOn: String + leavedOn: String +} + +type UserJoinedGameServerMutation { + userJoined(input: UserJoinedGameServerInput!): UserJoinedGameServer + userLeft(input: UserJoinedGameServerInput!): UserJoinedGameServer +} + +input UserJoinedGameServerInput { + ident: String! +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/userJoinedServer.gql b/kdb-bot/src/bot_graphql/model/userJoinedServer.gql new file mode 100644 index 00000000..bb73b40d --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/userJoinedServer.gql @@ -0,0 +1,29 @@ +type UserJoinedServer implements TableWithHistoryQuery { + id: ID + user: User + joinedOn: String + leavedOn: String + + createdAt: String + modifiedAt: String + + history: [UserJoinedServerHistory] +} + +type UserJoinedServerHistory implements HistoryTableQuery { + id: ID + user: ID + joinedOn: String + leavedOn: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input UserJoinedServerFilter { + id: ID + user: UserFilter + joinedOn: String + leavedOn: String +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql b/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql new file mode 100644 index 00000000..8cc73e15 --- /dev/null +++ b/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql @@ -0,0 +1,37 @@ +type UserJoinedVoiceChannel implements TableWithHistoryQuery { + id: ID + channelId: String + channelName: String + user: User + time: Float + joinedOn: String + leavedOn: String + + createdAt: String + modifiedAt: String + + history: [UserJoinedVoiceChannelHistory] +} + +type UserJoinedVoiceChannelHistory implements HistoryTableQuery { + id: ID + channelId: String + channelName: String + user: ID + time: Float + joinedOn: String + leavedOn: String + + deleted: Boolean + dateFrom: String + dateTo: String +} + +input UserJoinedVoiceChannelFilter { + id: ID + channelId: String + channelName: String + user: UserFilter + joinedOn: String + leavedOn: String +} \ No newline at end of file diff --git a/kdb-bot/src/bot_graphql/mutation.py b/kdb-bot/src/bot_graphql/mutation.py new file mode 100644 index 00000000..56bfa7c5 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutation.py @@ -0,0 +1,26 @@ +from ariadne import MutationType + +from bot_data.model.user_joined_game_server import UserJoinedGameServer +from bot_graphql.mutations.auto_role_mutation import AutoRoleMutation +from bot_graphql.mutations.auto_role_rule_mutation import AutoRoleRuleMutation +from bot_graphql.mutations.level_mutation import LevelMutation +from bot_graphql.mutations.user_joined_game_server_mutation import UserJoinedGameServerMutation +from bot_graphql.mutations.user_mutation import UserMutation + + +class Mutation(MutationType): + def __init__( + self, + auto_role_mutation: AutoRoleMutation, + auto_role_rule_mutation: AutoRoleRuleMutation, + level_mutation: LevelMutation, + user_mutation: UserMutation, + user_joined_game_server: UserJoinedGameServerMutation, + ): + MutationType.__init__(self) + + self.set_field("autoRole", lambda *_: auto_role_mutation) + self.set_field("autoRoleRule", lambda *_: auto_role_rule_mutation) + self.set_field("level", lambda *_: level_mutation) + self.set_field("user", lambda *_: user_mutation) + self.set_field("userJoinedGameServer", lambda *_: user_joined_game_server) diff --git a/kdb-bot/src/modules/stats/model/__init__.py b/kdb-bot/src/bot_graphql/mutations/__init__.py similarity index 74% rename from kdb-bot/src/modules/stats/model/__init__.py rename to kdb-bot/src/bot_graphql/mutations/__init__.py index 6e59683c..f7d4a378 100644 --- a/kdb-bot/src/modules/stats/model/__init__.py +++ b/kdb-bot/src/bot_graphql/mutations/__init__.py @@ -11,16 +11,16 @@ Discord bot for the Keksdose discord Server """ -__title__ = "modules.stats.model" +__title__ = "bot_graphql.mutations" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple -# imports +# imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py b/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py new file mode 100644 index 00000000..d936fc6e --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/auto_role_mutation.py @@ -0,0 +1,62 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.auto_role import AutoRole +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC + + +class AutoRoleMutation(QueryABC): + def __init__( + self, + servers: ServerRepositoryABC, + auto_roles: AutoRoleRepositoryABC, + db: DatabaseContextABC, + ): + QueryABC.__init__(self, "AutoRoleMutation") + + self._servers = servers + self._auto_roles = auto_roles + self._db = db + + self.set_field("createAutoRole", self.resolve_create_auto_role) + self.set_field("updateAutoRole", self.resolve_update_auto_role) + self.set_field("deleteAutoRole", self.resolve_delete_auto_role) + + def resolve_create_auto_role(self, *_, input: dict): + auto_role = AutoRole(self._servers.get_server_by_id(input["serverId"]), input["channelId"], input["messageId"]) + self._can_user_mutate_data(auto_role.server, UserRoleEnum.moderator) + + self._auto_roles.add_auto_role(auto_role) + self._db.save_changes() + + def get_new(x: AutoRole): + return ( + x.server.id == int(input["serverId"]) + and x.discord_channel_id == int(input["channelId"]) + and x.discord_message_id == int(input["messageId"]) + ) + + return self._auto_roles.get_auto_roles_by_server_id(auto_role.server.id).where(get_new).last() + + def resolve_update_auto_role(self, *_, input: dict): + auto_role = self._auto_roles.get_auto_role_by_id(input["id"]) + self._can_user_mutate_data(auto_role.server, UserRoleEnum.moderator) + + auto_role.discord_channel_id = input["channelId"] if "channelId" in input else auto_role.discord_channel_id + auto_role.discord_message_id = input["messageId"] if "messageId" in input else auto_role.discord_message_id + + self._auto_roles.update_auto_role(auto_role) + self._db.save_changes() + + auto_role = self._auto_roles.get_auto_role_by_id(input["id"]) + return auto_role + + def resolve_delete_auto_role(self, *_, id: int): + auto_role = self._auto_roles.get_auto_role_by_id(id) + self._can_user_mutate_data(auto_role.server, UserRoleEnum.moderator) + + self._auto_roles.delete_auto_role(auto_role) + self._db.save_changes() + return auto_role diff --git a/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py b/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py new file mode 100644 index 00000000..76dce97c --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/auto_role_rule_mutation.py @@ -0,0 +1,64 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.auto_role_rule import AutoRoleRule +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC + + +class AutoRoleRuleMutation(QueryABC): + def __init__( + self, + servers: ServerRepositoryABC, + auto_roles: AutoRoleRepositoryABC, + db: DatabaseContextABC, + ): + QueryABC.__init__(self, "AutoRoleRuleMutation") + + self._servers = servers + self._auto_roles = auto_roles + self._db = db + + self.set_field("createAutoRoleRule", self.resolve_create_auto_role_rule) + self.set_field("updateAutoRoleRule", self.resolve_update_auto_role_rule) + self.set_field("deleteAutoRoleRule", self.resolve_delete_auto_role_rule) + + def resolve_create_auto_role_rule(self, *_, input: dict): + auto_role_rule = AutoRoleRule( + self._auto_roles.get_auto_role_by_id(input["autoRoleId"]), input["emojiName"], input["roleId"] + ) + self._can_user_mutate_data(auto_role_rule.auto_role.server, UserRoleEnum.moderator) + + self._auto_roles.add_auto_role_rule(auto_role_rule) + self._db.save_changes() + + def get_new(x: AutoRoleRule): + return ( + x.auto_role.id == int(input["autoRoleId"]) + and x.emoji_name == input["emojiName"] + and x.role_id == int(input["roleId"]) + ) + + return self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_rule.auto_role.id).where(get_new).last() + + def resolve_update_auto_role_rule(self, *_, input: dict): + auto_role_rule = self._auto_roles.get_auto_role_rule_by_id(input["id"]) + self._can_user_mutate_data(auto_role_rule.auto_role.server, UserRoleEnum.moderator) + + auto_role_rule.emoji_name = input["emojiName"] if "emojiName" in input else auto_role_rule.emoji_name + auto_role_rule.role_id = input["roleId"] if "roleId" in input else auto_role_rule.role_id + + self._auto_roles.update_auto_role_rule(auto_role_rule) + self._db.save_changes() + + auto_role_rule = self._auto_roles.get_auto_role_rule_by_id(input["id"]) + return auto_role_rule + + def resolve_delete_auto_role_rule(self, *_, id: int): + auto_role_rule = self._auto_roles.get_auto_role_rule_by_id(id) + self._can_user_mutate_data(auto_role_rule.auto_role.server, UserRoleEnum.moderator) + + self._auto_roles.delete_auto_role_rule(auto_role_rule) + self._db.save_changes() + return auto_role_rule diff --git a/kdb-bot/src/bot_graphql/mutations/level_mutation.py b/kdb-bot/src/bot_graphql/mutations/level_mutation.py new file mode 100644 index 00000000..47f61e7c --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/level_mutation.py @@ -0,0 +1,82 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.level import Level +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC +from modules.level.level_seeder import LevelSeeder + + +class LevelMutation(QueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + servers: ServerRepositoryABC, + levels: LevelRepositoryABC, + db: DatabaseContextABC, + level_seeder: LevelSeeder, + ): + QueryABC.__init__(self, "LevelMutation") + + self._bot = bot + self._servers = servers + self._levels = levels + self._db = db + self._level_seeder = level_seeder + + self.set_field("createLevel", self.resolve_create_level) + self.set_field("updateLevel", self.resolve_update_level) + self.set_field("deleteLevel", self.resolve_delete_level) + + def resolve_create_level(self, *_, input: dict): + server = self._servers.get_server_by_id(input["serverId"]) + self._can_user_mutate_data(server, UserRoleEnum.admin) + + level = Level( + input["name"], + input["color"], + int(input["minXp"]), + int(input["permissions"]), + server, + ) + self._levels.add_level(level) + self._db.save_changes() + + def get_new_level(l: Level): + return ( + l.name == level.name + and l.color == level.color + and l.min_xp == level.min_xp + and l.permissions == level.permissions + ) + + self._bot.loop.create_task(self._level_seeder.seed()) + return self._levels.get_levels_by_server_id(level.server.id).where(get_new_level).last() + + def resolve_update_level(self, *_, input: dict): + level = self._levels.get_level_by_id(input["id"]) + self._can_user_mutate_data(level.server, UserRoleEnum.admin) + + level.name = input["name"] if "name" in input else level.name + level.color = input["color"] if "color" in input else level.color + level.min_xp = input["minXp"] if "minXp" in input else level.min_xp + level.permissions = input["permissions"] if "permissions" in input else level.permissions + + self._levels.update_level(level) + self._db.save_changes() + + self._bot.loop.create_task(self._level_seeder.seed()) + level = self._levels.get_level_by_id(input["id"]) + return level + + def resolve_delete_level(self, *_, id: int): + level = self._levels.get_level_by_id(id) + self._can_user_mutate_data(level.server, UserRoleEnum.admin) + + self._levels.delete_level(level) + self._db.save_changes() + + self._bot.loop.create_task(self._level_seeder.seed()) + return level diff --git a/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py b/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py new file mode 100644 index 00000000..ae0a5c04 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/user_joined_game_server_mutation.py @@ -0,0 +1,133 @@ +import hashlib +from datetime import datetime +from typing import Optional + +from cpl_core.database.context import DatabaseContextABC +from cpl_core.logging import LoggerABC +from cpl_discord.service import DiscordBotServiceABC +from flask import request + +from bot_api.configuration.authentication_settings import AuthenticationSettings +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC +from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.api_key import ApiKey +from bot_data.model.user_joined_game_server import UserJoinedGameServer +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC +from modules.base.abc.base_helper_abc import BaseHelperABC +from modules.base.configuration.base_server_settings import BaseServerSettings +from modules.permission.service.permission_service import PermissionService + + +class UserJoinedGameServerMutation(QueryABC): + def __init__( + self, + logger: LoggerABC, + base_helper: BaseHelperABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + user_joined_game_servers: UserJoinedGameServerRepositoryABC, + api_keys: ApiKeyRepositoryABC, + game_servers: GameServerRepositoryABC, + user_game_idents: UserGameIdentRepositoryABC, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + permissions: PermissionService, + auth_settings: AuthenticationSettings, + ): + QueryABC.__init__(self, "UserJoinedGameServerMutation") + + self._logger = logger + self._base_helper = base_helper + self._servers = servers + self._users = users + self._user_joined_game_servers = user_joined_game_servers + self._api_keys = api_keys + self._game_servers = game_servers + self._user_game_idents = user_game_idents + self._bot = bot + self._db = db + self._permissions = permissions + self._auth_settings = auth_settings + + self.set_field("userJoined", self.resolve_user_joined) + self.set_field("userLeft", self.resolve_user_left) + + def _get_api_key_str(self, api_key: ApiKey) -> str: + return hashlib.sha256( + f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8") + ).hexdigest() + + def _get_api_key(self) -> Optional[ApiKey]: + authorization = request.headers.get("Authorization").split() + if len(authorization) != 2: + return None + + api_key_str = authorization[1] + return ( + self._api_keys.get_api_keys() + .where(lambda key: self._get_api_key_str(key) == api_key_str) + .first_or_default() + ) + + def resolve_user_joined(self, *_, input: dict): + api_key = self._get_api_key() + if api_key is None: + self._logger.warn(__name__, f"UserJoinedGameServer not saved. Api-Key not available!") + return + + game_server = self._game_servers.get_game_server_by_api_key_id(api_key.id) + game_ident = self._user_game_idents.get_user_game_ident_by_ident(input["ident"]) + user = game_ident.user + self._can_user_mutate_data(user.server, UserRoleEnum.admin) + + active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.id) + if active is not None: + self._logger.debug( + __name__, + f"Skip UserJoinedGameServer for user {user.id}. User already plays on {active.game_server}.", + ) + return + + new = UserJoinedGameServer(user, game_server, datetime.now()) + self._user_joined_game_servers.add_user_joined_game_server(new) + self._db.save_changes() + + return self._user_joined_game_servers.get_active_user_joined_game_server_by_user_id(user.id) + + def resolve_user_left(self, *_, input: dict): + api_key = self._get_api_key() + if api_key is None: + self._logger.warn(__name__, f"UserJoinedGameServer not saved. Api-Key not available!") + return + + game_ident = self._user_game_idents.find_user_game_ident_by_ident(input["ident"]) + if game_ident is None: + return + user = game_ident.user + self._can_user_mutate_data(user.server, UserRoleEnum.admin) + + active = self._user_joined_game_servers.find_active_user_joined_game_server_by_user_id(user.id) + if active is None: + return + active.leaved_on = datetime.now() + + settings: BaseServerSettings = self._base_helper.get_config(user.server.discord_id) + + ontime = round((active.leaved_on - active.joined_on).total_seconds() / 3600, 2) + old_xp = user.xp + user.xp += round(ontime * settings.xp_per_ontime_hour) + + self._user_joined_game_servers.update_user_joined_game_server(active) + self._users.update_user(user) + self._db.save_changes() + self._logger.debug( + __name__, + f"User {user} leaved_on {active.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}", + ) + + return active diff --git a/kdb-bot/src/bot_graphql/mutations/user_mutation.py b/kdb-bot/src/bot_graphql/mutations/user_mutation.py new file mode 100644 index 00000000..c601aab9 --- /dev/null +++ b/kdb-bot/src/bot_graphql/mutations/user_mutation.py @@ -0,0 +1,51 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.user_role_enum import UserRoleEnum +from bot_graphql.abc.query_abc import QueryABC +from modules.level.service.level_service import LevelService +from modules.permission.service.permission_service import PermissionService + + +class UserMutation(QueryABC): + def __init__( + self, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + permissions: PermissionService, + levels: LevelRepositoryABC, + level_service: LevelService, + ): + QueryABC.__init__(self, "UserMutation") + + self._servers = servers + self._users = users + self._bot = bot + self._db = db + self._permissions = permissions + self._levels = levels + self._level_service = level_service + + self.set_field("updateUser", self.resolve_update_user) + + def resolve_update_user(self, *_, input: dict): + user = self._users.get_user_by_id(input["id"]) + self._can_user_mutate_data(user.server, UserRoleEnum.moderator) + + if "levelId" in input: + level = self._levels.get_level_by_id(input["levelId"]) + user.xp = level.min_xp + else: + user.xp = input["xp"] if "xp" in input else user.xp + + self._users.update_user(user) + self._db.save_changes() + self._bot.loop.create_task(self._level_service.set_level(user)) + + user = self._users.get_user_by_id(input["id"]) + return user diff --git a/kdb-bot/src/bot_graphql/queries/__init__.py b/kdb-bot/src/bot_graphql/queries/__init__.py new file mode 100644 index 00000000..442cbe95 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +bot Keksdose bot +~~~~~~~~~~~~~~~~~~~ + +Discord bot for the Keksdose discord Server + +:copyright: (c) 2022 - 2023 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = "bot_graphql.queries" +__author__ = "Sven Heidemann" +__license__ = "MIT" +__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" +__version__ = "1.0.0" + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple("VersionInfo", "major minor micro") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_graphql/queries/auto_role_history_query.py b/kdb-bot/src/bot_graphql/queries/auto_role_history_query.py new file mode 100644 index 00000000..7a96ad1d --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/auto_role_history_query.py @@ -0,0 +1,40 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.auto_role import AutoRole +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class AutoRoleHistoryQuery(HistoryQueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + auto_role_rules: AutoRoleRepositoryABC, + servers: ServerRepositoryABC, + ): + HistoryQueryABC.__init__(self, "AutoRole") + + self._bot = bot + self._auto_role_rules = auto_role_rules + self._servers = servers + + self.set_field("id", self.resolve_id) + self.set_field("channelId", self.resolve_channel_id) + self.set_field("messageId", self.resolve_message_id) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(x: AutoRole, *_): + return x.id + + @staticmethod + def resolve_channel_id(x: AutoRole, *_): + return x.discord_channel_id + + @staticmethod + def resolve_message_id(x: AutoRole, *_): + return x.discord_message_id + + def resolve_server(self, x: AutoRole, *_): + return x.server diff --git a/kdb-bot/src/bot_graphql/queries/auto_role_query.py b/kdb-bot/src/bot_graphql/queries/auto_role_query.py new file mode 100644 index 00000000..aaf694b7 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/auto_role_query.py @@ -0,0 +1,58 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.auto_role import AutoRole +from bot_data.model.auto_role_history import AutoRoleHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC +from bot_graphql.filter.auto_role_filter import AutoRoleFilter +from bot_graphql.filter.server_filter import ServerFilter + + +class AutoRoleQuery(DataQueryWithHistoryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + auto_role_rules: AutoRoleRepositoryABC, + servers: ServerRepositoryABC, + db: DatabaseContextABC, + ): + DataQueryWithHistoryABC.__init__(self, "AutoRole", "AutoRolesHistory", AutoRoleHistory, db) + + self._bot = bot + self._auto_role_rules = auto_role_rules + self._servers = servers + + self.set_field("id", self.resolve_id) + self.set_field("channelId", self.resolve_channel_id) + self.set_field("channelName", self.resolve_channel_name) + self.set_field("messageId", self.resolve_message_id) + self.set_field("server", self.resolve_server) + self.add_collection( + "autoRoleRule", + lambda x, *_: self._auto_role_rules.get_auto_role_rules_by_auto_role_id(x.id), + AutoRoleFilter, + ) + + @staticmethod + def resolve_id(x: AutoRole, *_): + return x.id + + @staticmethod + def resolve_channel_id(x: AutoRole, *_): + return x.discord_channel_id + + @staticmethod + def resolve_channel_name(x: AutoRole, *_): + return x.discord_channel_name + + @staticmethod + def resolve_message_id(x: AutoRole, *_): + return x.discord_message_id + + def resolve_server(self, x: AutoRole, *_, filter: ServerFilter = None): + if filter is not None: + return filter.filter(self._servers.get_server_by_id(x.server.id)) + + return self._servers.get_server_by_id(x.server.id) diff --git a/kdb-bot/src/bot_graphql/queries/auto_role_rule_history_query.py b/kdb-bot/src/bot_graphql/queries/auto_role_rule_history_query.py new file mode 100644 index 00000000..8cfb6869 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/auto_role_rule_history_query.py @@ -0,0 +1,37 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.model.auto_role_rule import AutoRoleRule +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class AutoRoleRuleHistoryQuery(HistoryQueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + auto_roles: AutoRoleRepositoryABC, + ): + HistoryQueryABC.__init__(self, "AutoRoleRule") + + self._bot = bot + self._auto_roles = auto_roles + + self.set_field("id", self.resolve_id) + self.set_field("emojiName", self.resolve_emoji_name) + self.set_field("roleId", self.resolve_role_id) + self.set_field("autoRole", self.resolve_auto_role) + + @staticmethod + def resolve_id(x: AutoRoleRule, *_): + return x.id + + @staticmethod + def resolve_emoji_name(x: AutoRoleRule, *_): + return x.emoji_name + + @staticmethod + def resolve_role_id(x: AutoRoleRule, *_): + return x.role_id + + def resolve_auto_role(self, x: AutoRoleRule, *_): + return x.auto_role diff --git a/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py b/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py new file mode 100644 index 00000000..e847a605 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/auto_role_rule_query.py @@ -0,0 +1,40 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.model.auto_role_rule import AutoRoleRule +from bot_data.model.auto_role_rule_history import AutoRoleRuleHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class AutoRoleRuleQuery(DataQueryWithHistoryABC): + def __init__(self, bot: DiscordBotServiceABC, auto_roles: AutoRoleRepositoryABC, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__(self, "AutoRoleRule", "AutoRoleRulesHistory", AutoRoleRuleHistory, db) + + self._bot = bot + self._auto_roles = auto_roles + + self.set_field("id", self.resolve_id) + self.set_field("emojiName", self.resolve_emoji_name) + self.set_field("roleId", self.resolve_role_id) + self.set_field("roleName", self.resolve_role_name) + self.set_field("autoRole", self.resolve_auto_role) + + @staticmethod + def resolve_id(x: AutoRoleRule, *_): + return x.id + + @staticmethod + def resolve_emoji_name(x: AutoRoleRule, *_): + return x.emoji_name + + @staticmethod + def resolve_role_id(x: AutoRoleRule, *_): + return x.role_id + + @staticmethod + def resolve_role_name(x: AutoRoleRule, *_): + return x.role_name + + def resolve_auto_role(self, x: AutoRoleRule, *_): + return self._auto_roles.get_auto_role_by_id(x.auto_role.id) diff --git a/kdb-bot/src/bot_graphql/queries/client_history_query.py b/kdb-bot/src/bot_graphql/queries/client_history_query.py new file mode 100644 index 00000000..3d1e340f --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/client_history_query.py @@ -0,0 +1,60 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.client import Client +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class ClientHistoryQuery(HistoryQueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + ): + HistoryQueryABC.__init__(self, "Client") + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("sentMessageCount", self.resolve_sent_message_count) + self.set_field("receivedMessageCount", self.resolve_received_message_count) + self.set_field("deletedMessageCount", self.resolve_deleted_message_count) + self.set_field("receivedCommandCount", self.resolve_received_command_count) + self.set_field("movedUsersCount", self.resolve_moved_users_count) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(client: Client, *_): + return client.id + + @staticmethod + def resolve_discord_id(client: Client, *_): + return client.discord_id + + @staticmethod + def resolve_name(client: Client, *_): + return client.name + + @staticmethod + def resolve_sent_message_count(client: Client, *_): + return client.sent_message_count + + @staticmethod + def resolve_received_message_count(client: Client, *_): + return client.received_command_count + + @staticmethod + def resolve_deleted_message_count(client: Client, *_): + return client.deleted_message_count + + @staticmethod + def resolve_received_command_count(client: Client, *_): + return client.received_command_count + + @staticmethod + def resolve_moved_users_count(client: Client, *_): + return client.moved_users_count + + @staticmethod + def resolve_server(client: Client, *_): + return client.server diff --git a/kdb-bot/src/bot_graphql/queries/client_query.py b/kdb-bot/src/bot_graphql/queries/client_query.py new file mode 100644 index 00000000..e5cd4c68 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/client_query.py @@ -0,0 +1,59 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.client import Client +from bot_data.model.client_history import ClientHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class ClientQuery(DataQueryWithHistoryABC): + def __init__(self, bot: DiscordBotServiceABC, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__(self, "Client", "ClientsHistory", ClientHistory, db) + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("sentMessageCount", self.resolve_sent_message_count) + self.set_field("receivedMessageCount", self.resolve_received_message_count) + self.set_field("deletedMessageCount", self.resolve_deleted_message_count) + self.set_field("receivedCommandCount", self.resolve_received_command_count) + self.set_field("movedUsersCount", self.resolve_moved_users_count) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(client: Client, *_): + return client.id + + @staticmethod + def resolve_discord_id(client: Client, *_): + return client.discord_id + + @staticmethod + def resolve_name(client: Client, *_): + return client.name + + @staticmethod + def resolve_sent_message_count(client: Client, *_): + return client.sent_message_count + + @staticmethod + def resolve_received_message_count(client: Client, *_): + return client.received_command_count + + @staticmethod + def resolve_deleted_message_count(client: Client, *_): + return client.deleted_message_count + + @staticmethod + def resolve_received_command_count(client: Client, *_): + return client.received_command_count + + @staticmethod + def resolve_moved_users_count(client: Client, *_): + return client.moved_users_count + + @staticmethod + def resolve_server(client: Client, *_): + return client.server diff --git a/kdb-bot/src/bot_graphql/queries/discord/__init__.py b/kdb-bot/src/bot_graphql/queries/discord/__init__.py new file mode 100644 index 00000000..06feea6e --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/discord/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +bot Keksdose bot +~~~~~~~~~~~~~~~~~~~ + +Discord bot for the Keksdose discord Server + +:copyright: (c) 2022 - 2023 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = "bot_graphql.queries.discord" +__author__ = "Sven Heidemann" +__license__ = "MIT" +__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" +__version__ = "1.0.0" + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple("VersionInfo", "major minor micro") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/bot_graphql/queries/discord/channel_query.py b/kdb-bot/src/bot_graphql/queries/discord/channel_query.py new file mode 100644 index 00000000..56807d5e --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/discord/channel_query.py @@ -0,0 +1,10 @@ +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class ChannelQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "Channel") + + self.set_field("id", lambda c, *_: c.id) + self.set_field("name", lambda c, *_: c.name) + self.set_field("type", lambda c, *_: type(c)) diff --git a/kdb-bot/src/bot_graphql/queries/discord/emoji_query.py b/kdb-bot/src/bot_graphql/queries/discord/emoji_query.py new file mode 100644 index 00000000..3c776a9d --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/discord/emoji_query.py @@ -0,0 +1,10 @@ +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class RoleQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "Emoji") + + self.set_field("id", lambda e, *_: e.id) + self.set_field("name", lambda e, *_: e.name) + self.set_field("url", lambda e, *_: e.url) diff --git a/kdb-bot/src/bot_graphql/queries/discord/guild_query.py b/kdb-bot/src/bot_graphql/queries/discord/guild_query.py new file mode 100644 index 00000000..f963e999 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/discord/guild_query.py @@ -0,0 +1,12 @@ +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class GuildQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "Guild") + + self.set_field("id", lambda g, *_: g.id) + self.set_field("name", lambda g, *_: g.name) + self.set_field("channels", lambda g, *_: g.channels) + self.set_field("roles", lambda g, *_: g.roles) + self.set_field("emojis", lambda g, *_: g.emojis) diff --git a/kdb-bot/src/bot_graphql/queries/discord/role_query.py b/kdb-bot/src/bot_graphql/queries/discord/role_query.py new file mode 100644 index 00000000..6880ed4f --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/discord/role_query.py @@ -0,0 +1,9 @@ +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class RoleQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "Role") + + self.set_field("id", lambda r, *_: r.id) + self.set_field("name", lambda r, *_: r.name) diff --git a/kdb-bot/src/bot_graphql/queries/known_user_history_query.py b/kdb-bot/src/bot_graphql/queries/known_user_history_query.py new file mode 100644 index 00000000..052bf291 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/known_user_history_query.py @@ -0,0 +1,18 @@ +from bot_data.model.known_user import KnownUser +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class KnownUserHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "KnownUser") + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + + @staticmethod + def resolve_id(x: KnownUser, *_): + return x.id + + @staticmethod + def resolve_discord_id(x: KnownUser, *_): + return x.discord_id diff --git a/kdb-bot/src/bot_graphql/queries/known_user_query.py b/kdb-bot/src/bot_graphql/queries/known_user_query.py new file mode 100644 index 00000000..d3435735 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/known_user_query.py @@ -0,0 +1,21 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.model.known_user import KnownUser +from bot_data.model.known_user_history import KnownUserHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class KnownUserQuery(DataQueryWithHistoryABC): + def __init__(self, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__(self, "KnownUser", "KnownUsersHistory", KnownUserHistory, db) + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + + @staticmethod + def resolve_id(x: KnownUser, *_): + return x.id + + @staticmethod + def resolve_discord_id(x: KnownUser, *_): + return x.discord_id diff --git a/kdb-bot/src/bot_graphql/queries/level_history_query.py b/kdb-bot/src/bot_graphql/queries/level_history_query.py new file mode 100644 index 00000000..fecf8ffb --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/level_history_query.py @@ -0,0 +1,38 @@ +from bot_data.model.level import Level +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class LevelHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "Level") + + self.set_field("id", self.resolve_id) + self.set_field("name", self.resolve_name) + self.set_field("color", self.resolve_color) + self.set_field("minXp", self.resolve_min_xp) + self.set_field("permissions", self.resolve_permissions) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(level: Level, *_): + return level.id + + @staticmethod + def resolve_name(level: Level, *_): + return level.name + + @staticmethod + def resolve_color(level: Level, *_): + return level.color + + @staticmethod + def resolve_min_xp(level: Level, *_): + return level.min_xp + + @staticmethod + def resolve_permissions(level: Level, *_): + return level.permissions + + @staticmethod + def resolve_server(level: Level, *_): + return level.server diff --git a/kdb-bot/src/bot_graphql/queries/level_query.py b/kdb-bot/src/bot_graphql/queries/level_query.py new file mode 100644 index 00000000..5f726c5b --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/level_query.py @@ -0,0 +1,41 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.model.level import Level +from bot_data.model.level_history import LevelHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class LevelQuery(DataQueryWithHistoryABC): + def __init__(self, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__(self, "Level", "LevelsHistory", LevelHistory, db) + + self.set_field("id", self.resolve_id) + self.set_field("name", self.resolve_name) + self.set_field("color", self.resolve_color) + self.set_field("minXp", self.resolve_min_xp) + self.set_field("permissions", self.resolve_permissions) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(level: Level, *_): + return level.id + + @staticmethod + def resolve_name(level: Level, *_): + return level.name + + @staticmethod + def resolve_color(level: Level, *_): + return level.color + + @staticmethod + def resolve_min_xp(level: Level, *_): + return level.min_xp + + @staticmethod + def resolve_permissions(level: Level, *_): + return level.permissions + + @staticmethod + def resolve_server(level: Level, *_): + return level.server diff --git a/kdb-bot/src/bot_graphql/queries/server_history_query.py b/kdb-bot/src/bot_graphql/queries/server_history_query.py new file mode 100644 index 00000000..1578d331 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/server_history_query.py @@ -0,0 +1,30 @@ +from bot_data.model.server import Server +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class ServerHistoryQuery(HistoryQueryABC): + def __init__( + self, + ): + HistoryQueryABC.__init__(self, "Server") + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("iconURL", self.resolve_icon_url) + + @staticmethod + def resolve_id(server: Server, *_): + return server.id + + @staticmethod + def resolve_discord_id(server: Server, *_): + return server.discord_id + + @staticmethod + def resolve_name(server: Server, *_): + return server.name + + @staticmethod + def resolve_icon_url(server: Server, *_): + return server.icon_url diff --git a/kdb-bot/src/bot_graphql/queries/server_query.py b/kdb-bot/src/bot_graphql/queries/server_query.py new file mode 100644 index 00000000..39012d49 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/server_query.py @@ -0,0 +1,72 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC +from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.server import Server +from bot_data.model.server_history import ServerHistory +from bot_graphql.abc.data_query_abc import DataQueryABC +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC +from bot_graphql.filter.auto_role_filter import AutoRoleFilter +from bot_graphql.filter.client_filter import ClientFilter +from bot_graphql.filter.level_filter import LevelFilter +from bot_graphql.filter.user_filter import UserFilter + + +class ServerQuery(DataQueryWithHistoryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + auto_roles: AutoRoleRepositoryABC, + clients: ClientRepositoryABC, + levels: LevelRepositoryABC, + users: UserRepositoryABC, + ujs: UserJoinedServerRepositoryABC, + ujvs: UserJoinedVoiceChannelRepositoryABC, + ): + DataQueryWithHistoryABC.__init__(self, "Server", "ServersHistory", ServerHistory, db) + + self._bot = bot + self._auto_roles = auto_roles + self._clients = clients + self._levels = levels + self._users = users + self._ujs = ujs + self._ujvs = ujvs + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("iconURL", self.resolve_icon_url) + + self.add_collection( + "autoRole", + lambda server, *_: self._auto_roles.get_auto_roles_by_server_id(server.id), + AutoRoleFilter, + ) + self.add_collection( + "client", lambda server, *_: self._clients.get_clients_by_server_id(server.id), ClientFilter + ) + self.add_collection("level", lambda server, *_: self._levels.get_levels_by_server_id(server.id), LevelFilter) + self.add_collection("user", lambda server, *_: self._users.get_users_by_server_id(server.id), UserFilter) + + @staticmethod + def resolve_id(server: Server, *_): + return server.id + + @staticmethod + def resolve_discord_id(server: Server, *_): + return server.discord_id + + @staticmethod + def resolve_name(server: Server, *_): + return server.name + + @staticmethod + def resolve_icon_url(server: Server, *_): + return server.icon_url diff --git a/kdb-bot/src/bot_graphql/queries/user_history_query.py b/kdb-bot/src/bot_graphql/queries/user_history_query.py new file mode 100644 index 00000000..14d3867b --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_history_query.py @@ -0,0 +1,28 @@ +from bot_data.model.user import User +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class UserHistoryQuery(HistoryQueryABC): + def __init__(self): + HistoryQueryABC.__init__(self, "User") + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + self.set_field("xp", self.resolve_xp) + self.set_field("server", self.resolve_server) + + @staticmethod + def resolve_id(user: User, *_): + return user.id + + @staticmethod + def resolve_discord_id(user: User, *_): + return user.discord_id + + @staticmethod + def resolve_xp(user: User, *_): + return user.xp + + @staticmethod + def resolve_server(user: User, *_): + return user.server diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_game_server_history_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_history_query.py new file mode 100644 index 00000000..d0997b5a --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_history_query.py @@ -0,0 +1,41 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.user_joined_game_server import UserJoinedGameServer +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class UserJoinedGameServerHistoryQuery(HistoryQueryABC): + def __init__(self, bot: DiscordBotServiceABC): + HistoryQueryABC.__init__(self, "UserJoinedGameServer") + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("gameServer", self.resolve_game_server) + self.set_field("user", self.resolve_user) + self.set_field("joinedOn", self.resolve_joined_on) + self.set_field("leavedOn", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedGameServer, *_): + return x.id + + @staticmethod + def resolve_game_server(x: UserJoinedGameServer, *_): + return x.game_server.name + + @staticmethod + def resolve_user(x: UserJoinedGameServer, *_): + return x.user + + @staticmethod + def resolve_time(x: UserJoinedGameServer, *_): + return x.time + + @staticmethod + def resolve_joined_on(x: UserJoinedGameServer, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedGameServer, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py new file mode 100644 index 00000000..6a5befaa --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_game_server_query.py @@ -0,0 +1,45 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.user_joined_game_server import UserJoinedGameServer +from bot_data.model.user_joined_game_server_history import UserJoinedGameServerHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class UserJoinedGameServerQuery(DataQueryWithHistoryABC): + def __init__(self, bot: DiscordBotServiceABC, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__( + self, "UserJoinedGameServer", "UserJoinedGameServersHistory", UserJoinedGameServerHistory, db + ) + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("gameServer", self.resolve_game_server) + self.set_field("user", self.resolve_user) + self.set_field("joinedOn", self.resolve_joined_on) + self.set_field("leavedOn", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedGameServer, *_): + return x.id + + @staticmethod + def resolve_game_server(x: UserJoinedGameServer, *_): + return x.game_server.name + + @staticmethod + def resolve_user(x: UserJoinedGameServer, *_): + return x.user + + @staticmethod + def resolve_time(x: UserJoinedGameServer, *_): + return x.time + + @staticmethod + def resolve_joined_on(x: UserJoinedGameServer, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedGameServer, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_server_history_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_server_history_query.py new file mode 100644 index 00000000..3d7beed5 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_server_history_query.py @@ -0,0 +1,28 @@ +from bot_data.model.user_joined_server import UserJoinedServer +from bot_graphql.abc.data_query_abc import DataQueryABC + + +class UserJoinedServerHistoryQuery(DataQueryABC): + def __init__(self): + DataQueryABC.__init__(self, "UserJoinedServer") + + self.set_field("id", self.resolve_id) + self.set_field("user", self.resolve_user) + self.set_field("joinedOn", self.resolve_joined_on) + self.set_field("leavedOn", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedServer, *_): + return x.id + + @staticmethod + def resolve_user(x: UserJoinedServer, *_): + return x.user + + @staticmethod + def resolve_joined_on(x: UserJoinedServer, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedServer, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py new file mode 100644 index 00000000..a8e236ff --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_server_query.py @@ -0,0 +1,33 @@ +from cpl_core.database.context import DatabaseContextABC + +from bot_data.model.user_joined_server import UserJoinedServer +from bot_data.model.user_joined_server_history import UserJoinedServerHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class UserJoinedServerQuery(DataQueryWithHistoryABC): + def __init__(self, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__( + self, "UserJoinedServer", "UserJoinedServersHistory", UserJoinedServerHistory, db + ) + + self.set_field("id", self.resolve_id) + self.set_field("user", self.resolve_user) + self.set_field("joinedOn", self.resolve_joined_on) + self.set_field("leavedOn", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedServer, *_): + return x.id + + @staticmethod + def resolve_user(x: UserJoinedServer, *_): + return x.user + + @staticmethod + def resolve_joined_on(x: UserJoinedServer, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedServer, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_history_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_history_query.py new file mode 100644 index 00000000..c9cae071 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_history_query.py @@ -0,0 +1,47 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_graphql.abc.history_query_abc import HistoryQueryABC + + +class UserJoinedVoiceChannelHistoryQuery(HistoryQueryABC): + def __init__(self, bot: DiscordBotServiceABC): + HistoryQueryABC.__init__(self, "UserJoinedVoiceChannel") + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("channelId", self.resolve_channel_id) + self.set_field("channelName", self.resolve_channel_name) + self.set_field("user", self.resolve_user) + self.set_field("time", self.resolve_time) + self.set_field("joinedOn", self.resolve_joined_on) + self.set_field("leavedOn", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedVoiceChannel, *_): + return x.id + + @staticmethod + def resolve_channel_id(x: UserJoinedVoiceChannel, *_): + return x.channel_id + + @staticmethod + def resolve_channel_name(x: UserJoinedVoiceChannel, *_): + return x.channel_name + + @staticmethod + def resolve_user(x: UserJoinedVoiceChannel, *_): + return x.user + + @staticmethod + def resolve_time(x: UserJoinedVoiceChannel, *_): + return x.time + + @staticmethod + def resolve_joined_on(x: UserJoinedVoiceChannel, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedVoiceChannel, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py new file mode 100644 index 00000000..a5465581 --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py @@ -0,0 +1,51 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel +from bot_data.model.user_joined_voice_channel_history import UserJoinedVoiceChannelHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC + + +class UserJoinedVoiceChannelQuery(DataQueryWithHistoryABC): + def __init__(self, bot: DiscordBotServiceABC, db: DatabaseContextABC): + DataQueryWithHistoryABC.__init__( + self, "UserJoinedVoiceChannel", "UserJoinedVoiceChannelsHistory", UserJoinedVoiceChannelHistory, db + ) + + self._bot = bot + + self.set_field("id", self.resolve_id) + self.set_field("channelId", self.resolve_channel_id) + self.set_field("channelName", self.resolve_channel_name) + self.set_field("user", self.resolve_user) + self.set_field("time", self.resolve_time) + self.set_field("joinedOn", self.resolve_joined_on) + self.set_field("leavedOn", self.resolve_leaved_on) + + @staticmethod + def resolve_id(x: UserJoinedVoiceChannel, *_): + return x.id + + @staticmethod + def resolve_channel_id(x: UserJoinedVoiceChannel, *_): + return x.channel_id + + @staticmethod + def resolve_channel_name(x: UserJoinedVoiceChannel, *_): + return x.channel_name + + @staticmethod + def resolve_user(x: UserJoinedVoiceChannel, *_): + return x.user + + @staticmethod + def resolve_time(x: UserJoinedVoiceChannel, *_): + return x.time + + @staticmethod + def resolve_joined_on(x: UserJoinedVoiceChannel, *_): + return x.joined_on + + @staticmethod + def resolve_leaved_on(x: UserJoinedVoiceChannel, *_): + return x.leaved_on diff --git a/kdb-bot/src/bot_graphql/queries/user_query.py b/kdb-bot/src/bot_graphql/queries/user_query.py new file mode 100644 index 00000000..9e924f5f --- /dev/null +++ b/kdb-bot/src/bot_graphql/queries/user_query.py @@ -0,0 +1,94 @@ +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC +from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC +from bot_data.model.user import User +from bot_data.model.user_history import UserHistory +from bot_graphql.abc.data_query_with_history_abc import DataQueryWithHistoryABC +from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter +from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter +from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter +from modules.level.service.level_service import LevelService +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class UserQuery(DataQueryWithHistoryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + levels: LevelService, + client_utils: ClientUtilsABC, + ujs: UserJoinedServerRepositoryABC, + ujvs: UserJoinedVoiceChannelRepositoryABC, + user_joined_game_server: UserJoinedGameServerRepositoryABC, + permissions: PermissionServiceABC, + ): + DataQueryWithHistoryABC.__init__(self, "User", "UsersHistory", UserHistory, db) + + self._bot = bot + self._levels = levels + self._client_utils = client_utils + self._user_joined_game_server = user_joined_game_server + self._ujs = ujs + self._ujvs = ujvs + self._permissions = permissions + + self.set_field("id", self.resolve_id) + self.set_field("discordId", self.resolve_discord_id) + self.set_field("name", self.resolve_name) + self.set_field("xp", self.resolve_xp) + self.set_field("ontime", self.resolve_ontime) + self.set_field("level", self.resolve_level) + self.add_collection( + "joinedServer", + lambda user, *_: self._ujs.get_user_joined_servers_by_user_id(user.id), + UserJoinedServerFilter, + ) + self.add_collection( + "joinedVoiceChannel", + lambda user, *_: self._ujvs.get_user_joined_voice_channels_by_user_id(user.id), + UserJoinedVoiceChannelFilter, + ) + self.add_collection( + "userJoinedGameServer", + lambda user, *_: self._user_joined_game_server.get_user_joined_game_servers_by_user_id(user.id), + UserJoinedGameServerFilter, + ) + self.set_field("server", self.resolve_server) + self.set_field("leftServer", self.resolve_left_server) + + @staticmethod + def resolve_id(user: User, *_): + return user.id + + @staticmethod + def resolve_discord_id(user: User, *_): + return user.discord_id + + @staticmethod + def resolve_name(user: User, *_): + return user.name + + @staticmethod + def resolve_xp(user: User, *_): + return user.xp + + @staticmethod + def resolve_ontime(user: User, *_): + return user.ontime + + @staticmethod + def resolve_level(user: User, *_): + return user.level + + @staticmethod + def resolve_server(user: User, *_): + return user.server + + @staticmethod + def resolve_left_server(user: User, *_): + return user.left_server diff --git a/kdb-bot/src/bot_graphql/query.py b/kdb-bot/src/bot_graphql/query.py new file mode 100644 index 00000000..8133e4dc --- /dev/null +++ b/kdb-bot/src/bot_graphql/query.py @@ -0,0 +1,69 @@ +from cpl_discord.service import DiscordBotServiceABC + +from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC +from bot_data.abc.client_repository_abc import ClientRepositoryABC +from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC +from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC +from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC +from bot_data.abc.user_joined_voice_channel_repository_abc import UserJoinedVoiceChannelRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_graphql.abc.query_abc import QueryABC +from bot_graphql.filter.auto_role_filter import AutoRoleFilter +from bot_graphql.filter.auto_role_rule_filter import AutoRoleRuleFilter +from bot_graphql.filter.client_filter import ClientFilter +from bot_graphql.filter.level_filter import LevelFilter +from bot_graphql.filter.server_filter import ServerFilter +from bot_graphql.filter.user_filter import UserFilter +from bot_graphql.filter.user_joined_game_server_filter import UserJoinedGameServerFilter +from bot_graphql.filter.user_joined_server_filter import UserJoinedServerFilter +from bot_graphql.filter.user_joined_voice_channel_filter import UserJoinedVoiceChannelFilter + + +class Query(QueryABC): + def __init__( + self, + bot: DiscordBotServiceABC, + auto_roles: AutoRoleRepositoryABC, + clients: ClientRepositoryABC, + known_users: KnownUserRepositoryABC, + levels: LevelRepositoryABC, + servers: ServerRepositoryABC, + user_joined_servers: UserJoinedServerRepositoryABC, + user_joined_voice_channels: UserJoinedVoiceChannelRepositoryABC, + user_joined_game_server: UserJoinedGameServerRepositoryABC, + users: UserRepositoryABC, + ): + QueryABC.__init__(self, "Query") + + self._bot = bot + + self.add_collection("autoRole", lambda *_: auto_roles.get_auto_roles(), AutoRoleFilter) + self.add_collection("autoRoleRule", lambda *_: auto_roles.get_auto_role_rules(), AutoRoleRuleFilter) + self.add_collection("client", lambda *_: clients.get_clients(), ClientFilter) + self.add_collection("knownUser", lambda *_: known_users.get_users()) + self.add_collection("level", lambda *_: levels.get_levels(), LevelFilter) + self.add_collection("server", lambda *_: servers.get_servers(), ServerFilter) + self.add_collection( + "userJoinedServer", lambda *_: user_joined_servers.get_user_joined_servers(), UserJoinedServerFilter + ) + self.add_collection( + "userJoinedVoiceChannel", + lambda *_: user_joined_voice_channels.get_user_joined_voice_channels(), + UserJoinedVoiceChannelFilter, + ) + self.add_collection( + "userJoinedGameServer", + lambda *_: user_joined_game_server.get_user_joined_game_servers(), + UserJoinedGameServerFilter, + ) + self.add_collection("user", lambda *_: users.get_users(), UserFilter) + + self.set_field("guilds", self._resolve_guilds) + + def _resolve_guilds(self, *_, filter=None): + if filter is None or "id" not in filter: + return self._bot.guilds + + return self._bot.guilds.where(lambda g: g.id == int(filter["id"])) diff --git a/kdb-bot/src/bot_graphql/schema.py b/kdb-bot/src/bot_graphql/schema.py new file mode 100644 index 00000000..d2972a78 --- /dev/null +++ b/kdb-bot/src/bot_graphql/schema.py @@ -0,0 +1,18 @@ +import os + +from ariadne import make_executable_schema, load_schema_from_path +from graphql import GraphQLSchema + +from bot_graphql.abc.query_abc import QueryABC +from bot_graphql.mutation import Mutation +from bot_graphql.query import Query + + +class Schema: + def __init__(self, query: Query, mutation: Mutation, queries: list[QueryABC]): + type_defs = load_schema_from_path(os.path.join(os.path.dirname(os.path.realpath(__file__)), "model/")) + self._schema = make_executable_schema(type_defs, query, mutation, *queries) + + @property + def schema(self) -> GraphQLSchema: + return self._schema diff --git a/kdb-bot/src/modules/auto_role/__init__.py b/kdb-bot/src/modules/auto_role/__init__.py index 225a5ad8..3cb4c3b0 100644 --- a/kdb-bot/src/modules/auto_role/__init__.py +++ b/kdb-bot/src/modules/auto_role/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.auto_role" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/auto_role/auto-role.json b/kdb-bot/src/modules/auto_role/auto-role.json index 9e9d6600..9d869df8 100644 --- a/kdb-bot/src/modules/auto_role/auto-role.json +++ b/kdb-bot/src/modules/auto_role/auto-role.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "auto-role", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/modules/auto_role/command/__init__.py b/kdb-bot/src/modules/auto_role/command/__init__.py index 7f5d14fa..0e750c54 100644 --- a/kdb-bot/src/modules/auto_role/command/__init__.py +++ b/kdb-bot/src/modules/auto_role/command/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.auto_role.command" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/auto_role/command/auto_role_group.py b/kdb-bot/src/modules/auto_role/command/auto_role_group.py index 947dc8bd..b0ce3525 100644 --- a/kdb-bot/src/modules/auto_role/command/auto_role_group.py +++ b/kdb-bot/src/modules/auto_role/command/auto_role_group.py @@ -1,9 +1,8 @@ -from typing import List as TList, Optional, Any +from typing import List as TList import discord from cpl_core.database.context import DatabaseContextABC from cpl_discord.command import DiscordCommandABC -from cpl_discord.container import TextChannel from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List from cpl_translation import TranslatePipe @@ -53,7 +52,7 @@ class AutoRoleGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.server_id).select(lambda x: x.auto_role_id) + auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.id).select(lambda x: x.id) return [ app_commands.Choice(name=auto_role, value=auto_role) for auto_role in self._client_utils.get_auto_complete_list(auto_roles, current) @@ -80,7 +79,7 @@ class AutoRoleGroup(DiscordCommandABC): color=int("ef9d0d", 16), ) server = self._servers.get_server_by_discord_id(ctx.guild.id) - auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.server_id) + auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.id) if auto_roles.count() < 1: await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.auto_role.error.nothing_found")) self._logger.trace(__name__, f"Finished command auto-role list") @@ -89,7 +88,7 @@ class AutoRoleGroup(DiscordCommandABC): auto_role_id = "" message_id = "" for auto_role in auto_roles: - auto_role_id += f"\n{auto_role.auto_role_id}" + auto_role_id += f"\n{auto_role.id}" message_id += f"\n{auto_role.discord_message_id}" embed.add_field( @@ -138,10 +137,10 @@ class AutoRoleGroup(DiscordCommandABC): self._logger.trace(__name__, f"Finished command auto-role add") return - server_id = self._servers.get_server_by_discord_id(ctx.guild.id).server_id - self._auto_roles.add_auto_role(AutoRole(server_id, int(channel.id), int(message_id))) + server = self._servers.get_server_by_discord_id(ctx.guild.id) + self._auto_roles.add_auto_role(AutoRole(server, int(channel.id), int(message_id))) self._db_context.save_changes() - self._logger.info(__name__, f"Saved auto-role for message {message_id} at server {server_id}") + self._logger.info(__name__, f"Saved auto-role for message {message_id} at server {server}") await self._message_service.send_ctx_msg( ctx, self._t.transform("modules.auto_role.add.success").format(message_id) ) @@ -182,7 +181,7 @@ class AutoRoleGroup(DiscordCommandABC): self._logger.trace(__name__, f"Finished command auto-role remove") return - for rule in self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_from_db.auto_role_id): + for rule in self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role_from_db.id): self._auto_roles.delete_auto_role_rule(rule) self._logger.info(__name__, f"Removed auto-role rule {rule.role_id}") @@ -306,7 +305,7 @@ class AutoRoleGroup(DiscordCommandABC): self._logger.trace(__name__, f"Finished command auto-role rule add") return - self._auto_roles.add_auto_role_rule(AutoRoleRule(auto_role, emoji_name, int(role_id))) + self._auto_roles.add_auto_role_rule(AutoRoleRule(auto_role_from_db, emoji_name, int(role_id))) self._db_context.save_changes() rule = ( self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role) @@ -393,12 +392,12 @@ class AutoRoleGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.server_id).select(lambda x: x.auto_role_id) + auto_roles = self._auto_roles.get_auto_roles_by_server_id(server.id).select(lambda x: x.id) rules = auto_roles.select_many(lambda ar: self._auto_roles.get_auto_role_rules_by_auto_role_id(ar)) return [ app_commands.Choice( - name=f"{rule.auto_role_rule_id} {rule.emoji_name} {interaction.guild.get_role(int(rule.role_id))}", - value=rule.auto_role_rule_id, + name=f"{rule.id} {rule.emoji_name} {interaction.guild.get_role(int(rule.role_id))}", + value=rule.id, ) - for rule in self._client_utils.get_auto_complete_list(rules, current, lambda r: r.auto_role_rule_id) + for rule in self._client_utils.get_auto_complete_list(rules, current, lambda r: r.id) ] diff --git a/kdb-bot/src/modules/auto_role/events/__init__.py b/kdb-bot/src/modules/auto_role/events/__init__.py index 1631cdbc..e2360924 100644 --- a/kdb-bot/src/modules/auto_role/events/__init__.py +++ b/kdb-bot/src/modules/auto_role/events/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.auto_role.events" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/auto_role/helper/__init__.py b/kdb-bot/src/modules/auto_role/helper/__init__.py index 7acb3eaf..4f23cb57 100644 --- a/kdb-bot/src/modules/auto_role/helper/__init__.py +++ b/kdb-bot/src/modules/auto_role/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.auto_role.helper" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py b/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py index c9ae6e7f..47ab3778 100644 --- a/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py +++ b/kdb-bot/src/modules/auto_role/helper/auto_role_reaction_handler.py @@ -1,4 +1,3 @@ -import discord from cpl_core.logging import LoggerABC from cpl_discord.service import DiscordBotServiceABC from cpl_query.extension import List @@ -50,7 +49,7 @@ class AutoRoleReactionHandler: self._logger.debug(__name__, f"auto-role for message not found - skipping") return - rules: List[AutoRoleRule] = self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role.auto_role_id) + rules: List[AutoRoleRule] = self._auto_roles.get_auto_role_rules_by_auto_role_id(auto_role.id) if rules.count() == 0: self._logger.debug(__name__, f"auto-role rules not found - skipping") return diff --git a/kdb-bot/src/modules/base/__init__.py b/kdb-bot/src/modules/base/__init__.py index fe173a55..5d5c4b02 100644 --- a/kdb-bot/src/modules/base/__init__.py +++ b/kdb-bot/src/modules/base/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/abc/__init__.py b/kdb-bot/src/modules/base/abc/__init__.py index 7730864a..2d3782f0 100644 --- a/kdb-bot/src/modules/base/abc/__init__.py +++ b/kdb-bot/src/modules/base/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.abc" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/base.json b/kdb-bot/src/modules/base/base.json index 845c05a7..cbe8c7c0 100644 --- a/kdb-bot/src/modules/base/base.json +++ b/kdb-bot/src/modules/base/base.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "base", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/modules/base/base_module.py b/kdb-bot/src/modules/base/base_module.py index 9377c6e9..4d8c4f2d 100644 --- a/kdb-bot/src/modules/base/base_module.py +++ b/kdb-bot/src/modules/base/base_module.py @@ -8,12 +8,15 @@ from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from modules.base.abc.base_helper_abc import BaseHelperABC from modules.base.command.afk_command import AFKCommand +from modules.base.command.game_server_group import GameServerGroup from modules.base.command.help_command import HelpCommand from modules.base.command.info_command import InfoCommand from modules.base.command.mass_move_command import MassMoveCommand from modules.base.command.ping_command import PingCommand from modules.base.command.presence_command import PresenceCommand from modules.base.command.purge_command import PurgeCommand +from modules.base.command.register_group import RegisterGroup +from modules.base.command.unregister_group import UnregisterGroup from modules.base.command.user_group import UserGroup from modules.base.events.base_on_command_error_event import BaseOnCommandErrorEvent from modules.base.events.base_on_command_event import BaseOnCommandEvent @@ -23,14 +26,20 @@ from modules.base.events.base_on_message_delete_event import BaseOnMessageDelete from modules.base.events.base_on_message_event import BaseOnMessageEvent from modules.base.events.base_on_raw_reaction_add import BaseOnRawReactionAddEvent from modules.base.events.base_on_raw_reaction_remove import BaseOnRawReactionRemoveEvent +from modules.base.events.base_on_scheduled_event_update_event import BaseOnScheduledEventUpdateEvent from modules.base.events.base_on_voice_state_update_event import ( BaseOnVoiceStateUpdateEvent, ) from modules.base.events.base_on_voice_state_update_event_help_channel import ( BaseOnVoiceStateUpdateEventHelpChannel, ) +from modules.base.events.base_on_voice_state_update_event_scheduled_event_bonus import ( + BaseOnVoiceStateUpdateEventScheduledEventBonus, +) from modules.base.helper.base_reaction_handler import BaseReactionHandler from modules.base.service.base_helper_service import BaseHelperService +from modules.base.service.event_service import EventService +from modules.base.service.user_warnings_service import UserWarningsService class BaseModule(ModuleABC): @@ -43,6 +52,9 @@ class BaseModule(ModuleABC): def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): services.add_transient(BaseHelperABC, BaseHelperService) services.add_transient(BaseReactionHandler) + services.add_singleton(EventService) + services.add_transient(UserWarningsService) + # commands self._dc.add_command(AFKCommand) self._dc.add_command(HelpCommand) @@ -53,6 +65,9 @@ class BaseModule(ModuleABC): self._dc.add_command(PurgeCommand) self._dc.add_command(UserGroup) + self._dc.add_command(RegisterGroup) + self._dc.add_command(UnregisterGroup) + self._dc.add_command(GameServerGroup) # events self._dc.add_event(DiscordEventTypesEnum.on_command.value, BaseOnCommandEvent) self._dc.add_event(DiscordEventTypesEnum.on_command_error.value, BaseOnCommandErrorEvent) @@ -73,3 +88,11 @@ class BaseModule(ModuleABC): DiscordEventTypesEnum.on_voice_state_update.value, BaseOnVoiceStateUpdateEventHelpChannel, ) + self._dc.add_event( + DiscordEventTypesEnum.on_voice_state_update.value, + BaseOnVoiceStateUpdateEventScheduledEventBonus, + ) + self._dc.add_event( + DiscordEventTypesEnum.on_scheduled_event_update.value, + BaseOnScheduledEventUpdateEvent, + ) diff --git a/kdb-bot/src/modules/base/command/__init__.py b/kdb-bot/src/modules/base/command/__init__.py index 1aa1acbd..b1d903c8 100644 --- a/kdb-bot/src/modules/base/command/__init__.py +++ b/kdb-bot/src/modules/base/command/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.command" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/command/game_server_group.py b/kdb-bot/src/modules/base/command/game_server_group.py new file mode 100644 index 00000000..7d3073be --- /dev/null +++ b/kdb-bot/src/modules/base/command/game_server_group.py @@ -0,0 +1,151 @@ +from typing import List as TList + +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.helper.command_checks import CommandChecks +from bot_core.logging.command_logger import CommandLogger +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.model.game_server import GameServer +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class GameServerGroup(DiscordCommandABC): + def __init__( + self, + logger: CommandLogger, + message_service: MessageServiceABC, + bot: DiscordBotServiceABC, + client_utils: ClientUtilsABC, + translate: TranslatePipe, + servers: ServerRepositoryABC, + game_servers: GameServerRepositoryABC, + api_keys: ApiKeyRepositoryABC, + db: DatabaseContextABC, + permission_service: PermissionServiceABC, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._message_service = message_service + self._bot = bot + self._client_utils = client_utils + self._t = translate + self._servers = servers + self._game_servers = game_servers + self._api_keys = api_keys + self._db = db + self._permissions = permission_service + + self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") + + @commands.hybrid_group(name="game-server") + @commands.guild_only() + async def game_server(self, ctx: Context): + pass + + @game_server.command(alias="game-servers") + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def list(self, ctx: Context, wait: int = None): + self._logger.debug(__name__, f"Received command game_server list {ctx}") + + if ctx.guild is None: + return + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + game_servers = self._game_servers.get_game_servers_by_server_id(server.id) + if game_servers.count() < 1: + await self._message_service.send_ctx_msg( + ctx, self._t.transform("modules.base.game_server.error.nothing_found") + ) + self._logger.trace(__name__, f"Finished command game_server list") + return + + game_server_name = "" + api_key = "" + for game_server in game_servers: + game_server: GameServer = game_server + game_server_name += f"\n{game_server.name}" + api_key += f"\n{game_server.api_key.identifier}" + + embed = discord.Embed( + title=self._t.transform("modules.base.game_server.list.title"), + description=self._t.transform("modules.base.game_server.list.description"), + color=int("ef9d0d", 16), + ) + embed.add_field( + name=self._t.transform("modules.base.game_server.list.name"), + value=game_server_name, + inline=True, + ) + embed.add_field(name=self._t.transform("modules.base.game_server.list.api_key"), value=api_key, inline=True) + + await self._message_service.send_ctx_msg(ctx, embed, wait_before_delete=wait) + self._logger.trace(__name__, f"Finished command game_server list") + + @game_server.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_admin() + async def add(self, ctx: Context, name: str, api_key_id: int): + self._logger.debug(__name__, f"Received command game-server add {ctx}: {name} {api_key_id}") + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + api_key = self._api_keys.get_api_key_by_id(api_key_id) + game_server = GameServer(name, server, api_key) + + self._game_servers.add_game_server(game_server) + self._db.save_changes() + await self._message_service.send_ctx_msg( + ctx, + self._t.transform("modules.base.game_server.add.success").format(name), + ) + + self._logger.trace(__name__, f"Finished command game-server add") + + @add.autocomplete("api_key_id") + async def api_key_id_autocomplete( + self, interaction: discord.Interaction, current: str + ) -> TList[app_commands.Choice[str]]: + keys = self._api_keys.get_api_keys() + + return [ + app_commands.Choice(name=f"{key.identifier}: {key.key}", value=key.id) + for key in self._client_utils.get_auto_complete_list(keys, current, lambda x: x.key) + ] + + @game_server.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_admin() + async def remove(self, ctx: Context, id: int): + self._logger.debug(__name__, f"Received command game-server remove {ctx}: {id}") + + game_server = self._game_servers.get_game_server_by_id(id) + self._game_servers.delete_game_server(game_server) + self._db.save_changes() + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.game_server.remove.success")) + + self._logger.trace(__name__, f"Finished command game-server remove") + + @remove.autocomplete("id") + async def id_autocomplete(self, interaction: discord.Interaction, current: str) -> TList[app_commands.Choice[str]]: + server = self._servers.get_server_by_discord_id(interaction.guild.id) + game_servers = self._game_servers.get_game_servers_by_server_id(server.id) + + return [ + app_commands.Choice(name=gs.name, value=gs.id) + for gs in self._client_utils.get_auto_complete_list(game_servers, current, lambda x: x.name) + ] diff --git a/kdb-bot/src/modules/base/command/ping_command.py b/kdb-bot/src/modules/base/command/ping_command.py index 9e223f9a..eaf58ff6 100644 --- a/kdb-bot/src/modules/base/command/ping_command.py +++ b/kdb-bot/src/modules/base/command/ping_command.py @@ -59,7 +59,7 @@ class PingCommand(DiscordCommandABC): color=int("ef9d0d", 16), ) server = self._servers.get_server_by_discord_id(ctx.guild.id) - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) for server in settings.ping_urls: embed.add_field(name=server, value=f"{self._get_ping(server)} ms", inline=False) await self._message_service.send_ctx_msg(ctx, embed) diff --git a/kdb-bot/src/modules/base/command/register_group.py b/kdb-bot/src/modules/base/command/register_group.py new file mode 100644 index 00000000..dc3fed15 --- /dev/null +++ b/kdb-bot/src/modules/base/command/register_group.py @@ -0,0 +1,109 @@ +from typing import List as TList + +import discord +import requests +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.helper.command_checks import CommandChecks +from bot_core.logging.command_logger import CommandLogger +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.user_game_ident import UserGameIdent + + +class RegisterGroup(DiscordCommandABC): + def __init__( + self, + logger: CommandLogger, + message_service: MessageServiceABC, + bot: DiscordBotServiceABC, + client_utils: ClientUtilsABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + game_server: GameServerRepositoryABC, + user_game_ident: UserGameIdentRepositoryABC, + db: DatabaseContextABC, + t: TranslatePipe, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._message_service = message_service + self._bot = bot + self._client_utils = client_utils + self._servers = servers + self._users = users + self._game_server = game_server + self._user_game_ident = user_game_ident + self._db = db + self._t = t + + self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") + + @commands.hybrid_group() + @commands.guild_only() + async def register(self, ctx: Context): + pass + + @register.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def minecraft(self, ctx: Context, member: discord.Member, game_server: int, name: str): + self._logger.debug(__name__, f"Received command register minecraft {ctx}") + + minecraft_id = None + try: + self._logger.debug(__name__, f"Try to get minecraft id for {name}") + response = requests.get(url=f"https://api.mojang.com/users/profiles/minecraft/{name}") + if len(response.content) == 0: + await self._message_service.send_interaction_msg( + ctx.interaction, self._t.transform("modules.base.register.not_found") + ) + return + + minecraft_id = response.json()["id"] + except Exception as e: + self._logger.error(__name__, f"Get minecraft id for {name} failed", e) + await self._message_service.send_interaction_msg( + ctx.interaction, self._t.transform("modules.base.register.not_found") + ) + + if minecraft_id is None: + return + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + gs = self._game_server.get_game_server_by_id(game_server) + + game_ident = UserGameIdent(user, gs, minecraft_id) + self._user_game_ident.add_user_game_ident(game_ident) + self._db.save_changes() + + await self._message_service.send_interaction_msg( + ctx.interaction, self._t.transform("modules.base.register.success") + ) + + self._logger.trace(__name__, f"Finished register minecraft command") + + @minecraft.autocomplete("game_server") + async def game_server_autocomplete( + self, interaction: discord.Interaction, current: str + ) -> TList[app_commands.Choice[str]]: + server = self._servers.get_server_by_discord_id(interaction.guild.id) + game_servers = self._game_server.get_game_servers_by_server_id(server.id) + + return [ + app_commands.Choice(name=gs.name, value=gs.id) + for gs in self._client_utils.get_auto_complete_list(game_servers, current, lambda x: x.name) + ] diff --git a/kdb-bot/src/modules/base/command/unregister_group.py b/kdb-bot/src/modules/base/command/unregister_group.py new file mode 100644 index 00000000..4d5f796a --- /dev/null +++ b/kdb-bot/src/modules/base/command/unregister_group.py @@ -0,0 +1,86 @@ +from typing import List as TList + +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context + +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.helper.command_checks import CommandChecks +from bot_core.logging.command_logger import CommandLogger +from bot_data.abc.game_server_repository_abc import GameServerRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_game_ident_repository_abc import UserGameIdentRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC + + +class UnregisterGroup(DiscordCommandABC): + def __init__( + self, + logger: CommandLogger, + message_service: MessageServiceABC, + bot: DiscordBotServiceABC, + client_utils: ClientUtilsABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + game_server: GameServerRepositoryABC, + user_game_idents: UserGameIdentRepositoryABC, + db: DatabaseContextABC, + t: TranslatePipe, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._message_service = message_service + self._bot = bot + self._client_utils = client_utils + self._servers = servers + self._users = users + self._game_server = game_server + self._user_game_idents = user_game_idents + self._db = db + self._t = t + + self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") + + # @commands.hybrid_group() + # @commands.guild_only() + # async def unregister(self, ctx: Context): + # pass + + @commands.hybrid_command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def unregister(self, ctx: Context, member: discord.Member, game_server: int): + self._logger.debug(__name__, f"Received command unregister {ctx}") + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + ident = user.game_idents.where(lambda x: x.game_server.id == game_server).single() + self._user_game_idents.delete_user_game_ident(ident) + self._users.update_user(user) + self._db.save_changes() + + await self._message_service.send_interaction_msg( + ctx.interaction, self._t.transform("modules.base.unregister.success") + ) + + self._logger.trace(__name__, f"Finished unregister command") + + @unregister.autocomplete("game_server") + async def game_server_autocomplete( + self, interaction: discord.Interaction, current: str + ) -> TList[app_commands.Choice[str]]: + server = self._servers.get_server_by_discord_id(interaction.guild.id) + game_servers = self._game_server.get_game_servers_by_server_id(server.id) + + return [ + app_commands.Choice(name=gs.name, value=gs.id) + for gs in self._client_utils.get_auto_complete_list(game_servers, current, lambda x: x.name) + ] diff --git a/kdb-bot/src/modules/base/command/user_group.py b/kdb-bot/src/modules/base/command/user_group.py index b76a0c06..37570a70 100644 --- a/kdb-bot/src/modules/base/command/user_group.py +++ b/kdb-bot/src/modules/base/command/user_group.py @@ -21,6 +21,8 @@ from bot_data.abc.user_joined_voice_channel_repository_abc import ( UserJoinedVoiceChannelRepositoryABC, ) from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC +from modules.base.service.user_warnings_service import UserWarningsService from modules.level.service.level_service import LevelService from modules.permission.abc.permission_service_abc import PermissionServiceABC @@ -42,6 +44,8 @@ class UserGroup(DiscordCommandABC): translate: TranslatePipe, date: DateTimeOffsetPipe, level: LevelService, + user_warnings: UserWarningsRepositoryABC, + user_warnings_service: UserWarningsService, ): DiscordCommandABC.__init__(self) @@ -59,6 +63,8 @@ class UserGroup(DiscordCommandABC): self._t = translate self._date = date self._level = level + self._user_warnings = user_warnings + self._user_warnings_service = user_warnings_service self._logger.trace(__name__, f"Loaded command service: {type(self).__name__}") @@ -81,7 +87,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": if is_remove: @@ -125,8 +131,8 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) - joins = self._user_joined_servers.get_user_joined_servers_by_user_id(user.user_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + joins = self._user_joined_servers.get_user_joined_servers_by_user_id(user.id) embed = discord.Embed(title=member.name, description=member.name, color=int("ef9d0d", 16)) @@ -181,9 +187,13 @@ class UserGroup(DiscordCommandABC): ) if is_mod or member == ctx.author: + warnings_string = "" + for warning in self._user_warnings.get_user_warnings_by_user_id(user.id): + warnings_string += f"{warning.id} - {warning.description}\n" + embed.add_field( name=self._t.transform("modules.base.user.atr.warnings"), - value=self._t.transform("common.not_implemented_yet"), + value=warnings_string, inline=False, ) @@ -206,7 +216,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": value = str(user.xp) @@ -241,7 +251,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": try: @@ -312,7 +322,7 @@ class UserGroup(DiscordCommandABC): member = ctx.author server = self._servers.find_server_by_discord_id(ctx.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if atr == "xp": user.xp = 0 @@ -321,7 +331,7 @@ class UserGroup(DiscordCommandABC): await self._level.check_level(member) elif atr == "ontime": - self._user_joined_voice_channel.delete_user_joined_voice_channel_by_user_id(user.user_id) + self._user_joined_voice_channel.delete_user_joined_voice_channel_by_user_id(user.id) self._db.save_changes() else: @@ -341,3 +351,72 @@ class UserGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> List[app_commands.Choice[str]]: return [app_commands.Choice(name=value, value=key) for key, value in self._atr_list] + + @user.group() + @commands.guild_only() + async def warning(self, ctx: Context): + pass + + @warning.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def show(self, ctx: Context, member: discord.Member, wait: int = None): + self._logger.debug(__name__, f"Received command user warning show {ctx}:{member}") + + server = self._servers.find_server_by_discord_id(ctx.guild.id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + + embed = discord.Embed( + title=member.name, description=self._t.transform("modules.base.user.atr.warnings"), color=int("ef9d0d", 16) + ) + + warnings = self._user_warnings.get_user_warnings_by_user_id(user.id) + warnings_id_string = "" + for warning in warnings: + warnings_id_string += f"{warning.id}\n" + + warnings_description_string = "" + for warning in warnings: + warnings_description_string += f"{warning.description}\n" + + embed.add_field( + name=self._t.transform("modules.base.warnings.show.id"), + value=warnings_id_string, + inline=True, + ) + embed.add_field( + name=self._t.transform("modules.base.warnings.show.description"), + value=warnings_description_string, + inline=True, + ) + await self._message_service.send_interaction_msg(ctx.interaction, embed, wait_before_delete=wait) + self._logger.trace(__name__, f"Finished user warning show command") + + @warning.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def add(self, ctx: Context, member: discord.Member, description: str): + self._logger.debug(__name__, f"Received command user warning add {ctx}:{member},{description}") + try: + await self._user_warnings_service.add_warnings(member, description, ctx.author.id) + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.warnings.add.success")) + except Exception as e: + self._logger.error(__name__, f"Adding user warning failed", e) + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.warnings.add.failed")) + self._logger.trace(__name__, f"Finished user warning add command") + + @warning.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def remove(self, ctx: Context, warning_id: int): + self._logger.debug(__name__, f"Received command user warning remove {ctx}:{warning_id}") + try: + await self._user_warnings_service.remove_warnings(warning_id) + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.warnings.remove.success")) + except Exception as e: + self._logger.error(__name__, f"Removing user warning failed", e) + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.base.warnings.remove.failed")) + self._logger.trace(__name__, f"Finished user warning remove command") diff --git a/kdb-bot/src/modules/base/configuration/__init__.py b/kdb-bot/src/modules/base/configuration/__init__.py index 157e31db..b910f85e 100644 --- a/kdb-bot/src/modules/base/configuration/__init__.py +++ b/kdb-bot/src/modules/base/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.configuration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/configuration/base_server_settings.py b/kdb-bot/src/modules/base/configuration/base_server_settings.py index 531e44c9..f0538374 100644 --- a/kdb-bot/src/modules/base/configuration/base_server_settings.py +++ b/kdb-bot/src/modules/base/configuration/base_server_settings.py @@ -15,10 +15,12 @@ class BaseServerSettings(ConfigurationModelABC): self._xp_per_reaction: int = 0 self._max_message_xp_per_hour: int = 0 self._xp_per_ontime_hour: int = 0 + self._xp_per_event_participation: int = 0 self._afk_channel_ids: List[int] = List(int) self._afk_command_channel_id: int = 0 self._help_command_reference_url: str = "" self._help_voice_channel_id: int = 0 + self._team_channel_id: int = 0 self._ping_urls = List(str) @property @@ -45,6 +47,10 @@ class BaseServerSettings(ConfigurationModelABC): def xp_per_ontime_hour(self) -> int: return self._xp_per_ontime_hour + @property + def xp_per_event_participation(self) -> int: + return self._xp_per_event_participation + @property def afk_channel_ids(self) -> List[int]: return self._afk_channel_ids @@ -57,6 +63,10 @@ class BaseServerSettings(ConfigurationModelABC): def help_command_reference_url(self) -> str: return self._help_command_reference_url + @property + def team_channel_id(self) -> int: + return self._team_channel_id + @property def help_voice_channel_id(self) -> int: return self._help_voice_channel_id @@ -73,11 +83,15 @@ class BaseServerSettings(ConfigurationModelABC): self._xp_per_reaction = int(settings["XpPerReaction"]) self._max_message_xp_per_hour = int(settings["MaxMessageXpPerHour"]) self._xp_per_ontime_hour = int(settings["XpPerOntimeHour"]) + self._xp_per_event_participation = ( + 0 if "XpPerEventParticipation" not in settings else settings["XpPerEventParticipation"] + ) for index in settings["AFKChannelIds"]: self._afk_channel_ids.append(int(index)) self._afk_command_channel_id = settings["AFKCommandChannelId"] self._help_command_reference_url = settings["HelpCommandReferenceUrl"] self._help_voice_channel_id = settings["HelpVoiceChannelId"] + self._team_channel_id = settings["TeamChannelId"] for url in settings["PingURLs"]: self._ping_urls.append(url) except Exception as e: diff --git a/kdb-bot/src/modules/base/events/__init__.py b/kdb-bot/src/modules/base/events/__init__.py index e6276fe1..6e5e6326 100644 --- a/kdb-bot/src/modules/base/events/__init__.py +++ b/kdb-bot/src/modules/base/events/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.events" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/events/base_on_command_event.py b/kdb-bot/src/modules/base/events/base_on_command_event.py index 7b46564b..14ff7287 100644 --- a/kdb-bot/src/modules/base/events/base_on_command_event.py +++ b/kdb-bot/src/modules/base/events/base_on_command_event.py @@ -64,7 +64,7 @@ class BaseOnCommandEvent(OnCommandABC): user: Optional[User] = None try: - user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return diff --git a/kdb-bot/src/modules/base/events/base_on_member_join_event.py b/kdb-bot/src/modules/base/events/base_on_member_join_event.py index 1913532a..3acfe4aa 100644 --- a/kdb-bot/src/modules/base/events/base_on_member_join_event.py +++ b/kdb-bot/src/modules/base/events/base_on_member_join_event.py @@ -85,7 +85,7 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): try: server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is not None: self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) self._db.save_changes() @@ -94,7 +94,7 @@ class BaseOnMemberJoinEvent(OnMemberJoinABC): self._logger.debug(__name__, f"Add user: {member.id}") self._users.add_user(User(member.id, 0, server)) self._db.save_changes() - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) self._user_joins.add_user_joined_server(UserJoinedServer(user, datetime.now())) self._db.save_changes() except Exception as e: diff --git a/kdb-bot/src/modules/base/events/base_on_member_remove_event.py b/kdb-bot/src/modules/base/events/base_on_member_remove_event.py index ba9217f0..211f8c57 100644 --- a/kdb-bot/src/modules/base/events/base_on_member_remove_event.py +++ b/kdb-bot/src/modules/base/events/base_on_member_remove_event.py @@ -47,17 +47,17 @@ class BaseOnMemberRemoveEvent(OnMemberRemoveABC): try: server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.error(__name__, f"Cannot find user {member}") return - join = self._user_joins.get_active_user_joined_server_by_user_id(user.user_id) + join = self._user_joins.get_active_user_joined_server_by_user_id(user.id) join.leaved_on = datetime.now() self._user_joins.update_user_joined_server(join) self._db.save_changes() except Exception as e: - self._logger.error(__name__, f"Cannot get user {member.id}", e) + self._logger.error(__name__, f"Cannot remove user {member.id}", e) @EventChecks.check_is_ready() async def on_member_remove(self, member: discord.Member): diff --git a/kdb-bot/src/modules/base/events/base_on_message_delete_event.py b/kdb-bot/src/modules/base/events/base_on_message_delete_event.py index 2ae8172a..6320269a 100644 --- a/kdb-bot/src/modules/base/events/base_on_message_delete_event.py +++ b/kdb-bot/src/modules/base/events/base_on_message_delete_event.py @@ -52,7 +52,7 @@ class BaseOnMessageDeleteEvent(OnMessageDeleteABC): user: Optional[User] = None try: - user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return diff --git a/kdb-bot/src/modules/base/events/base_on_message_event.py b/kdb-bot/src/modules/base/events/base_on_message_event.py index 85578fda..72637252 100644 --- a/kdb-bot/src/modules/base/events/base_on_message_event.py +++ b/kdb-bot/src/modules/base/events/base_on_message_event.py @@ -57,7 +57,7 @@ class BaseOnMessageEvent(OnMessageABC): user: Optional[User] = None try: - user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return diff --git a/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py new file mode 100644 index 00000000..5b9cf901 --- /dev/null +++ b/kdb-bot/src/modules/base/events/base_on_scheduled_event_update_event.py @@ -0,0 +1,39 @@ +import discord +from cpl_core.logging import LoggerABC +from cpl_discord.events.on_scheduled_event_update_abc import OnScheduledEventUpdateABC +from cpl_discord.service import DiscordBotServiceABC +from discord import EventStatus + +from modules.base.model.active_event import ActiveEvent +from modules.base.service.event_service import EventService + + +class BaseOnScheduledEventUpdateEvent(OnScheduledEventUpdateABC): + def __init__( + self, + logger: LoggerABC, + bot: DiscordBotServiceABC, + events: EventService, + ): + OnScheduledEventUpdateABC.__init__(self) + + self._logger = logger + self._bot = bot + self._events = events + + async def on_scheduled_event_update(self, before: discord.ScheduledEvent, after: discord.ScheduledEvent): + self._logger.debug(__name__, f"Module {type(self)} started") + + # save started event + if before.status != after.status and after.status == EventStatus.active: + self._events.add_event(ActiveEvent(after)) + # delete stopped event + if before.status != after.status and ( + after.status.value == EventStatus.cancelled.value or after.status.value == EventStatus.completed.value + ): + event = self._events.get_active_event(after) + if event is None: + return + self._events.remove_event(event) + + self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py index 253170f5..c2a25a32 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py @@ -48,10 +48,10 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._logger.info(__name__, f"Module {type(self)} loaded") - def _switch_voice_state(self, dc_user_id: int, before_dc_channel_id: int, after_dc_channel_id: int, server: Server): + def _update_voice_state(self, joined: bool, dc_user_id: int, channel_id: int, server: Server): user: Optional[User] = None try: - user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.id) except Exception as e: self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) return @@ -61,60 +61,19 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): return try: - end_date = datetime.now() - join = UserJoinedVoiceChannel(user, before_dc_channel_id, end_date) - self._user_joins_vc.add_user_joined_voice_channel(join) - - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) - - join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.user_id) - join.leaved_on = end_date - - # ontime as hours - ontime = round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2) - old_xp = user.xp - user.xp += round(ontime * settings.xp_per_ontime_hour) - - self._user_joins_vc.update_user_joined_voice_channel(join) - self._users.update_user(user) - self._db.save_changes() - - self._logger.debug( - __name__, - f"User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}", - ) - except Exception as e: - self._logger.error(__name__, f"Ontime validation failed", e) - - def _update_voice_state(self, joined: bool, dc_user_id: int, dc_channel_id: int, server: Server): - user: Optional[User] = None - try: - user = self._users.get_user_by_discord_id_and_server_id(dc_user_id, server.server_id) - except Exception as e: - self._logger.error(__name__, f"Cannot get user {dc_user_id}", e) - return - - if user is None: - self._logger.error(__name__, f"User not found {dc_user_id}") - return - - try: - end_date = datetime.now() if joined: - join = UserJoinedVoiceChannel(user, dc_channel_id, end_date) + join = UserJoinedVoiceChannel(user, channel_id, datetime.now()) self._user_joins_vc.add_user_joined_voice_channel(join) self._db.save_changes() return - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) - join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.user_id) - join.leaved_on = end_date + join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.id) + join.leaved_on = datetime.now() - # ontime as hours - ontime = round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2) old_xp = user.xp - user.xp += round(ontime * settings.xp_per_ontime_hour) + user.xp += round(join.time * settings.xp_per_ontime_hour) self._user_joins_vc.update_user_joined_voice_channel(join) self._users.update_user(user) @@ -122,7 +81,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._logger.debug( __name__, - f"User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}", + f"User {user} leaved_on {join.leaved_on}. Ontime: {join.time}h | xp: from {old_xp} to {user.xp}", ) except Exception as e: self._logger.error(__name__, f"Ontime validation failed", e) @@ -173,11 +132,9 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._logger.trace(__name__, f"User {member.id} left {before.channel}") self._update_voice_state(False, member.id, before.channel.id, server) - elif ( - before.channel.id not in settings.afk_channel_ids - and after.channel.id not in settings.afk_channel_ids - ): + else: self._logger.trace(__name__, f"User {member.id} switched to {after.channel}") - self._switch_voice_state(member.id, before.channel.id, after.channel.id, server) + self._update_voice_state(False, member.id, before.channel.id, server) + self._update_voice_state(True, member.id, after.channel.id, server) except Exception as e: self._logger.error(__name__, f"Cannot handle voice state for user {member.id}", e) diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py index 15405cc8..4f640ff0 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_help_channel.py @@ -43,7 +43,7 @@ class BaseOnVoiceStateUpdateEventHelpChannel(OnVoiceStateUpdateABC): ): self._logger.debug(__name__, f"Module {type(self)} started") server = self._servers.get_server_by_discord_id(member.guild.id) - settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + settings: BaseServerSettings = self._base_helper.get_config(server.discord_id) if after.channel is None or after.channel.id != settings.help_voice_channel_id: return @@ -57,4 +57,4 @@ class BaseOnVoiceStateUpdateEventHelpChannel(OnVoiceStateUpdateABC): a, ) - self._logger.debug(__name__, f"Module {type(self)} stopped") + self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py new file mode 100644 index 00000000..54050851 --- /dev/null +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event_scheduled_event_bonus.py @@ -0,0 +1,66 @@ +import discord +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_core.logging import LoggerABC +from cpl_discord.events import OnVoiceStateUpdateABC + +from bot_core.helper.event_checks import EventChecks +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from modules.base.abc.base_helper_abc import BaseHelperABC +from modules.base.configuration.base_server_settings import BaseServerSettings +from modules.base.service.event_service import EventService + + +class BaseOnVoiceStateUpdateEventScheduledEventBonus(OnVoiceStateUpdateABC): + def __init__( + self, + config: ConfigurationABC, + logger: LoggerABC, + base_helper: BaseHelperABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + events: EventService, + db: DatabaseContextABC, + ): + OnVoiceStateUpdateABC.__init__(self) + self._config = config + self._logger = logger + self._base_helper = base_helper + self._servers = servers + self._users = users + self._events = events + self._db = db + + self._logger.info(__name__, f"Module {type(self)} loaded") + + @EventChecks.check_is_ready() + async def on_voice_state_update( + self, + member: discord.Member, + before: discord.VoiceState, + after: discord.VoiceState, + ): + self._logger.debug(__name__, f"Module {type(self)} started") + if member.bot or after.channel is None: + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + active_event = self._events.get_active_event_by_channel_id(after.channel.id) + if active_event is None: + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + if active_event.participants.any(lambda x: x.user_id == user.user_id): + self._logger.debug(__name__, f"Module {type(self)} stopped") + return + + settings: BaseServerSettings = self._base_helper.get_config(server.discord_server_id) + user.xp += settings.xp_per_event_participation + self._users.update_user(user) + self._db.save_changes() + active_event.participants.append(user) + + self._logger.debug(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/base/helper/__init__.py b/kdb-bot/src/modules/base/helper/__init__.py index a30d1bf3..12f0a6ff 100644 --- a/kdb-bot/src/modules/base/helper/__init__.py +++ b/kdb-bot/src/modules/base/helper/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.helper" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/helper/base_reaction_handler.py b/kdb-bot/src/modules/base/helper/base_reaction_handler.py index 3bb06cdc..9fb4f89e 100644 --- a/kdb-bot/src/modules/base/helper/base_reaction_handler.py +++ b/kdb-bot/src/modules/base/helper/base_reaction_handler.py @@ -52,6 +52,9 @@ class BaseReactionHandler: __name__, f"{log_msg} to message {LogMessageHelper.get_log_string(message)}", ) + if member == message.author: + self._logger.debug(__name__, f"Skipping reaction handling") + return except Exception as e: self._logger.error(__name__, f"Getting message for reaction logging failed", e) self._logger.info(__name__, f"{log_msg} to message {payload.message_id}") @@ -62,7 +65,7 @@ class BaseReactionHandler: return server = self._servers.get_server_by_discord_id(guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) settings: BaseServerSettings = self._base_helper.get_config(guild.id) if r_type == "add": diff --git a/kdb-bot/src/modules/base/model/__init__.py b/kdb-bot/src/modules/base/model/__init__.py new file mode 100644 index 00000000..828f8215 --- /dev/null +++ b/kdb-bot/src/modules/base/model/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- + +""" +bot Keksdose bot +~~~~~~~~~~~~~~~~~~~ + +Discord bot for the Keksdose discord Server + +:copyright: (c) 2022 - 2023 sh-edraft.de +:license: MIT, see LICENSE for more details. + +""" + +__title__ = "modules.base.model" +__author__ = "Sven Heidemann" +__license__ = "MIT" +__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" +__version__ = "1.0.0" + +from collections import namedtuple + + +# imports: + +VersionInfo = namedtuple("VersionInfo", "major minor micro") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/model/active_event.py b/kdb-bot/src/modules/base/model/active_event.py new file mode 100644 index 00000000..63861e0c --- /dev/null +++ b/kdb-bot/src/modules/base/model/active_event.py @@ -0,0 +1,18 @@ +import discord +from cpl_query.extension import List + +from bot_data.model.user import User + + +class ActiveEvent: + def __init__(self, event: discord.ScheduledEvent): + self._event = event + self._participants = List(User) + + @property + def event(self) -> discord.ScheduledEvent: + return self._event + + @property + def participants(self) -> List[User]: + return self._participants diff --git a/kdb-bot/src/modules/base/service/__init__.py b/kdb-bot/src/modules/base/service/__init__.py index 7b569a64..53a3894f 100644 --- a/kdb-bot/src/modules/base/service/__init__.py +++ b/kdb-bot/src/modules/base/service/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.service" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/base/service/event_service.py b/kdb-bot/src/modules/base/service/event_service.py new file mode 100644 index 00000000..8073b3d3 --- /dev/null +++ b/kdb-bot/src/modules/base/service/event_service.py @@ -0,0 +1,31 @@ +from typing import Optional + +import discord +from cpl_query.extension import List + +from modules.base.model.active_event import ActiveEvent + + +class EventService: + def __init__(self): + self._active_events = List(ActiveEvent) + + def add_event(self, event: ActiveEvent): + if self._active_events.contains(event): + return + + self._active_events.add(event) + + def get_active_event(self, event: discord.ScheduledEvent) -> Optional[ActiveEvent]: + return self._active_events.where(lambda x: x.event.id == event.id).single_or_default() + + def get_active_event_by_channel_id(self, channel_id: int) -> Optional[ActiveEvent]: + return self._active_events.where( + lambda x: x.event.channel is not None and x.event.channel.id == channel_id + ).single_or_default() + + def remove_event(self, event: ActiveEvent): + if not self._active_events.contains(event): + return + + self._active_events.remove(event) diff --git a/kdb-bot/src/modules/base/service/user_warnings_service.py b/kdb-bot/src/modules/base/service/user_warnings_service.py new file mode 100644 index 00000000..d80a674c --- /dev/null +++ b/kdb-bot/src/modules/base/service/user_warnings_service.py @@ -0,0 +1,133 @@ +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_core.logging import LoggerABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe + +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_data.abc.level_repository_abc import LevelRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.abc.user_warnings_repository_abc import UserWarningsRepositoryABC +from bot_data.model.user import User +from bot_data.model.user_warnings import UserWarnings +from modules.base.abc.base_helper_abc import BaseHelperABC +from modules.base.configuration.base_server_settings import BaseServerSettings +from modules.level.service.level_service import LevelService +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class UserWarningsService: + def __init__( + self, + logger: LoggerABC, + db: DatabaseContextABC, + bot: DiscordBotServiceABC, + warnings: UserWarningsRepositoryABC, + users: UserRepositoryABC, + servers: ServerRepositoryABC, + levels: LevelRepositoryABC, + level_service: LevelService, + message_service: MessageServiceABC, + t: TranslatePipe, + permissions: PermissionServiceABC, + base_helper: BaseHelperABC, + ): + self._logger = logger + self._db = db + self._bot = bot + self._warnings = warnings + self._users = users + self._servers = servers + self._levels = levels + self._level_service = level_service + self._message_service = message_service + self._t = t + self._permissions = permissions + self._base_helper = base_helper + + async def notify_team(self, member: discord.Member, description: str, removed=False): + try: + settings: BaseServerSettings = self._base_helper.get_config(member.guild.id) + channel = member.guild.get_channel(settings.team_channel_id) + if removed: + translation = self._t.transform("modules.base.warnings.team_removed").format( + description, member.mention + ) + else: + translation = self._t.transform("modules.base.warnings.team_warned").format(member.mention, description) + + self._bot.loop.create_task(self._message_service.send_channel_message(channel, translation)) + except Exception as e: + self._logger.error(__name__, f"Team notification for user warning failed!", e) + + async def notify_user(self, member: discord.Member, message: str): + try: + # run as task to keep the interaction alive + self._bot.loop.create_task(self._message_service.send_dm_message(message, member)) + except Exception as e: + self._logger.error(__name__, f"User notification for user warning failed!", e) + + async def check_for_warnings(self, member: discord.Member, user: User): + existing_warnings = self._warnings.get_user_warnings_by_user_id(user.id) + + if existing_warnings.count() == 1: + await self.notify_user(member, self._t.transform("modules.base.warnings.first")) + + elif existing_warnings.count() == 2: + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + level = self._level_service.get_level(user) + levels = self._levels.get_levels_by_server_id(server.id).order_by(lambda l: l.min_xp) + + new_level = levels.where(lambda l: l.min_xp < level.min_xp).last_or_default() + if new_level is not None: + user.xp = new_level.min_xp + self._users.update_user(user) + self._db.save_changes() + await self.notify_user(member, self._t.transform("modules.base.warnings.second")) + + elif existing_warnings.count() == 3: + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + levels = self._levels.get_levels_by_server_id(server.id) + + new_level = levels.where(lambda l: l.min_xp > 0).order_by(lambda l: l.min_xp).last_or_default() + if new_level is not None: + user.xp = new_level.min_xp + self._users.update_user(user) + self._db.save_changes() + await self.notify_user(member, self._t.transform("modules.base.warnings.third")) + + elif existing_warnings.count() >= 4: + user.xp = 0 + self._users.update_user(user) + self._db.save_changes() + await self.notify_team(member, self._t.transform("modules.base.warnings.kick").format(member.mention)) + await member.kick() + + async def add_warnings(self, member: discord.Member, description: str, author_id: int = None): + server = self._servers.get_server_by_discord_id(member.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) + + author = None + if author_id is not None: + author = self._users.get_user_by_discord_id_and_server_id(author_id, server.id) + + warning = UserWarnings(description, user, author) + self._warnings.add_user_warnings(warning) + self._db.save_changes() + await self.notify_user(member, self._t.transform("modules.base.warnings.warned").format(warning.description)) + await self.notify_team(member, warning.description) + await self.check_for_warnings(member, user) + + async def remove_warnings(self, id: int): + warning = self._warnings.get_user_warnings_by_id(id) + self._warnings.delete_user_warnings(warning) + self._db.save_changes() + + guild = self._bot.get_guild(warning.user.server.discord_id) + member = guild.get_member(warning.user.discord_id) + + await self.notify_user(member, self._t.transform("modules.base.warnings.removed").format(warning.description)) + await self.notify_team(member, warning.description, removed=True) diff --git a/kdb-bot/src/modules/base/thread/__init__.py b/kdb-bot/src/modules/base/thread/__init__.py index f85b1e37..13db833f 100644 --- a/kdb-bot/src/modules/base/thread/__init__.py +++ b/kdb-bot/src/modules/base/thread/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.base.thread" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/boot_log/__init__.py b/kdb-bot/src/modules/boot_log/__init__.py index 5696e43a..dc8fd16b 100644 --- a/kdb-bot/src/modules/boot_log/__init__.py +++ b/kdb-bot/src/modules/boot_log/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.boot_log" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/boot_log/boot-log.json b/kdb-bot/src/modules/boot_log/boot-log.json index 29921d48..aceea3f7 100644 --- a/kdb-bot/src/modules/boot_log/boot-log.json +++ b/kdb-bot/src/modules/boot_log/boot-log.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "boot-log", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py b/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py index bfa0367d..58c2b5c4 100644 --- a/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py +++ b/kdb-bot/src/modules/boot_log/boot_log_on_ready_event.py @@ -68,9 +68,11 @@ class BootLogOnReadyEvent(OnReadyABC): self._logger.error(__name__, f"Config {type(self).__name__}_{g.id} not found!") return - await self._message_service.send_channel_message( - self._bot.get_channel(module_settings.login_message_channel_id), - self._t.transform("modules.boot_log.login_message").format(init_time), + self._bot.loop.create_task( + self._message_service.send_channel_message( + self._bot.get_channel(module_settings.login_message_channel_id), + self._t.transform("modules.boot_log.login_message").format(init_time), + ) ) self._config.add_configuration("IS_READY", "true") diff --git a/kdb-bot/src/modules/boot_log/configuration/__init__.py b/kdb-bot/src/modules/boot_log/configuration/__init__.py index 3a3d3d8e..1bcfbf63 100644 --- a/kdb-bot/src/modules/boot_log/configuration/__init__.py +++ b/kdb-bot/src/modules/boot_log/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.boot_log.configuration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/database/__init__.py b/kdb-bot/src/modules/database/__init__.py index ecdc13f0..95a49ce8 100644 --- a/kdb-bot/src/modules/database/__init__.py +++ b/kdb-bot/src/modules/database/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.database" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/database/database.json b/kdb-bot/src/modules/database/database.json index 52033376..1b9f8709 100644 --- a/kdb-bot/src/modules/database/database.json +++ b/kdb-bot/src/modules/database/database.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "database", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/kdb-bot/src/modules/database/database_extension.py b/kdb-bot/src/modules/database/database_extension.py index 88682ca0..1c26e70b 100644 --- a/kdb-bot/src/modules/database/database_extension.py +++ b/kdb-bot/src/modules/database/database_extension.py @@ -1,3 +1,4 @@ +import sys from datetime import datetime from cpl_core.application.application_extension_abc import ApplicationExtensionABC @@ -9,7 +10,6 @@ from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum from bot_core.configuration.feature_flags_settings import FeatureFlagsSettings from bot_core.logging.database_logger import DatabaseLogger from bot_data.service.migration_service import MigrationService -from bot_data.service.seeder_service import SeederService class DatabaseExtension(ApplicationExtensionABC): @@ -25,3 +25,6 @@ class DatabaseExtension(ApplicationExtensionABC): config.add_configuration("Database_StartTime", str(datetime.now())) migrations: MigrationService = services.get_service(MigrationService) migrations.migrate() + if config.get_configuration("MIGRATION_ONLY"): + logger.warn(__name__, "Migrations finished. Stopping application...") + sys.exit() diff --git a/kdb-bot/src/modules/database/database_on_ready_event.py b/kdb-bot/src/modules/database/database_on_ready_event.py index 694628e5..8d512035 100644 --- a/kdb-bot/src/modules/database/database_on_ready_event.py +++ b/kdb-bot/src/modules/database/database_on_ready_event.py @@ -11,6 +11,7 @@ from bot_core.logging.database_logger import DatabaseLogger from bot_core.pipes.date_time_offset_pipe import DateTimeOffsetPipe from bot_data.abc.client_repository_abc import ClientRepositoryABC from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC +from bot_data.abc.user_joined_game_server_repository_abc import UserJoinedGameServerRepositoryABC from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC from bot_data.abc.user_joined_voice_channel_repository_abc import ( UserJoinedVoiceChannelRepositoryABC, @@ -41,6 +42,7 @@ class DatabaseOnReadyEvent(OnReadyABC): known_users: KnownUserRepositoryABC, user_joins: UserJoinedServerRepositoryABC, user_joins_vc: UserJoinedVoiceChannelRepositoryABC, + user_joined_gs: UserJoinedGameServerRepositoryABC, dtp: DateTimeOffsetPipe, ): self._config = config @@ -55,6 +57,7 @@ class DatabaseOnReadyEvent(OnReadyABC): self._known_users = known_users self._user_joins = user_joins self._user_joins_vc = user_joins_vc + self._user_joined_gs = user_joined_gs self._dtp = dtp OnReadyABC.__init__(self) @@ -141,7 +144,7 @@ class DatabaseOnReadyEvent(OnReadyABC): if server is None: self._logger.fatal(__name__, f"Server not found in database: {g.id}") - client = self._clients.find_client_by_server_id(server.server_id) + client = self._clients.find_client_by_server_id(server.id) if client is not None: continue @@ -153,7 +156,7 @@ class DatabaseOnReadyEvent(OnReadyABC): self._clients.add_client(Client(self._bot.user.id, 0, 0, 0, 0, 0, server)) self._db_context.save_changes() - client = self._clients.find_client_by_server_id(server.server_id) + client = self._clients.find_client_by_server_id(server.id) if client is None: self._logger.fatal( __name__, @@ -184,7 +187,7 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) if user is not None: continue @@ -217,11 +220,11 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {u.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(u.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(u.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {u.id}") - join = self._user_joins.find_active_user_joined_server_by_user_id(user.user_id) + join = self._user_joins.find_active_user_joined_server_by_user_id(user.id) if join is not None: continue @@ -250,7 +253,7 @@ class DatabaseOnReadyEvent(OnReadyABC): joins = self._user_joins.get_user_joined_servers() for join in joins: join: UserJoinedServer = join - if join.user.server.discord_server_id != guild.id: + if join.user.server.discord_id != guild.id: continue if join.leaved_on is not None: @@ -283,11 +286,11 @@ class DatabaseOnReadyEvent(OnReadyABC): self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") continue - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {member.id}") - joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.user_id) + joins = self._user_joins_vc.find_active_user_joined_voice_channels_by_user_id(user.id) if joins is None or len(joins) == 0: continue @@ -315,7 +318,7 @@ class DatabaseOnReadyEvent(OnReadyABC): if member.voice is None or member.voice.channel.id in settings.afk_channel_ids: continue - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.fatal(__name__, f"User not found in database: {member.id}") @@ -327,17 +330,60 @@ class DatabaseOnReadyEvent(OnReadyABC): except Exception as e: self._logger.error(__name__, f"Cannot get UserJoinedVoiceChannel", e) + def _check_user_joined_gs(self): + self._logger.debug(__name__, f"Start checking UserJoinedGameServer table") + for guild in self._bot.guilds: + guild: discord.Guild = guild + + server = self._servers.find_server_by_discord_id(guild.id) + if server is None: + self._logger.fatal(__name__, f"Server not found in database: {guild.id}") + + try: + for member in guild.members: + if member.bot: + self._logger.trace(__name__, f"User {member.id} is ignored, because its a bot") + continue + + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) + if user is None: + self._logger.fatal(__name__, f"User not found in database: {member.id}") + + joins = self._user_joined_gs.find_active_user_joined_game_servers_by_user_id(user.id) + if joins is None or len(joins) == 0: + continue + + for join in joins: + self._logger.warn( + __name__, + f"Active UserJoinedGameServer found in database: {guild.id}:{member.id}@{join.joined_on}", + ) + join.leaved_on = datetime.now() + settings: BaseServerSettings = self._config.get_configuration(f"BaseServerSettings_{guild.id}") + + if ( + (join.leaved_on - join.joined_on).total_seconds() / 60 / 60 + ) > settings.max_voice_state_hours: + join.leaved_on = join.joined_on + timedelta(hours=settings.max_voice_state_hours) + + self._user_joined_gs.update_user_joined_game_server(join) + # todo: maybe add XP + self._db_context.save_changes() + except Exception as e: + self._logger.error(__name__, f"Cannot get UserJoinedGameServer", e) + async def on_ready(self): self._logger.debug(__name__, f"Module {type(self)} started") - await self._seeder.seed() - self._check_known_users() self._check_servers() self._check_clients() self._check_users() self._check_user_joins() self._check_user_joins_vc() + self._check_user_joined_gs() + + await self._seeder.seed() self._validate_init_time() self._logger.trace(__name__, f"Module {type(self)} stopped") diff --git a/kdb-bot/src/modules/level/__init__.py b/kdb-bot/src/modules/level/__init__.py index aa3b114d..461af2eb 100644 --- a/kdb-bot/src/modules/level/__init__.py +++ b/kdb-bot/src/modules/level/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.level" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/level/command/__init__.py b/kdb-bot/src/modules/level/command/__init__.py index 70055185..e0922394 100644 --- a/kdb-bot/src/modules/level/command/__init__.py +++ b/kdb-bot/src/modules/level/command/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.level.command" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/level/command/level_group.py b/kdb-bot/src/modules/level/command/level_group.py index b508ead3..1e7c4ae5 100644 --- a/kdb-bot/src/modules/level/command/level_group.py +++ b/kdb-bot/src/modules/level/command/level_group.py @@ -108,7 +108,7 @@ class LevelGroup(DiscordCommandABC): self, interaction: discord.Interaction, current: str ) -> TList[app_commands.Choice[str]]: server = self._servers.get_server_by_discord_id(interaction.guild.id) - levels = self._levels.get_levels_by_server_id(server.server_id).select(lambda l: l.name) + levels = self._levels.get_levels_by_server_id(server.id).select(lambda l: l.name) return [ app_commands.Choice(name=level, value=level) for level in self._client_utils.get_auto_complete_list(levels, current) @@ -130,7 +130,7 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - levels = self._levels.get_levels_by_server_id(server.server_id) + levels = self._levels.get_levels_by_server_id(server.id) if levels.count() < 1: await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.level.error.nothing_found")) self._logger.trace(__name__, f"Finished command level list") @@ -187,7 +187,7 @@ class LevelGroup(DiscordCommandABC): server = self._servers.get_server_by_discord_id(ctx.guild.id) level = Level(name, color, min_xp, permissions, server) - levels = self._levels.get_levels_by_server_id(server.server_id) + levels = self._levels.get_levels_by_server_id(server.id) if levels.where(lambda l: l.name == level.name).first_or_default() is not None: self._logger.debug(__name__, f"Level with name {level.name} already exists") @@ -261,7 +261,7 @@ class LevelGroup(DiscordCommandABC): server = self._servers.get_server_by_discord_id(ctx.guild.id) level_from_db = ( - self._levels.get_levels_by_server_id(server.server_id).where(lambda l: l.name == level).single_or_default() + self._levels.get_levels_by_server_id(server.id).where(lambda l: l.name == level).single_or_default() ) if level_from_db is None: await self._message_service.send_ctx_msg( @@ -353,7 +353,7 @@ class LevelGroup(DiscordCommandABC): server = self._servers.get_server_by_discord_id(ctx.guild.id) level_from_db = ( - self._levels.get_levels_by_server_id(server.server_id).where(lambda l: l.name == level).first_or_default() + self._levels.get_levels_by_server_id(server.id).where(lambda l: l.name == level).first_or_default() ) if level_from_db is None: self._logger.debug(__name__, f"level {level} not found") @@ -399,9 +399,9 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) level = self._level_service.get_level(user) - levels = self._levels.get_levels_by_server_id(server.server_id).order_by(lambda l: l.min_xp) + levels = self._levels.get_levels_by_server_id(server.id).order_by(lambda l: l.min_xp) if level == levels.first(): await self._message_service.send_ctx_msg( @@ -441,9 +441,9 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) level = self._level_service.get_level(user) - levels = self._levels.get_levels_by_server_id(server.server_id).order_by(lambda l: l.min_xp) + levels = self._levels.get_levels_by_server_id(server.id).order_by(lambda l: l.min_xp) if level.name == levels.last().name: await self._message_service.send_ctx_msg( @@ -482,11 +482,9 @@ class LevelGroup(DiscordCommandABC): return server = self._servers.get_server_by_discord_id(ctx.guild.id) - user = self._users.get_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.get_user_by_discord_id_and_server_id(member.id, server.id) current_level = self._level_service.get_level(user) - new_level = ( - self._levels.get_levels_by_server_id(server.server_id).where(lambda l: l.name == level).single_or_default() - ) + new_level = self._levels.get_levels_by_server_id(server.id).where(lambda l: l.name == level).single_or_default() if new_level is None: await self._message_service.send_ctx_msg( diff --git a/kdb-bot/src/modules/level/configuration/__init__.py b/kdb-bot/src/modules/level/configuration/__init__.py index 6ba3abb5..b3d06aa2 100644 --- a/kdb-bot/src/modules/level/configuration/__init__.py +++ b/kdb-bot/src/modules/level/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.level.configuration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/level/events/__init__.py b/kdb-bot/src/modules/level/events/__init__.py index ba781410..80c5ac30 100644 --- a/kdb-bot/src/modules/level/events/__init__.py +++ b/kdb-bot/src/modules/level/events/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.level.events" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/level/level.json b/kdb-bot/src/modules/level/level.json index bbacdedc..fef52546 100644 --- a/kdb-bot/src/modules/level/level.json +++ b/kdb-bot/src/modules/level/level.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "level", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/modules/level/level_module.py b/kdb-bot/src/modules/level/level_module.py index 1e2295a9..be99518c 100644 --- a/kdb-bot/src/modules/level/level_module.py +++ b/kdb-bot/src/modules/level/level_module.py @@ -8,6 +8,7 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_data.abc.data_seeder_abc import DataSeederABC from modules.level.command.level_group import LevelGroup from modules.level.events.level_on_member_join_event import LevelOnMemberJoinEvent from modules.level.events.level_on_message_event import LevelOnMessageEvent @@ -29,7 +30,7 @@ class LevelModule(ModuleABC): env.set_working_directory(cwd) def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): - services.add_transient(LevelSeeder) + services.add_transient(DataSeederABC, LevelSeeder) services.add_transient(LevelService) # commands diff --git a/kdb-bot/src/modules/level/level_seeder.py b/kdb-bot/src/modules/level/level_seeder.py index 7a51e2df..1ed5ab7d 100644 --- a/kdb-bot/src/modules/level/level_seeder.py +++ b/kdb-bot/src/modules/level/level_seeder.py @@ -1,4 +1,5 @@ import discord +from cpl_core.database.context import DatabaseContextABC from cpl_discord.container import Guild from cpl_discord.service import DiscordBotServiceABC from discord import Permissions, Colour @@ -21,6 +22,7 @@ class LevelSeeder(DataSeederABC): level_repo: LevelRepositoryService, servers: ServerRepositoryABC, level: LevelService, + db: DatabaseContextABC, bot: DiscordBotServiceABC, ): DataSeederABC.__init__(self) @@ -29,6 +31,7 @@ class LevelSeeder(DataSeederABC): self._levels = level_repo self._servers = servers self._level = level + self._db = db self._bot = bot self._level_header = levels.level_header @@ -47,10 +50,11 @@ class LevelSeeder(DataSeederABC): ) self._logger.debug(__name__, f"Created role {level.name}") - levels = self._levels.find_levels_by_server_id(server.server_id) + levels = self._levels.find_levels_by_server_id(server.id) if levels is None or levels.where(lambda l: l.name == level.name).first_or_default() is None: self._levels.add_level(level) self._logger.debug(__name__, f"Saved level {level.name}") + self._db.save_changes() except discord.errors.Forbidden as e: self._logger.error(__name__, f"Creating level failed", e) level.permissions = 0 @@ -69,7 +73,7 @@ class LevelSeeder(DataSeederABC): if server is None: continue - levels = self._levels.find_levels_by_server_id(server.server_id) + levels = self._levels.find_levels_by_server_id(server.id) if levels is not None and levels.count() > 0: # create levels from db for level in levels: diff --git a/kdb-bot/src/modules/level/service/__init__.py b/kdb-bot/src/modules/level/service/__init__.py index 02b6de83..752b77c3 100644 --- a/kdb-bot/src/modules/level/service/__init__.py +++ b/kdb-bot/src/modules/level/service/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.level.service" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/level/service/level_service.py b/kdb-bot/src/modules/level/service/level_service.py index 192a7dde..2acfd6fc 100644 --- a/kdb-bot/src/modules/level/service/level_service.py +++ b/kdb-bot/src/modules/level/service/level_service.py @@ -1,5 +1,3 @@ -import asyncio - import discord from cpl_core.configuration import ConfigurationABC from cpl_core.database.context import DatabaseContextABC @@ -41,7 +39,7 @@ class LevelService: self._t = t def get_level(self, user: User) -> Level: - levels_by_server = self._levels.get_levels_by_server_id(user.server.server_id) + levels_by_server = self._levels.get_levels_by_server_id(user.server.id) levels = levels_by_server.order_by(lambda l: l.min_xp).where(lambda l: user.xp >= l.min_xp) if levels.count() == 0: @@ -50,8 +48,8 @@ class LevelService: return levels.last() async def set_level(self, user: User): - level_names = self._levels.get_levels_by_server_id(user.server.server_id).select(lambda l: l.name) - guild: Guild = self._bot.guilds.where(lambda g: g.id == user.server.discord_server_id).single() + level_names = self._levels.get_levels_by_server_id(user.server.id).select(lambda l: l.name) + guild: Guild = self._bot.guilds.where(lambda g: g.id == user.server.discord_id).single() member: Member = guild.members.where(lambda m: m.id == user.discord_id).single() level = self.get_level(user) @@ -59,6 +57,7 @@ class LevelService: if level_role in member.roles: return + notification_needed = False for role in member.roles: if role.name not in level_names.to_list(): continue @@ -66,6 +65,7 @@ class LevelService: try: self._logger.debug(__name__, f"Try to remove role {role.name} from {member.name}") await member.remove_roles(role) + notification_needed = True self._logger.info(__name__, f"Removed role {role.name} from {member.name}") except Exception as e: self._logger.error(__name__, f"Removing role {role.name} from {member.name} failed!", e) @@ -77,19 +77,20 @@ class LevelService: except Exception as e: self._logger.error(__name__, f"Adding role {level_role.name} to {member.name} failed!", e) - level_settings: LevelServerSettings = self._config.get_configuration(f"LevelServerSettings_{guild.id}") - await self._message_service.send_channel_message( - self._bot.get_channel(level_settings.changed_level_notification_channel), - self._t.transform("modules.level.new_level_message").format(member.mention, level.name), - is_persistent=True, - ) + if notification_needed: + level_settings: LevelServerSettings = self._config.get_configuration(f"LevelServerSettings_{guild.id}") + await self._message_service.send_channel_message( + self._bot.get_channel(level_settings.changed_level_notification_channel), + self._t.transform("modules.level.new_level_message").format(member.mention, level.name), + is_persistent=True, + ) async def check_level(self, member: discord.Member): if member.bot: return server = self._servers.get_server_by_discord_id(member.guild.id) - user = self._users.find_user_by_discord_id_and_server_id(member.id, server.server_id) + user = self._users.find_user_by_discord_id_and_server_id(member.id, server.id) if user is None: self._logger.warn(__name__, f"User not found {member.guild.name}@{member.name}") return diff --git a/kdb-bot/src/modules/permission/__init__.py b/kdb-bot/src/modules/permission/__init__.py index 6b084d9a..9562f0b7 100644 --- a/kdb-bot/src/modules/permission/__init__.py +++ b/kdb-bot/src/modules/permission/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.permission" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/permission/abc/__init__.py b/kdb-bot/src/modules/permission/abc/__init__.py index 11021cdb..4d367495 100644 --- a/kdb-bot/src/modules/permission/abc/__init__.py +++ b/kdb-bot/src/modules/permission/abc/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.permission.abc" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/permission/configuration/__init__.py b/kdb-bot/src/modules/permission/configuration/__init__.py index 8d659f2a..30127fba 100644 --- a/kdb-bot/src/modules/permission/configuration/__init__.py +++ b/kdb-bot/src/modules/permission/configuration/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.permission.configuration" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/permission/events/__init__.py b/kdb-bot/src/modules/permission/events/__init__.py index d67c3853..bed7cc4e 100644 --- a/kdb-bot/src/modules/permission/events/__init__.py +++ b/kdb-bot/src/modules/permission/events/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.permission.events" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/permission/permission.json b/kdb-bot/src/modules/permission/permission.json index 0a8acaaa..f1754590 100644 --- a/kdb-bot/src/modules/permission/permission.json +++ b/kdb-bot/src/modules/permission/permission.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "permission", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/modules/permission/service/__init__.py b/kdb-bot/src/modules/permission/service/__init__.py index 07c51a23..583bf14a 100644 --- a/kdb-bot/src/modules/permission/service/__init__.py +++ b/kdb-bot/src/modules/permission/service/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.permission.service" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/permission/service/permission_service.py b/kdb-bot/src/modules/permission/service/permission_service.py index e793ebe1..c13f517c 100644 --- a/kdb-bot/src/modules/permission/service/permission_service.py +++ b/kdb-bot/src/modules/permission/service/permission_service.py @@ -1,6 +1,6 @@ import discord -from cpl_core.logging import LoggerABC from cpl_core.configuration import ConfigurationABC +from cpl_core.logging import LoggerABC from cpl_discord.service import DiscordBotServiceABC from bot_core.configuration.bot_settings import BotSettings @@ -126,14 +126,15 @@ class PermissionService(PermissionServiceABC): return self._technicians def is_member_admin(self, member: discord.Member) -> bool: - return member.guild.id in self._admins and member in self._admins[member.guild.id] + return member is not None and member.guild.id in self._admins and member in self._admins[member.guild.id] def is_member_moderator(self, member: discord.Member) -> bool: return ( - member.guild.id in self._moderators + member is not None + and member.guild.id in self._moderators and member in self._moderators[member.guild.id] or self.is_member_admin(member) ) def is_member_technician(self, member: discord.Member) -> bool: - return member in self._technicians + return member is not None and member in self._technicians diff --git a/kdb-bot/src/modules/stats/command/__init__.py b/kdb-bot/src/modules/stats/command/__init__.py deleted file mode 100644 index abbec8b4..00000000 --- a/kdb-bot/src/modules/stats/command/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -bot Keksdose bot -~~~~~~~~~~~~~~~~~~~ - -Discord bot for the Keksdose discord Server - -:copyright: (c) 2022 - 2023 sh-edraft.de -:license: MIT, see LICENSE for more details. - -""" - -__title__ = "modules.stats.command" -__author__ = "Sven Heidemann" -__license__ = "MIT" -__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" - -from collections import namedtuple - - -# imports - -VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") diff --git a/kdb-bot/src/modules/stats/command/stats_group.py b/kdb-bot/src/modules/stats/command/stats_group.py deleted file mode 100644 index 7db65858..00000000 --- a/kdb-bot/src/modules/stats/command/stats_group.py +++ /dev/null @@ -1,232 +0,0 @@ -from typing import List as TList - -import discord -from cpl_core.database.context import DatabaseContextABC -from cpl_discord.command import DiscordCommandABC -from cpl_translation import TranslatePipe -from discord import app_commands -from discord.ext import commands -from discord.ext.commands import Context - -from bot_core.abc.client_utils_abc import ClientUtilsABC -from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.helper.command_checks import CommandChecks -from bot_core.logging.command_logger import CommandLogger -from bot_data.abc.server_repository_abc import ServerRepositoryABC -from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC -from modules.permission.abc.permission_service_abc import PermissionServiceABC -from modules.stats.service.statistic_service import StatisticService -from modules.stats.ui.add_statistic_form import AddStatisticForm - - -class StatsGroup(DiscordCommandABC): - def __init__( - self, - logger: CommandLogger, - message_service: MessageServiceABC, - client_utils: ClientUtilsABC, - translate: TranslatePipe, - permission_service: PermissionServiceABC, - statistic: StatisticService, - servers: ServerRepositoryABC, - stats: StatisticRepositoryABC, - db: DatabaseContextABC, - ): - DiscordCommandABC.__init__(self) - - self._logger = logger - self._client_utils = client_utils - self._message_service = message_service - self._t = translate - self._permissions = permission_service - self._statistic = statistic - self._servers = servers - self._stats = stats - self._db = db - - @commands.hybrid_group() - @commands.guild_only() - async def stats(self, ctx: Context): - pass - - @stats.command() - @commands.guild_only() - @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_moderator() - async def list(self, ctx: Context, wait: int = None): - self._logger.debug(__name__, f"Received command stats list {ctx}") - - if ctx.guild is None: - return - - embed = discord.Embed( - title=self._t.transform("modules.auto_role.list.title"), - description=self._t.transform("modules.auto_role.list.description"), - color=int("ef9d0d", 16), - ) - - server = self._servers.get_server_by_discord_id(ctx.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) - - if stats.count() == 0: - await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.list.nothing_found")) - return - - statistics = "" - descriptions = "" - for statistic in stats: - statistics += f"\n{statistic.name}" - descriptions += f"\n{statistic.description}" - - embed.add_field( - name=self._t.transform("modules.stats.list.statistic"), - value=statistics, - inline=True, - ) - embed.add_field( - name=self._t.transform("modules.stats.list.description"), - value=descriptions, - inline=True, - ) - await self._message_service.send_ctx_msg(ctx, embed, wait_before_delete=wait) - self._logger.trace(__name__, f"Finished command stats list") - - @stats.command() - @commands.guild_only() - @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_moderator() - async def view(self, ctx: Context, name: str, wait: int = None): - self._logger.debug(__name__, f"Received command stats view {ctx}:{name}") - - if ctx.guild is None: - return - - try: - server = self._servers.get_server_by_discord_id(ctx.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) - statistic = stats.where(lambda s: s.name == name).single() - result = await self._statistic.execute(statistic.code, server) - - embed = discord.Embed( - title=statistic.name, - description=statistic.description, - color=int("ef9d0d", 16), - ) - - for i in range(result.header.count()): - header = result.header[i] - value = "" - for row in result.values: - value += f"\n{row[i]}" - embed.add_field(name=header, value=value, inline=True) - - await self._message_service.send_ctx_msg(ctx, embed, wait_before_delete=wait) - except Exception as e: - self._logger.error(__name__, f"Cannot view statistic {name}", e) - await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.view.failed")) - - self._logger.trace(__name__, f"Finished stats view command") - - @view.autocomplete("name") - async def view_autocomplete( - self, interaction: discord.Interaction, current: str - ) -> TList[app_commands.Choice[str]]: - server = self._servers.get_server_by_discord_id(interaction.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) - return [ - app_commands.Choice(name=f"{statistic.name}: {statistic.description}", value=statistic.name) - for statistic in stats - ] - - @stats.command() - @commands.guild_only() - @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_technician() - async def add(self, ctx: Context, name: str): - self._logger.debug(__name__, f"Received command stats add {ctx}: {name}") - - if ctx.guild is None: - return - - server = self._servers.get_server_by_discord_id(ctx.guild.id) - form = AddStatisticForm( - server, - self._stats, - self._db, - name, - self._message_service, - self._logger, - self._t, - ) - self._logger.trace(__name__, f"Finished stats add command") - self._logger.trace(__name__, f"Started stats command form") - await ctx.interaction.response.send_modal(form) - - @stats.command() - @commands.guild_only() - @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_technician() - async def edit(self, ctx: Context, name: str): - self._logger.debug(__name__, f"Received command stats edit {ctx}: {name}") - - try: - server = self._servers.get_server_by_discord_id(ctx.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) - statistic = stats.where(lambda s: s.name == name).single() - form = AddStatisticForm( - server, - self._stats, - self._db, - name, - self._message_service, - self._logger, - self._t, - code=statistic.code, - description=statistic.description, - ) - self._logger.trace(__name__, f"Finished stats edit command") - self._logger.trace(__name__, f"Started stats command form") - await ctx.interaction.response.send_modal(form) - except Exception as e: - self._logger.error(__name__, f"Cannot edit statistic {name}", e) - await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.edit.failed")) - - @edit.autocomplete("name") - async def edit_autocomplete( - self, interaction: discord.Interaction, current: str - ) -> TList[app_commands.Choice[str]]: - server = self._servers.get_server_by_discord_id(interaction.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) - return [ - app_commands.Choice(name=f"{statistic.name}: {statistic.description}", value=statistic.name) - for statistic in stats - ] - - @stats.command() - @commands.guild_only() - @CommandChecks.check_is_ready() - @CommandChecks.check_is_member_technician() - async def remove(self, ctx: Context, name: str): - self._logger.debug(__name__, f"Received command stats remove {ctx}: {name}") - - try: - server = self._servers.get_server_by_discord_id(ctx.guild.id) - statistic = self._stats.get_statistic_by_name(name, server.server_id) - self._stats.delete_statistic(statistic) - self._db.save_changes() - await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.remove.success")) - self._logger.trace(__name__, f"Finished stats remove command") - except Exception as e: - self._logger.error(__name__, f"Cannot remove statistic {name}", e) - await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.stats.remove.failed")) - - @remove.autocomplete("name") - async def edit_autocomplete( - self, interaction: discord.Interaction, current: str - ) -> TList[app_commands.Choice[str]]: - server = self._servers.get_server_by_discord_id(interaction.guild.id) - stats = self._stats.get_statistics_by_server_id(server.server_id) - return [ - app_commands.Choice(name=f"{statistic.name}: {statistic.description}", value=statistic.name) - for statistic in stats - ] diff --git a/kdb-bot/src/modules/stats/model/statistic_result.py b/kdb-bot/src/modules/stats/model/statistic_result.py deleted file mode 100644 index d8e62bf6..00000000 --- a/kdb-bot/src/modules/stats/model/statistic_result.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_query.extension import List - - -class StatisticResult: - def __init__(self): - self._header = List(str) - self._values = List(List) - - @property - def header(self) -> List[str]: - return self._header - - @header.setter - def header(self, value: List[str]): - self._header = value - - @property - def values(self) -> List[List]: - return self._values - - @values.setter - def values(self, value: List[List]): - self._values = value diff --git a/kdb-bot/src/modules/stats/service/__init__.py b/kdb-bot/src/modules/stats/service/__init__.py deleted file mode 100644 index 0fe51ae2..00000000 --- a/kdb-bot/src/modules/stats/service/__init__.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -bot Keksdose bot -~~~~~~~~~~~~~~~~~~~ - -Discord bot for the Keksdose discord Server - -:copyright: (c) 2022 - 2023 sh-edraft.de -:license: MIT, see LICENSE for more details. - -""" - -__title__ = "modules.stats.service" -__author__ = "Sven Heidemann" -__license__ = "MIT" -__copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" - -from collections import namedtuple - - -# imports - -VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") diff --git a/kdb-bot/src/modules/stats/service/statistic_service.py b/kdb-bot/src/modules/stats/service/statistic_service.py deleted file mode 100644 index 8286c533..00000000 --- a/kdb-bot/src/modules/stats/service/statistic_service.py +++ /dev/null @@ -1,87 +0,0 @@ -from abc import abstractmethod - -from cpl_discord.service import DiscordBotServiceABC -from cpl_query.extension import List -from discord import Guild - -from bot_data.abc.auto_role_repository_abc import AutoRoleRepositoryABC -from bot_data.abc.client_repository_abc import ClientRepositoryABC -from bot_data.abc.known_user_repository_abc import KnownUserRepositoryABC -from bot_data.abc.level_repository_abc import LevelRepositoryABC -from bot_data.abc.server_repository_abc import ServerRepositoryABC -from bot_data.abc.user_joined_server_repository_abc import UserJoinedServerRepositoryABC -from bot_data.abc.user_joined_voice_channel_repository_abc import ( - UserJoinedVoiceChannelRepositoryABC, -) -from bot_data.abc.user_repository_abc import UserRepositoryABC -from bot_data.model.auto_role import AutoRole -from bot_data.model.client import Client -from bot_data.model.known_user import KnownUser -from bot_data.model.level import Level -from bot_data.model.server import Server -from bot_data.model.user import User -from bot_data.model.user_joined_server import UserJoinedServer -from bot_data.model.user_joined_voice_channel import UserJoinedVoiceChannel -from modules.stats.model.statistic_result import StatisticResult - - -class StatisticService: - def __init__( - self, - auto_roles: AutoRoleRepositoryABC, - clients: ClientRepositoryABC, - known_users: KnownUserRepositoryABC, - levels: LevelRepositoryABC, - servers: ServerRepositoryABC, - user_joined_servers: UserJoinedServerRepositoryABC, - user_joined_voice_channel: UserJoinedVoiceChannelRepositoryABC, - users: UserRepositoryABC, - bot: DiscordBotServiceABC, - ): - self._auto_roles = auto_roles - self._clients = clients - self._known_users = known_users - self._levels = levels - self._servers = servers - self._user_joined_servers = user_joined_servers - self._user_joined_voice_channel = user_joined_voice_channel - self._users = users - self._bot = bot - - async def execute(self, code: str, server: Server) -> StatisticResult: - guild = self._bot.guilds.where(lambda g: g.id == server.discord_server_id).single() - - return await self.get_data( - code, - self._auto_roles.get_auto_roles().where(lambda x: x.server.server_id == server.server_id), - self._clients.get_clients().where(lambda x: x.server.server_id == server.server_id), - self._known_users.get_users(), - self._levels.get_levels().where(lambda x: x.server.server_id == server.server_id), - self._servers.get_servers().where(lambda x: x.server_id == server.server_id), - self._user_joined_servers.get_user_joined_servers().where( - lambda x: x.user.server.server_id == server.server_id - ), - self._user_joined_voice_channel.get_user_joined_voice_channels().where( - lambda x: x.user.server.server_id == server.server_id - ), - self._users.get_users().where(lambda x: x.server.server_id == server.server_id), - guild, - ) - - @staticmethod - async def get_data( - code: str, - auto_roles: List[AutoRole], - clients: List[Client], - known_users: List[KnownUser], - levels: List[Level], - servers: List[Server], - user_joined_servers: List[UserJoinedServer], - user_joined_voice_channel: List[UserJoinedVoiceChannel], - users: List[User], - guild: Guild, - ) -> StatisticResult: - result = StatisticResult() - exec(code) - - return result diff --git a/kdb-bot/src/modules/stats/stats.json b/kdb-bot/src/modules/stats/stats.json deleted file mode 100644 index 009b92e2..00000000 --- a/kdb-bot/src/modules/stats/stats.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "ProjectSettings": { - "Name": "stats", - "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" - }, - "Author": "", - "AuthorEmail": "", - "Description": "", - "LongDescription": "", - "URL": "", - "CopyrightDate": "", - "CopyrightName": "", - "LicenseName": "", - "LicenseDescription": "", - "Dependencies": [ - "cpl-core==2022.12.0" - ], - "DevDependencies": [ - "cpl-cli==2022.12.0" - ], - "PythonVersion": ">=3.10.4", - "PythonPath": {}, - "Classifiers": [] - }, - "BuildSettings": { - "ProjectType": "library", - "SourcePath": "", - "OutputPath": "../../dist", - "Main": "stats.main", - "EntryPoint": "stats", - "IncludePackageData": false, - "Included": [], - "Excluded": [ - "*/__pycache__", - "*/logs", - "*/tests" - ], - "PackageData": {}, - "ProjectReferences": [] - } -} \ No newline at end of file diff --git a/kdb-bot/src/modules/stats/stats_module.py b/kdb-bot/src/modules/stats/stats_module.py deleted file mode 100644 index 9cb459af..00000000 --- a/kdb-bot/src/modules/stats/stats_module.py +++ /dev/null @@ -1,23 +0,0 @@ -from cpl_core.configuration import ConfigurationABC -from cpl_core.dependency_injection import ServiceCollectionABC -from cpl_core.environment import ApplicationEnvironmentABC -from cpl_discord.service.discord_collection_abc import DiscordCollectionABC - -from bot_core.abc.module_abc import ModuleABC -from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum -from modules.stats.command.stats_group import StatsGroup -from modules.stats.service.statistic_service import StatisticService - - -class StatsModule(ModuleABC): - def __init__(self, dc: DiscordCollectionABC): - ModuleABC.__init__(self, dc, FeatureFlagsEnum.stats_module) - - def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironmentABC): - pass - - def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): - services.add_transient(StatisticService) - # commands - self._dc.add_command(StatsGroup) - # events diff --git a/kdb-bot/src/modules/stats/ui/add_statistic_form.py b/kdb-bot/src/modules/stats/ui/add_statistic_form.py deleted file mode 100644 index 0688aef6..00000000 --- a/kdb-bot/src/modules/stats/ui/add_statistic_form.py +++ /dev/null @@ -1,99 +0,0 @@ -import discord -from cpl_core.database.context import DatabaseContextABC -from cpl_query.extension import List -from cpl_translation import TranslatePipe -from discord import ui, TextStyle - -from bot_core.abc.message_service_abc import MessageServiceABC -from bot_core.logging.command_logger import CommandLogger -from bot_data.abc.statistic_repository_abc import StatisticRepositoryABC -from bot_data.model.server import Server -from bot_data.model.statistic import Statistic - - -class AddStatisticForm(ui.Modal): - - description = ui.TextInput(label="Beschreibung", required=True) - code = ui.TextInput(label="Code", required=True, style=TextStyle.long) - - def __init__( - self, - server: Server, - stats: StatisticRepositoryABC, - db: DatabaseContextABC, - name: str, - message_service: MessageServiceABC, - logger: CommandLogger, - t: TranslatePipe, - code: str = None, - description: str = None, - ): - ui.Modal.__init__(self, title=name) - - self._server = server - self._stats = stats - self._db = db - self._name = name - self._message_service = message_service - self._logger = logger - self._t = t - - if code is not None: - self.code.default = code - - if description is not None: - self.description.default = description - - async def on_submit(self, interaction: discord.Interaction): - statistic = ( - self._stats.get_statistics_by_server_id(self._server.server_id) - .where(lambda s: s.name == self._name) - .single_or_default() - ) - - if interaction.guild is None: - if statistic is None: - await self._message_service.send_interaction_msg( - interaction, self._t.transform("modules.stats.add.failed") - ) - else: - await self._message_service.send_interaction_msg( - interaction, self._t.transform("modules.stats.edit.failed") - ) - return - - try: - if statistic is None: - self._stats.add_statistic( - Statistic( - self._name, - self.description.value, - self.code.value, - self._server, - ) - ) - self._db.save_changes() - await self._message_service.send_interaction_msg( - interaction, self._t.transform("modules.stats.add.success") - ) - return - - statistic.description = self.description.value - statistic.code = self.code.value - self._stats.update_statistic(statistic) - self._db.save_changes() - await self._message_service.send_interaction_msg( - interaction, self._t.transform("modules.stats.edit.success") - ) - except Exception as e: - self._logger.error(__name__, f"Save statistic {self._name} failed", e) - if statistic is None: - await self._message_service.send_interaction_msg( - interaction, self._t.transform("modules.stats.add.failed") - ) - else: - await self._message_service.send_interaction_msg( - interaction, self._t.transform("modules.stats.edit.failed") - ) - - self._logger.trace(__name__, f"Finished stats command form") diff --git a/kdb-bot/src/modules/technician/__init__.py b/kdb-bot/src/modules/technician/__init__.py index f5c1313e..e14a25bd 100644 --- a/kdb-bot/src/modules/technician/__init__.py +++ b/kdb-bot/src/modules/technician/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.technician" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/technician/api_key_seeder.py b/kdb-bot/src/modules/technician/api_key_seeder.py new file mode 100644 index 00000000..f8f1305c --- /dev/null +++ b/kdb-bot/src/modules/technician/api_key_seeder.py @@ -0,0 +1,44 @@ +from cpl_core.configuration import ConfigurationABC +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.service import DiscordBotServiceABC + +from bot_core.logging.database_logger import DatabaseLogger +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.data_seeder_abc import DataSeederABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.api_key import ApiKey + + +class ApiKeySeeder(DataSeederABC): + def __init__( + self, + logger: DatabaseLogger, + config: ConfigurationABC, + bot: DiscordBotServiceABC, + db: DatabaseContextABC, + users: UserRepositoryABC, + api_keys: ApiKeyRepositoryABC, + ): + DataSeederABC.__init__(self) + + self._logger = logger + self._config = config + self._bot = bot + self._db = db + self._users = users + self._api_keys = api_keys + + async def seed(self): + self._logger.debug(__name__, f"API-Key seeder started") + + if self._api_keys.get_api_keys().count() > 0: + self._logger.debug(__name__, f"Skip API-Key seeder") + return + + try: + frontend_key = ApiKey("frontend", "87f529fd-a32e-40b3-a1d1-7a1583cf3ff5", None) + self._api_keys.add_api_key(frontend_key) + self._db.save_changes() + self._logger.info(__name__, f"Created frontend API-Key") + except Exception as e: + self._logger.fatal(__name__, "Cannot create frontend API-Key", e) diff --git a/kdb-bot/src/modules/technician/command/__init__.py b/kdb-bot/src/modules/technician/command/__init__.py index 32e38a84..fa8ce9d5 100644 --- a/kdb-bot/src/modules/technician/command/__init__.py +++ b/kdb-bot/src/modules/technician/command/__init__.py @@ -15,7 +15,7 @@ __title__ = "modules.technician.command" __author__ = "Sven Heidemann" __license__ = "MIT" __copyright__ = "Copyright (c) 2022 - 2023 sh-edraft.de" -__version__ = "0.3.1.post1" +__version__ = "1.0.0" from collections import namedtuple @@ -23,4 +23,4 @@ from collections import namedtuple # imports: VersionInfo = namedtuple("VersionInfo", "major minor micro") -version_info = VersionInfo(major="0", minor="3", micro="1.post1") +version_info = VersionInfo(major="1", minor="0", micro="0") diff --git a/kdb-bot/src/modules/technician/command/api_key_group.py b/kdb-bot/src/modules/technician/command/api_key_group.py new file mode 100644 index 00000000..11912385 --- /dev/null +++ b/kdb-bot/src/modules/technician/command/api_key_group.py @@ -0,0 +1,139 @@ +import hashlib +import uuid +from typing import List as TList + +import discord +from cpl_core.database.context import DatabaseContextABC +from cpl_discord.command import DiscordCommandABC +from cpl_discord.service import DiscordBotServiceABC +from cpl_translation import TranslatePipe +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context + +from bot_api.configuration.authentication_settings import AuthenticationSettings +from bot_core.abc.client_utils_abc import ClientUtilsABC +from bot_core.abc.message_service_abc import MessageServiceABC +from bot_core.helper.command_checks import CommandChecks +from bot_core.logging.command_logger import CommandLogger +from bot_data.abc.api_key_repository_abc import ApiKeyRepositoryABC +from bot_data.abc.server_repository_abc import ServerRepositoryABC +from bot_data.abc.user_repository_abc import UserRepositoryABC +from bot_data.model.api_key import ApiKey +from modules.permission.abc.permission_service_abc import PermissionServiceABC + + +class ApiKeyGroup(DiscordCommandABC): + def __init__( + self, + logger: CommandLogger, + auth_settings: AuthenticationSettings, + message_service: MessageServiceABC, + bot: DiscordBotServiceABC, + client_utils: ClientUtilsABC, + permission_service: PermissionServiceABC, + translate: TranslatePipe, + db: DatabaseContextABC, + servers: ServerRepositoryABC, + users: UserRepositoryABC, + api_keys: ApiKeyRepositoryABC, + ): + DiscordCommandABC.__init__(self) + + self._logger = logger + self._auth_settings = auth_settings + self._message_service = message_service + self._bot = bot + self._client_utils = client_utils + self._permissions = permission_service + self._t = translate + self._db = db + self._servers = servers + self._users = users + self._api_keys = api_keys + + def _get_api_key_str(self, api_key: ApiKey) -> str: + return hashlib.sha256( + f"{api_key.identifier}:{api_key.key}+{self._auth_settings.secret_key}".encode("utf-8") + ).hexdigest() + + @commands.hybrid_group(name="api-key") + @commands.guild_only() + async def api_key(self, ctx: Context): + pass + + @api_key.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_technician() + async def get(self, ctx: Context, key: str, wait: int = None): + self._logger.debug(__name__, f"Received command api-key get {ctx}: {key},{wait}") + + api_key = self._api_keys.get_api_key_by_key(key) + await self._message_service.send_ctx_msg( + ctx, + self._t.transform("modules.technician.api_key.get").format( + api_key.identifier, self._get_api_key_str(api_key) + ), + ) + self._logger.trace(__name__, f"Finished command api-key get") + + @get.autocomplete("key") + async def get_autocomplete(self, interaction: discord.Interaction, current: str) -> TList[app_commands.Choice[str]]: + keys = self._api_keys.get_api_keys() + + return [ + app_commands.Choice(name=f"{key.identifier}: {key.key}", value=key.key) + for key in self._client_utils.get_auto_complete_list(keys, current, lambda x: x.key) + ] + + @api_key.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def add(self, ctx: Context, identifier: str): + self._logger.debug(__name__, f"Received command api-key add {ctx}: {identifier}") + + server = self._servers.get_server_by_discord_id(ctx.guild.id) + user = self._users.get_user_by_discord_id_and_server_id(ctx.author.id, server.id) + api_key = ApiKey(identifier, str(uuid.uuid4()), user) + self._api_keys.add_api_key(api_key) + self._db.save_changes() + await self._message_service.send_ctx_msg( + ctx, + self._t.transform("modules.technician.api_key.add.success").format( + identifier, self._get_api_key_str(api_key) + ), + ) + + self._logger.trace(__name__, f"Finished command api-key add") + + @api_key.command() + @commands.guild_only() + @CommandChecks.check_is_ready() + @CommandChecks.check_is_member_moderator() + async def remove(self, ctx: Context, key: str): + self._logger.debug(__name__, f"Received command api-key remove {ctx}: {key}") + + keys = self._api_keys.get_api_keys().where(lambda x: x.key == key) + if keys.count() < 1: + await self._message_service.send_ctx_msg( + ctx, + self._t.transform("modules.technician.api_key.remove.not_found"), + ) + + api_key = keys.single() + self._api_keys.delete_api_key(api_key) + self._db.save_changes() + await self._message_service.send_ctx_msg(ctx, self._t.transform("modules.technician.api_key.remove.success")) + + self._logger.trace(__name__, f"Finished command api-key remove") + + @remove.autocomplete("key") + async def set_autocomplete(self, interaction: discord.Interaction, current: str) -> TList[app_commands.Choice[str]]: + keys = self._api_keys.get_api_keys() + + return [ + app_commands.Choice(name=f"{key.identifier}: {key.key}", value=key.key) + for key in self._client_utils.get_auto_complete_list(keys, current, lambda x: x.key) + ] diff --git a/kdb-bot/src/modules/technician/technician.json b/kdb-bot/src/modules/technician/technician.json index fb5d9e67..c102f54c 100644 --- a/kdb-bot/src/modules/technician/technician.json +++ b/kdb-bot/src/modules/technician/technician.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "technician", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "", "AuthorEmail": "", diff --git a/kdb-bot/src/modules/technician/technician_module.py b/kdb-bot/src/modules/technician/technician_module.py index 9a9ca7ba..9aa5089c 100644 --- a/kdb-bot/src/modules/technician/technician_module.py +++ b/kdb-bot/src/modules/technician/technician_module.py @@ -5,11 +5,14 @@ from cpl_discord.service.discord_collection_abc import DiscordCollectionABC from bot_core.abc.module_abc import ModuleABC from bot_core.configuration.feature_flags_enum import FeatureFlagsEnum +from bot_data.abc.data_seeder_abc import DataSeederABC from modules.base.abc.base_helper_abc import BaseHelperABC +from modules.base.service.base_helper_service import BaseHelperService +from modules.technician.api_key_seeder import ApiKeySeeder +from modules.technician.command.api_key_group import ApiKeyGroup from modules.technician.command.log_command import LogCommand from modules.technician.command.restart_command import RestartCommand from modules.technician.command.shutdown_command import ShutdownCommand -from modules.base.service.base_helper_service import BaseHelperService class TechnicianModule(ModuleABC): @@ -20,9 +23,11 @@ class TechnicianModule(ModuleABC): pass def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironmentABC): + services.add_transient(DataSeederABC, ApiKeySeeder) services.add_transient(BaseHelperABC, BaseHelperService) # commands self._dc.add_command(RestartCommand) self._dc.add_command(ShutdownCommand) self._dc.add_command(LogCommand) + self._dc.add_command(ApiKeyGroup) # events diff --git a/kdb-bot/tools/checks/get_ontime_overlaps.py b/kdb-bot/tools/checks/get_ontime_overlaps.py index 5efe6842..115b8099 100644 --- a/kdb-bot/tools/checks/get_ontime_overlaps.py +++ b/kdb-bot/tools/checks/get_ontime_overlaps.py @@ -46,7 +46,6 @@ def main(): groups[user].extend(ujvcs.where(lambda x: x.UserId == user)) for group in groups: - values: List[UserJoinedVoiceChannel] = groups[group] def find_overlaps(x: UserJoinedVoiceChannel) -> bool: diff --git a/kdb-bot/tools/get_version/get-version.json b/kdb-bot/tools/get_version/get-version.json index 99773f27..dfbff1fd 100644 --- a/kdb-bot/tools/get_version/get-version.json +++ b/kdb-bot/tools/get_version/get-version.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "get-version", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/kdb-bot/tools/post_build/post-build.json b/kdb-bot/tools/post_build/post-build.json index ddbfa727..c12accdd 100644 --- a/kdb-bot/tools/post_build/post-build.json +++ b/kdb-bot/tools/post_build/post-build.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "post-build", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/kdb-bot/tools/post_build/service/remove_config.py b/kdb-bot/tools/post_build/service/remove_config.py index ab8b9d47..60370937 100644 --- a/kdb-bot/tools/post_build/service/remove_config.py +++ b/kdb-bot/tools/post_build/service/remove_config.py @@ -16,7 +16,6 @@ class RemoveConfig: build: BuildSettings, post_build: PostBuildSettings, ): - self._env = env self._workspace = ws self._project = project diff --git a/kdb-bot/tools/set_version/set-version.json b/kdb-bot/tools/set_version/set-version.json index 1932cf25..147bc827 100644 --- a/kdb-bot/tools/set_version/set-version.json +++ b/kdb-bot/tools/set_version/set-version.json @@ -2,9 +2,9 @@ "ProjectSettings": { "Name": "set-version", "Version": { - "Major": "0", - "Minor": "3", - "Micro": "1.post1" + "Major": "1", + "Minor": "0", + "Micro": "0" }, "Author": "Sven Heidemann", "AuthorEmail": "sven.heidemann@sh-edraft.de", diff --git a/kdb-web/package-lock.json b/kdb-web/package-lock.json index df66cf23..9c7b31b2 100644 --- a/kdb-web/package-lock.json +++ b/kdb-web/package-lock.json @@ -1,36 +1,36 @@ { "name": "kdb-web", - "version": "0.3.0", - "lockfileVersion": 2, + "version": "1.0.dev251", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "kdb-web", - "version": "0.3.0", + "version": "1.0.dev251", "dependencies": { - "@angular/animations": "^14.0.0", - "@angular/common": "^14.0.0", - "@angular/compiler": "^14.0.0", - "@angular/core": "^14.0.0", - "@angular/forms": "^14.0.0", - "@angular/platform-browser": "^14.0.0", - "@angular/platform-browser-dynamic": "^14.0.0", - "@angular/router": "^14.0.0", + "@angular/animations": "^15.1.4", + "@angular/common": "^15.1.4", + "@angular/compiler": "^15.1.4", + "@angular/core": "^15.1.4", + "@angular/forms": "^15.1.4", + "@angular/platform-browser": "^15.1.4", + "@angular/platform-browser-dynamic": "^15.1.4", + "@angular/router": "^15.1.4", "@auth0/angular-jwt": "^5.1.0", "@microsoft/signalr": "^6.0.9", "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", "@types/socket.io-client": "^3.0.0", "primeicons": "^6.0.1", - "primeng": "^14.1.2", + "primeng": "^15.2.0", "rxjs": "~7.5.0", "socket.io-client": "^4.5.3", "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "^14.0.0", - "@angular/cli": "~14.0.0", - "@angular/compiler-cli": "^14.0.0", + "@angular-devkit/build-angular": "^15.1.5", + "@angular/cli": "~15.1.5", + "@angular/compiler-cli": "^15.1.4", "@types/jasmine": "~4.0.0", "@types/node": "^18.11.9", "jasmine-core": "~4.1.0", @@ -40,15 +40,9 @@ "karma-jasmine": "~5.0.0", "karma-jasmine-html-reporter": "~1.7.0", "tslib": "^2.4.1", - "typescript": "~4.7.2" + "typescript": "~4.9.5" } }, - "node_modules/@adobe/css-tools": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz", - "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==", - "dev": true - }, "node_modules/@ampproject/remapping": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", @@ -63,16 +57,16 @@ } }, "node_modules/@angular-devkit/architect": { - "version": "0.1402.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1402.6.tgz", - "integrity": "sha512-qTmPBD7fBXBtlSapGLUEcJvRuL/O556zCFFpH3kSlzPNTYxi2falBjGY+4aG+078RXT1vVZtFsvRTart6VbhAg==", + "version": "0.1502.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1502.4.tgz", + "integrity": "sha512-bDBcaRMBfXFfK9MpvfNO926F1rL0PEw+mveXxq3/SSql+1XP/hrc5TVGwnoim4g6DqsGmu9upS5DyJ6PnL/hHA==", "dev": true, "dependencies": { - "@angular-devkit/core": "14.2.6", + "@angular-devkit/core": "15.2.4", "rxjs": "6.6.7" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } @@ -96,96 +90,98 @@ "dev": true }, "node_modules/@angular-devkit/build-angular": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-14.2.6.tgz", - "integrity": "sha512-XtaUwb3aZ8S0vl0y9bmbdFOH0KQCQ778twFH+ZfHW2BcPYtQz2Cy2rcVKXBQ850RyC0GxgMPfco6OGQndPpizg==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-15.2.4.tgz", + "integrity": "sha512-wt0S4oz0vxuW0/Ak5X0vQ7s7TSPynmktVNJblu9SFRgwCD3kplV2B693F+M6t8eLzSy0UCSbZp9h3Ae8gLEiEw==", "dev": true, "dependencies": { "@ampproject/remapping": "2.2.0", - "@angular-devkit/architect": "0.1402.6", - "@angular-devkit/build-webpack": "0.1402.6", - "@angular-devkit/core": "14.2.6", - "@babel/core": "7.18.10", - "@babel/generator": "7.18.12", + "@angular-devkit/architect": "0.1502.4", + "@angular-devkit/build-webpack": "0.1502.4", + "@angular-devkit/core": "15.2.4", + "@babel/core": "7.20.12", + "@babel/generator": "7.20.14", "@babel/helper-annotate-as-pure": "7.18.6", - "@babel/plugin-proposal-async-generator-functions": "7.18.10", - "@babel/plugin-transform-async-to-generator": "7.18.6", - "@babel/plugin-transform-runtime": "7.18.10", - "@babel/preset-env": "7.18.10", - "@babel/runtime": "7.18.9", - "@babel/template": "7.18.10", + "@babel/helper-split-export-declaration": "7.18.6", + "@babel/plugin-proposal-async-generator-functions": "7.20.7", + "@babel/plugin-transform-async-to-generator": "7.20.7", + "@babel/plugin-transform-runtime": "7.19.6", + "@babel/preset-env": "7.20.2", + "@babel/runtime": "7.20.13", + "@babel/template": "7.20.7", "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "14.2.6", + "@ngtools/webpack": "15.2.4", "ansi-colors": "4.1.3", - "babel-loader": "8.2.5", + "autoprefixer": "10.4.13", + "babel-loader": "9.1.2", "babel-plugin-istanbul": "6.1.1", - "browserslist": "^4.9.1", - "cacache": "16.1.2", + "browserslist": "4.21.5", + "cacache": "17.0.4", + "chokidar": "3.5.3", "copy-webpack-plugin": "11.0.0", "critters": "0.0.16", - "css-loader": "6.7.1", - "esbuild-wasm": "0.15.5", - "glob": "8.0.3", + "css-loader": "6.7.3", + "esbuild-wasm": "0.17.8", + "glob": "8.1.0", "https-proxy-agent": "5.0.1", "inquirer": "8.2.4", - "jsonc-parser": "3.1.0", + "jsonc-parser": "3.2.0", "karma-source-map-support": "1.4.0", "less": "4.1.3", - "less-loader": "11.0.0", + "less-loader": "11.1.0", "license-webpack-plugin": "4.0.2", - "loader-utils": "3.2.0", - "mini-css-extract-plugin": "2.6.1", - "minimatch": "5.1.0", - "open": "8.4.0", + "loader-utils": "3.2.1", + "magic-string": "0.29.0", + "mini-css-extract-plugin": "2.7.2", + "open": "8.4.1", "ora": "5.4.1", - "parse5-html-rewriting-stream": "6.0.1", + "parse5-html-rewriting-stream": "7.0.0", "piscina": "3.2.0", - "postcss": "8.4.16", - "postcss-import": "15.0.0", - "postcss-loader": "7.0.1", - "postcss-preset-env": "7.8.0", - "regenerator-runtime": "0.13.9", + "postcss": "8.4.21", + "postcss-loader": "7.0.2", "resolve-url-loader": "5.0.0", "rxjs": "6.6.7", - "sass": "1.54.4", - "sass-loader": "13.0.2", - "semver": "7.3.7", - "source-map-loader": "4.0.0", + "sass": "1.58.1", + "sass-loader": "13.2.0", + "semver": "7.3.8", + "source-map-loader": "4.0.1", "source-map-support": "0.5.21", - "stylus": "0.59.0", - "stylus-loader": "7.0.0", - "terser": "5.14.2", + "terser": "5.16.3", "text-table": "0.2.0", "tree-kill": "1.2.2", - "tslib": "2.4.0", - "webpack": "5.74.0", - "webpack-dev-middleware": "5.3.3", - "webpack-dev-server": "4.11.0", + "tslib": "2.5.0", + "webpack": "5.76.1", + "webpack-dev-middleware": "6.0.1", + "webpack-dev-server": "4.11.1", "webpack-merge": "5.8.0", "webpack-subresource-integrity": "5.1.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "optionalDependencies": { - "esbuild": "0.15.5" + "esbuild": "0.17.8" }, "peerDependencies": { - "@angular/compiler-cli": "^14.0.0", - "@angular/localize": "^14.0.0", - "@angular/service-worker": "^14.0.0", + "@angular/compiler-cli": "^15.0.0", + "@angular/localize": "^15.0.0", + "@angular/platform-server": "^15.0.0", + "@angular/service-worker": "^15.0.0", "karma": "^6.3.0", - "ng-packagr": "^14.0.0", + "ng-packagr": "^15.0.0", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0", - "typescript": ">=4.6.2 <4.9" + "typescript": ">=4.8.2 <5.0" }, "peerDependenciesMeta": { "@angular/localize": { "optional": true }, + "@angular/platform-server": { + "optional": true + }, "@angular/service-worker": { "optional": true }, @@ -221,23 +217,17 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "node_modules/@angular-devkit/build-angular/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - }, "node_modules/@angular-devkit/build-webpack": { - "version": "0.1402.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1402.6.tgz", - "integrity": "sha512-gKsDxQ9pze0N1qDM0kdM4FfwpkjSOb0bQzqjZi7wTfrh/WGIQMCjG9CRwWT+Z289ZKaTpcQDPsDtOSo5QpKNDg==", + "version": "0.1502.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1502.4.tgz", + "integrity": "sha512-Bs/pxcY3517QAVyAalDxJgjc93KWQos+dFdgEQrKxj/VTs1BTYnLbb2M8Y7MoxVnfH4S+qqxGe5B57T+TlB3Eg==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1402.6", + "@angular-devkit/architect": "0.1502.4", "rxjs": "6.6.7" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -265,19 +255,19 @@ "dev": true }, "node_modules/@angular-devkit/core": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.2.6.tgz", - "integrity": "sha512-qtRSdRm/h7C3ya04PJTDgQXV6mM8Y4RakANX1GTSXetCf9AVSxg74NJX76DWUgiHT4JiPYnJgJU6Hr/L0H6JOQ==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.2.4.tgz", + "integrity": "sha512-yl+0j1bMwJLKShsyCXw77tbJG8Sd21+itisPLL2MgEpLNAO252kr9zG4TLlFRJyKVftm2l1h78KjqvM5nbOXNg==", "dev": true, "dependencies": { - "ajv": "8.11.0", + "ajv": "8.12.0", "ajv-formats": "2.1.1", - "jsonc-parser": "3.1.0", + "jsonc-parser": "3.2.0", "rxjs": "6.6.7", "source-map": "0.7.4" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -309,37 +299,37 @@ "dev": true }, "node_modules/@angular-devkit/schematics": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-14.0.7.tgz", - "integrity": "sha512-nJUJXCBQr7rmVn6IXFAXMCWAB1w6JQmFGuFVW0G3GH/A0e+A3ttzJc6qVLYluqaFoafw394cZu24YJo55E/+Zg==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-15.1.6.tgz", + "integrity": "sha512-cwmJFpS43zrdlmfwfHIxG/Nzg5rzFdtKrHx64ZXxNFm6JdyK2JTs/qrHUwv1FYWAcqhdiHn+00jYklMmvsvPOA==", "dev": true, "dependencies": { - "@angular-devkit/core": "14.0.7", - "jsonc-parser": "3.0.0", - "magic-string": "0.26.1", + "@angular-devkit/core": "15.1.6", + "jsonc-parser": "3.2.0", + "magic-string": "0.27.0", "ora": "5.4.1", "rxjs": "6.6.7" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", - "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.1.6.tgz", + "integrity": "sha512-jGgxyRjecVf6lEyqDxz7ltMEndNPxIg720pk6r40fgsu0dU8w9vjJSJe7k0XdJiXVRcN6wZa/J5nO/xcwWVIsA==", "dev": true, "dependencies": { - "ajv": "8.11.0", + "ajv": "8.12.0", "ajv-formats": "2.1.1", - "jsonc-parser": "3.0.0", + "jsonc-parser": "3.2.0", "rxjs": "6.6.7", - "source-map": "0.7.3" + "source-map": "0.7.4" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -352,11 +342,17 @@ } } }, - "node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true + "node_modules/@angular-devkit/schematics/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } }, "node_modules/@angular-devkit/schematics/node_modules/rxjs": { "version": "6.6.7", @@ -370,15 +366,6 @@ "npm": ">=2.0.0" } }, - "node_modules/@angular-devkit/schematics/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/@angular-devkit/schematics/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -386,84 +373,82 @@ "dev": true }, "node_modules/@angular/animations": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-14.2.6.tgz", - "integrity": "sha512-Tmb3Jj016j8m8OOGSk/ReL0b+OuUCMj0KQansk3C4pCpH9oPF67Vnm0fmVC2wYjjsSS/iDgl4kaDW740wfPGNQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-15.2.3.tgz", + "integrity": "sha512-65MTsTGAoJXtfSek6Scc3g9ZD6abs+QzcWjgFek0hFX2Lgc144lhEBBmTolFEjPFAS23hjdPQHztegIT92WPAA==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "14.2.6" + "@angular/core": "15.2.3" } }, "node_modules/@angular/cli": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-14.0.7.tgz", - "integrity": "sha512-tABt1EDwBHm0ngsutdkXXWgPgHzapGLC7rSPHXStMc24ngViFZpXGzBCpompjHvXNt6bjklmJmuRvjS6+ktBZA==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-15.1.6.tgz", + "integrity": "sha512-GmC9jZK2ipUWj0dlfTI5oEYia4y1fLfO3AtAKU5CylNYrGyB+DRytKY8Bx6Fs4kaNBY8V8YnyLi7E/78gziMdg==", "dev": true, "dependencies": { - "@angular-devkit/architect": "0.1400.7", - "@angular-devkit/core": "14.0.7", - "@angular-devkit/schematics": "14.0.7", - "@schematics/angular": "14.0.7", + "@angular-devkit/architect": "0.1501.6", + "@angular-devkit/core": "15.1.6", + "@angular-devkit/schematics": "15.1.6", + "@schematics/angular": "15.1.6", "@yarnpkg/lockfile": "1.1.0", - "ansi-colors": "4.1.1", - "debug": "4.3.4", - "ini": "3.0.0", + "ansi-colors": "4.1.3", + "ini": "3.0.1", "inquirer": "8.2.4", - "jsonc-parser": "3.0.0", - "npm-package-arg": "9.0.2", - "npm-pick-manifest": "7.0.1", + "jsonc-parser": "3.2.0", + "npm-package-arg": "10.1.0", + "npm-pick-manifest": "8.0.1", "open": "8.4.0", "ora": "5.4.1", - "pacote": "13.3.0", - "resolve": "1.22.0", - "semver": "7.3.7", + "pacote": "15.0.8", + "resolve": "1.22.1", + "semver": "7.3.8", "symbol-observable": "4.0.0", - "uuid": "8.3.2", - "yargs": "17.4.1" + "yargs": "17.6.2" }, "bin": { "ng": "bin/ng.js" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular/cli/node_modules/@angular-devkit/architect": { - "version": "0.1400.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1400.7.tgz", - "integrity": "sha512-8dv/Ql86dHajsHYjjr5jvpiV7uXWbt7Mz4K/rGiOi+zzDNKPcZcuCejulWhOySDcCPjT/an47Qcwr+awL4Wr4g==", + "version": "0.1501.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1501.6.tgz", + "integrity": "sha512-u07zZFlfrg0Qn4mu5M9Nz0pH2Yd2028XF/73980PsZMxwkSm4diF08v4bHk3UyR7yPT7phwvt4znj6ryZhx1gw==", "dev": true, "dependencies": { - "@angular-devkit/core": "14.0.7", + "@angular-devkit/core": "15.1.6", "rxjs": "6.6.7" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@angular/cli/node_modules/@angular-devkit/core": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", - "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.1.6.tgz", + "integrity": "sha512-jGgxyRjecVf6lEyqDxz7ltMEndNPxIg720pk6r40fgsu0dU8w9vjJSJe7k0XdJiXVRcN6wZa/J5nO/xcwWVIsA==", "dev": true, "dependencies": { - "ajv": "8.11.0", + "ajv": "8.12.0", "ajv-formats": "2.1.1", - "jsonc-parser": "3.0.0", + "jsonc-parser": "3.2.0", "rxjs": "6.6.7", - "source-map": "0.7.3" + "source-map": "0.7.4" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -476,21 +461,23 @@ } } }, - "node_modules/@angular/cli/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "node_modules/@angular/cli/node_modules/open": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", + "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@angular/cli/node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, "node_modules/@angular/cli/node_modules/rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", @@ -503,15 +490,6 @@ "npm": ">=2.0.0" } }, - "node_modules/@angular/cli/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/@angular/cli/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -519,32 +497,32 @@ "dev": true }, "node_modules/@angular/common": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-14.2.6.tgz", - "integrity": "sha512-WNX7xe8LKP5DHPlae+c77PDwj0iIAAPIe1lWbhQysyi8uttbtL9VVP2XTFuQ3E6oVHJr+0IR0LMVGJ+a8i6zsw==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-15.2.3.tgz", + "integrity": "sha512-J68CSb57XadC2weHw7kmHjCdrHNgxPv8ZW6KlnmYvIRJrkKsZuCl+PvFe90VMDvHtlBnSnz8sjAPqoUxesMRNg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "14.2.6", + "@angular/core": "15.2.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/compiler": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-14.2.6.tgz", - "integrity": "sha512-XtmJRNQQ/bUcRjB6jG67km3EPug8frnHH50sLqxye+cljCzWQpzFN/Qr1z0abuzEX8OC4alqxCDCFgTFyyVkaQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-15.2.3.tgz", + "integrity": "sha512-KdEb5vWptRON6lXhhu93DLog4ekfrlHD74bOWbGQ2F40mycXqLNigOxbDCYifIAeE0xmRxbyV9KBvS6LKLC9uA==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/core": "14.2.6" + "@angular/core": "15.2.3" }, "peerDependenciesMeta": { "@angular/core": { @@ -553,19 +531,19 @@ } }, "node_modules/@angular/compiler-cli": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-14.2.6.tgz", - "integrity": "sha512-zKnpZ5WDbM31dwr5GDAbCblMIEUzWSglUyqCxJfbCg21dE0EuLfd/WzsROgM2TucOtCT5xNipqz4bc+wdEOIgQ==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-15.2.3.tgz", + "integrity": "sha512-n52yntOPnVeQdNq612YyQ1KW27+BZq1YIxtkST6Xmrv6rFuduLVtBLMl+CpZ3vONBzMI1fY6svck6fPb0x4kbQ==", "dev": true, "dependencies": { - "@babel/core": "^7.17.2", + "@babel/core": "7.19.3", + "@jridgewell/sourcemap-codec": "^1.4.14", "chokidar": "^3.0.0", "convert-source-map": "^1.5.1", "dependency-graph": "^0.11.0", - "magic-string": "^0.26.0", + "magic-string": "^0.27.0", "reflect-metadata": "^0.1.2", "semver": "^7.0.0", - "sourcemap-codec": "^1.4.8", "tslib": "^2.3.0", "yargs": "^17.2.1" }, @@ -575,59 +553,110 @@ "ngcc": "bundles/ngcc/main-ngcc.js" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/compiler": "14.2.6", - "typescript": ">=4.6.2 <4.9" + "@angular/compiler": "15.2.3", + "typescript": ">=4.8.2 <5.0" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.19.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.3.tgz", + "integrity": "sha512-WneDJxdsjEvyKtXKsaBGbDeiyOjR5vYq4HcShxnIbG0qixpoHjI3MqeZM9NDvsojNCEBItQE4juOo/bU6e72gQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.19.3", + "@babel/helper-compilation-targets": "^7.19.3", + "@babel/helper-module-transforms": "^7.19.0", + "@babel/helpers": "^7.19.0", + "@babel/parser": "^7.19.3", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.19.3", + "@babel/types": "^7.19.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/compiler-cli/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" } }, "node_modules/@angular/core": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-14.2.6.tgz", - "integrity": "sha512-fEIz7E488X03tLIqmWQRpahxRRU2SMjb9i/rMUjMQJkbppJC3cykl31bCYzeixNO+zpE55GPGuQX2qI/yDenZA==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-15.2.3.tgz", + "integrity": "sha512-e+d6upOqAyqE7MxxRthd1ZJILSKX+hXHCmujc48id8G3zhP0tD59iZ03KgUe8RMvXMlSBUhwOwDX39tr701eig==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { "rxjs": "^6.5.3 || ^7.4.0", - "zone.js": "~0.11.4" + "zone.js": "~0.11.4 || ~0.12.0 || ~0.13.0" } }, "node_modules/@angular/forms": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-14.2.6.tgz", - "integrity": "sha512-t7Hd9RMnHbXRTdH/H8h8ZC3PsK1U4rH+XYaIbQNcys/XSf1uRFHx9MWqkwS5hoQEFOxkFSX5dRv2xSnHtxfq5w==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-15.2.3.tgz", + "integrity": "sha512-+ZcmpmIah87JsPF2Nvh2QoklgW9hWXp4azMPrXsuxackZXKTl/xl8NY32WABQndbhVjtSj08SHCuKd0rPHvpGw==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "14.2.6", - "@angular/core": "14.2.6", - "@angular/platform-browser": "14.2.6", + "@angular/common": "15.2.3", + "@angular/core": "15.2.3", + "@angular/platform-browser": "15.2.3", "rxjs": "^6.5.3 || ^7.4.0" } }, "node_modules/@angular/platform-browser": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-14.2.6.tgz", - "integrity": "sha512-KQUN4YVYEK5NOL7QFnDulQta6tm9rPh/mruX/XCLkSmoRMlFBmsHyjx+VJBnBNUbUxNsBj7kknifOu9PqDgAWg==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-15.2.3.tgz", + "integrity": "sha512-73EdTiw9jR/l/t9MBKD5slWcIiaE3bHQY4oCKzywMYu6ANci+WkCu7Ek2SGGq69M4+bKRo1/e/5XF4vvmNOBYQ==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/animations": "14.2.6", - "@angular/common": "14.2.6", - "@angular/core": "14.2.6" + "@angular/animations": "15.2.3", + "@angular/common": "15.2.3", + "@angular/core": "15.2.3" }, "peerDependenciesMeta": { "@angular/animations": { @@ -636,36 +665,36 @@ } }, "node_modules/@angular/platform-browser-dynamic": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-14.2.6.tgz", - "integrity": "sha512-SlWEYLED4ST1AFfgeB8SyKLVJYp36XT+3Vw3yDrObsthzXCiFAuYHQZfSWgT1Sfx3uFqEdN7nskJqD05wN3mQg==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-15.2.3.tgz", + "integrity": "sha512-HQ+xJzSa1O75s8Trcem8TnFu1rjbrzyRXfus/9Dpxam46ywIt1VuowSegz8K4hBaXnNFn53mZVpyK1hBtPq/bg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "14.2.6", - "@angular/compiler": "14.2.6", - "@angular/core": "14.2.6", - "@angular/platform-browser": "14.2.6" + "@angular/common": "15.2.3", + "@angular/compiler": "15.2.3", + "@angular/core": "15.2.3", + "@angular/platform-browser": "15.2.3" } }, "node_modules/@angular/router": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-14.2.6.tgz", - "integrity": "sha512-Vz1kadGSqA7ZCZQ2woNbSBPMdiE5eTZv8cGympaFnFQQUzQTQ6zi22wY4RzovDk5Lw+EQkvOmaW2864LDzDeug==", + "version": "15.2.3", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-15.2.3.tgz", + "integrity": "sha512-rbgAANRKsx6KPg/oTubyMjGfvSTh+42vj2/fUsARtIqi+kwr1FK/NM/64b1cv+oGYdxZsUkSxNPv4lONjh/DZg==", "dependencies": { "tslib": "^2.3.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0" + "node": "^14.20.0 || ^16.13.0 || >=18.10.0" }, "peerDependencies": { - "@angular/common": "14.2.6", - "@angular/core": "14.2.6", - "@angular/platform-browser": "14.2.6", + "@angular/common": "15.2.3", + "@angular/core": "15.2.3", + "@angular/platform-browser": "15.2.3", "rxjs": "^6.5.3 || ^7.4.0" } }, @@ -676,9 +705,9 @@ "dev": true }, "node_modules/@auth0/angular-jwt": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-5.1.0.tgz", - "integrity": "sha512-EAQoNKPQSZYphcX6FnY2e7xQpD4ZdHQ1DbHq/m+G1U1qA60m3XnhdjPPfu+blVHARlxEbRzWXc48UOVrnMsrZw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-5.1.2.tgz", + "integrity": "sha512-8ulz24cPpEkZb9/AdAaWfYIkomQDbZqvB9LproF/48Klnr30EJx09AYF9sbKTN4qLSgIZSlCb/Y7XQJZ51vSzA==", "dependencies": { "tslib": "^2.0.0" }, @@ -699,34 +728,34 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", - "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", + "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "version": "7.20.12", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", + "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-module-transforms": "^7.18.9", - "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", + "@babel/generator": "^7.20.7", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helpers": "^7.20.7", + "@babel/parser": "^7.20.7", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.12", + "@babel/types": "^7.20.7", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { @@ -747,12 +776,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "version": "7.20.14", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", + "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", "dev": true, "dependencies": { - "@babel/types": "^7.18.10", + "@babel/types": "^7.20.7", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -800,14 +829,15 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.19.3", + "@babel/compat-data": "^7.20.5", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", "semver": "^6.3.0" }, "engines": { @@ -827,17 +857,18 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", + "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.0", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/helper-split-export-declaration": "^7.18.6" }, "engines": { @@ -848,13 +879,13 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", - "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", + "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" + "regexpu-core": "^5.3.1" }, "engines": { "node": ">=6.9.0" @@ -911,13 +942,13 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -936,12 +967,12 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", + "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", "dev": true, "dependencies": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -960,19 +991,19 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" }, "engines": { "node": ">=6.9.0" @@ -991,9 +1022,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", + "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1018,40 +1049,41 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", - "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", + "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.20.7", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", - "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "dev": true, "dependencies": { - "@babel/types": "^7.19.4" + "@babel/types": "^7.20.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", - "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", + "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", "dev": true, "dependencies": { - "@babel/types": "^7.18.9" + "@babel/types": "^7.20.0" }, "engines": { "node": ">=6.9.0" @@ -1088,38 +1120,38 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", + "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", "dev": true, "dependencies": { "@babel/helper-function-name": "^7.19.0", "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" + "@babel/traverse": "^7.20.5", + "@babel/types": "^7.20.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", - "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -1140,9 +1172,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", - "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1167,14 +1199,14 @@ } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", - "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz", + "integrity": "sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -1184,13 +1216,13 @@ } }, "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", - "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-remap-async-to-generator": "^7.18.9", "@babel/plugin-syntax-async-generators": "^7.8.4" }, @@ -1218,13 +1250,13 @@ } }, "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", - "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, "engines": { @@ -1283,12 +1315,12 @@ } }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", - "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", + "integrity": "sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" }, "engines": { @@ -1331,16 +1363,16 @@ } }, "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.19.4.tgz", - "integrity": "sha512-wHmj6LDxVDnL+3WhXteUBaoM1aVILZODAUjg11kHqG4cOlfgMQGxw6aCgvrXrmaJR3Bn14oZhImyCPZzRpC93Q==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.19.4", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" + "@babel/plugin-transform-parameters": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -1366,13 +1398,13 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", - "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", "@babel/plugin-syntax-optional-chaining": "^7.8.3" }, "engines": { @@ -1399,14 +1431,14 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", + "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, "engines": { @@ -1496,12 +1528,12 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", - "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz", + "integrity": "sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.19.0" }, "engines": { "node": ">=6.9.0" @@ -1625,12 +1657,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", - "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", + "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1640,14 +1672,14 @@ } }, "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", + "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -1672,12 +1704,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.19.4.tgz", - "integrity": "sha512-934S2VLLlt2hRJwPf4MczaOr4hYF0z+VKPwqTNxyKX7NthTiPfhuKFWQZHXRM0vh/wo/VyXB3s4bZUNA08l+tQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", + "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1687,18 +1719,18 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz", - "integrity": "sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", + "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.19.0", + "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-replace-supers": "^7.20.7", "@babel/helper-split-export-declaration": "^7.18.6", "globals": "^11.1.0" }, @@ -1710,12 +1742,13 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", - "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", + "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7" }, "engines": { "node": ">=6.9.0" @@ -1725,12 +1758,12 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.19.4.tgz", - "integrity": "sha512-t0j0Hgidqf0aM86dF8U+vXYReUgJnlv4bZLsyoPnwZNrGY+7/38o8YjaELrvHeVfTZao15kjR0PVv0nju2iduA==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", + "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1787,12 +1820,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", + "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1849,14 +1882,13 @@ } }, "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", - "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", + "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1866,15 +1898,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", - "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", + "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-simple-access": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1884,16 +1915,15 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz", - "integrity": "sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==", + "version": "7.20.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", + "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", "dev": true, "dependencies": { "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-identifier": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" + "@babel/helper-module-transforms": "^7.20.11", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-identifier": "^7.19.1" }, "engines": { "node": ">=6.9.0" @@ -1919,13 +1949,13 @@ } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", - "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", + "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", "dev": true, "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-create-regexp-features-plugin": "^7.20.5", + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1966,12 +1996,12 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", + "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1996,13 +2026,13 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", + "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" + "@babel/helper-plugin-utils": "^7.20.2", + "regenerator-transform": "^0.15.1" }, "engines": { "node": ">=6.9.0" @@ -2027,16 +2057,16 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz", - "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==", + "version": "7.19.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz", + "integrity": "sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.9", - "babel-plugin-polyfill-corejs2": "^0.3.2", - "babel-plugin-polyfill-corejs3": "^0.5.3", - "babel-plugin-polyfill-regenerator": "^0.4.0", + "@babel/helper-plugin-utils": "^7.19.0", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", "semver": "^6.3.0" }, "engines": { @@ -2071,13 +2101,13 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz", - "integrity": "sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", + "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" }, "engines": { "node": ">=6.9.0" @@ -2163,18 +2193,18 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", - "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", + "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", + "@babel/compat-data": "^7.20.1", + "@babel/helper-compilation-targets": "^7.20.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-validator-option": "^7.18.6", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-async-generator-functions": "^7.20.1", "@babel/plugin-proposal-class-properties": "^7.18.6", "@babel/plugin-proposal-class-static-block": "^7.18.6", "@babel/plugin-proposal-dynamic-import": "^7.18.6", @@ -2183,7 +2213,7 @@ "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-object-rest-spread": "^7.20.2", "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", "@babel/plugin-proposal-optional-chaining": "^7.18.9", "@babel/plugin-proposal-private-methods": "^7.18.6", @@ -2194,7 +2224,7 @@ "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.18.6", + "@babel/plugin-syntax-import-assertions": "^7.20.0", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -2207,10 +2237,10 @@ "@babel/plugin-transform-arrow-functions": "^7.18.6", "@babel/plugin-transform-async-to-generator": "^7.18.6", "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.18.9", - "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-block-scoping": "^7.20.2", + "@babel/plugin-transform-classes": "^7.20.2", "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.20.2", "@babel/plugin-transform-dotall-regex": "^7.18.6", "@babel/plugin-transform-duplicate-keys": "^7.18.9", "@babel/plugin-transform-exponentiation-operator": "^7.18.6", @@ -2218,30 +2248,30 @@ "@babel/plugin-transform-function-name": "^7.18.9", "@babel/plugin-transform-literals": "^7.18.9", "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-amd": "^7.19.6", + "@babel/plugin-transform-modules-commonjs": "^7.19.6", + "@babel/plugin-transform-modules-systemjs": "^7.19.6", "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", "@babel/plugin-transform-new-target": "^7.18.6", "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-parameters": "^7.20.1", "@babel/plugin-transform-property-literals": "^7.18.6", "@babel/plugin-transform-regenerator": "^7.18.6", "@babel/plugin-transform-reserved-words": "^7.18.6", "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-spread": "^7.19.0", "@babel/plugin-transform-sticky-regex": "^7.18.6", "@babel/plugin-transform-template-literals": "^7.18.9", "@babel/plugin-transform-typeof-symbol": "^7.18.9", "@babel/plugin-transform-unicode-escapes": "^7.18.10", "@babel/plugin-transform-unicode-regex": "^7.18.6", "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.10", - "babel-plugin-polyfill-corejs2": "^0.3.2", - "babel-plugin-polyfill-corejs3": "^0.5.3", - "babel-plugin-polyfill-regenerator": "^0.4.0", - "core-js-compat": "^3.22.1", + "@babel/types": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "core-js-compat": "^3.25.1", "semver": "^6.3.0" }, "engines": { @@ -2276,46 +2306,52 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "node_modules/@babel/runtime": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", - "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "version": "7.20.13", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.13.tgz", + "integrity": "sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==", "dev": true, "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", - "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.4", + "@babel/generator": "^7.21.3", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.4", - "@babel/types": "^7.19.4", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2324,13 +2360,14 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.19.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", - "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", "dev": true, "dependencies": { - "@babel/types": "^7.19.4", + "@babel/types": "^7.21.3", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -2352,9 +2389,9 @@ } }, "node_modules/@babel/types": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", - "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", @@ -2374,287 +2411,6 @@ "node": ">=0.1.90" } }, - "node_modules/@csstools/postcss-cascade-layers": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", - "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", - "dev": true, - "dependencies": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-color-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", - "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", - "dev": true, - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-font-format-keywords": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", - "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-hwb-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", - "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-ic-unit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", - "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", - "dev": true, - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-is-pseudo-class": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", - "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", - "dev": true, - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-nested-calc": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", - "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-normalize-display-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", - "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-oklab-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", - "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", - "dev": true, - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/@csstools/postcss-stepped-value-functions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", - "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-text-decoration-shorthand": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", - "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-trigonometric-functions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", - "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/postcss-unset-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "dev": true, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/@csstools/selector-specificity": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", - "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", - "dev": true, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2", - "postcss-selector-parser": "^6.0.10" - } - }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -2664,10 +2420,170 @@ "node": ">=10.0.0" } }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.8.tgz", + "integrity": "sha512-0/rb91GYKhrtbeglJXOhAv9RuYimgI8h623TplY2X+vA4EXnk3Zj1fXZreJ0J3OJJu1bwmb0W7g+2cT/d8/l/w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.8.tgz", + "integrity": "sha512-oa/N5j6v1svZQs7EIRPqR8f+Bf8g6HBDjD/xHC02radE/NjKHK7oQmtmLxPs1iVwYyvE+Kolo6lbpfEQ9xnhxQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.8.tgz", + "integrity": "sha512-bTliMLqD7pTOoPg4zZkXqCDuzIUguEWLpeqkNfC41ODBHwoUgZ2w5JBeYimv4oP6TDVocoYmEhZrCLQTrH89bg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.8.tgz", + "integrity": "sha512-ghAbV3ia2zybEefXRRm7+lx8J/rnupZT0gp9CaGy/3iolEXkJ6LYRq4IpQVI9zR97ID80KJVoUlo3LSeA/sMAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.8.tgz", + "integrity": "sha512-n5WOpyvZ9TIdv2V1K3/iIkkJeKmUpKaCTdun9buhGRWfH//osmUjlv4Z5mmWdPWind/VGcVxTHtLfLCOohsOXw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.8.tgz", + "integrity": "sha512-a/SATTaOhPIPFWvHZDoZYgxaZRVHn0/LX1fHLGfZ6C13JqFUZ3K6SMD6/HCtwOQ8HnsNaEeokdiDSFLuizqv5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.8.tgz", + "integrity": "sha512-xpFJb08dfXr5+rZc4E+ooZmayBW6R3q59daCpKZ/cDU96/kvDM+vkYzNeTJCGd8rtO6fHWMq5Rcv/1cY6p6/0Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.8.tgz", + "integrity": "sha512-6Ij8gfuGszcEwZpi5jQIJCVIACLS8Tz2chnEBfYjlmMzVsfqBP1iGmHQPp7JSnZg5xxK9tjCc+pJ2WtAmPRFVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.8.tgz", + "integrity": "sha512-v3iwDQuDljLTxpsqQDl3fl/yihjPAyOguxuloON9kFHYwopeJEf1BkDXODzYyXEI19gisEsQlG1bM65YqKSIww==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.8.tgz", + "integrity": "sha512-8svILYKhE5XetuFk/B6raFYIyIqydQi+GngEXJgdPdI7OMKUbSd7uzR02wSY4kb53xBrClLkhH4Xs8P61Q2BaA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/linux-loong64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.5.tgz", - "integrity": "sha512-UHkDFCfSGTuXq08oQltXxSZmH1TXyWsL+4QhZDWvvLl6mEJQqk3u7/wq1LjhrrAXYIllaTtRSzUXl4Olkf2J8A==", + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.8.tgz", + "integrity": "sha512-B6FyMeRJeV0NpyEOYlm5qtQfxbdlgmiGdD+QsipzKfFky0K5HW5Td6dyK3L3ypu1eY4kOmo7wW0o94SBqlqBSA==", "cpu": [ "loong64" ], @@ -2680,6 +2596,182 @@ "node": ">=12" } }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.8.tgz", + "integrity": "sha512-CCb67RKahNobjm/eeEqeD/oJfJlrWyw29fgiyB6vcgyq97YAf3gCOuP6qMShYSPXgnlZe/i4a8WFHBw6N8bYAA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.8.tgz", + "integrity": "sha512-bytLJOi55y55+mGSdgwZ5qBm0K9WOCh0rx+vavVPx+gqLLhxtSFU0XbeYy/dsAAD6xECGEv4IQeFILaSS2auXw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.8.tgz", + "integrity": "sha512-2YpRyQJmKVBEHSBLa8kBAtbhucaclb6ex4wchfY0Tj3Kg39kpjeJ9vhRU7x4mUpq8ISLXRXH1L0dBYjAeqzZAw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.8.tgz", + "integrity": "sha512-QgbNY/V3IFXvNf11SS6exkpVcX0LJcob+0RWCgV9OiDAmVElnxciHIisoSix9uzYzScPmS6dJFbZULdSAEkQVw==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.8.tgz", + "integrity": "sha512-mM/9S0SbAFDBc4OPoyP6SEOo5324LpUxdpeIUUSrSTOfhHU9hEfqRngmKgqILqwx/0DVJBzeNW7HmLEWp9vcOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.8.tgz", + "integrity": "sha512-eKUYcWaWTaYr9zbj8GertdVtlt1DTS1gNBWov+iQfWuWyuu59YN6gSEJvFzC5ESJ4kMcKR0uqWThKUn5o8We6Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.8.tgz", + "integrity": "sha512-Vc9J4dXOboDyMXKD0eCeW0SIeEzr8K9oTHJU+Ci1mZc5njPfhKAqkRt3B/fUNU7dP+mRyralPu8QUkiaQn7iIg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.8.tgz", + "integrity": "sha512-0xvOTNuPXI7ft1LYUgiaXtpCEjp90RuBBYovdd2lqAFxje4sEucurg30M1WIm03+3jxByd3mfo+VUmPtRSVuOw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.8.tgz", + "integrity": "sha512-G0JQwUI5WdEFEnYNKzklxtBheCPkuDdu1YrtRrjuQv30WsYbkkoixKxLLv8qhJmNI+ATEWquZe/N0d0rpr55Mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.8.tgz", + "integrity": "sha512-Fqy63515xl20OHGFykjJsMnoIWS+38fqfg88ClvPXyDbLtgXal2DTlhb1TfTX34qWi3u4I7Cq563QcHpqgLx8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.8.tgz", + "integrity": "sha512-1iuezdyDNngPnz8rLRDO2C/ZZ/emJLb72OsZeqQ6gL6Avko/XCXZw+NuxBSNhBAP13Hie418V7VMt9et1FMvpg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -2789,9 +2881,9 @@ "dev": true }, "node_modules/@microsoft/signalr": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-6.0.10.tgz", - "integrity": "sha512-ND9LiIYac+ZDgCgW2QzpNfe9BTiOtjc2AX/2GtFIhRGhEzx5CixcNANg2VGj27IAxycAPPnEoy7+QA31Eil7QQ==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-6.0.15.tgz", + "integrity": "sha512-rQNX3lOy2gfWdI8V9fCIZfI/daSoQe3a7AQ5/JhKowlYu7RUdx5KG8eGzcBFN/esjoVi8xDgqHMK9PJBhWFquw==", "dependencies": { "abort-controller": "^3.0.0", "eventsource": "^1.0.7", @@ -2801,18 +2893,18 @@ } }, "node_modules/@ngtools/webpack": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-14.2.6.tgz", - "integrity": "sha512-HdfoHLGPzyP135BOlvTQcpeWisVfiH0u40YNTBVK3QAsrLnY17e2QG5BWBOrVYipRu1975cZtTC9rPjcCY8aLQ==", + "version": "15.2.4", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-15.2.4.tgz", + "integrity": "sha512-cQ7MsRoGJgPOVnpvFgWhygeSe6zJ0ITiUhjmmuOgpNDfYkrgYxN3Ot/qvQefFei+oGZ1JJ9bRb8lcPKL/apoBQ==", "dev": true, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, "peerDependencies": { - "@angular/compiler-cli": "^14.0.0", - "typescript": ">=4.6.2 <4.9", + "@angular/compiler-cli": "^15.0.0", + "typescript": ">=4.8.2 <5.0", "webpack": "^5.54.0" } }, @@ -2877,73 +2969,94 @@ } }, "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", "dev": true, "dependencies": { - "@gar/promisify": "^1.1.3", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/git": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", - "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.0.3.tgz", + "integrity": "sha512-8cXNkDIbnXPVbhXMmQ7/bklCAjtmPaXfI9aEM4iH+xSuEHINLMHhlfESvVwdqmHJRJkR48vNJTSUvoF6GRPSFA==", "dev": true, "dependencies": { - "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", "lru-cache": "^7.4.4", "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", "promise-inflight": "^1.0.1", "promise-retry": "^2.0.1", "semver": "^7.3.5", - "which": "^2.0.2" + "which": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@npmcli/git/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", "dev": true, "dependencies": { "isexe": "^2.0.0" }, "bin": { - "node-which": "bin/node-which" + "node-which": "bin/which.js" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/installed-package-contents": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", - "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", "dev": true, "dependencies": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "bin": { - "installed-package-contents": "index.js" + "installed-package-contents": "lib/index.js" }, "engines": { - "node": ">= 10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/move-file": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, "dependencies": { "mkdirp": "^1.0.4", @@ -2953,72 +3066,115 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@npmcli/node-gyp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", - "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/promise-spawn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", "dev": true, "dependencies": { - "infer-owner": "^1.0.4" + "which": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@npmcli/run-script": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.3.tgz", - "integrity": "sha512-ZXL6qgC5NjwfZJ2nET+ZSLEz/PJgJ/5CU90C2S66dZY4Jw73DasS4ZCXuy/KHWYP0imjJ4VtA+Gebb5BxxKp9Q==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.0.tgz", + "integrity": "sha512-ql+AbRur1TeOdl1FY+RAwGW9fcr4ZwiVKabdvm93mujGREVuVLbdkXRJDrkTXSdCjaxYydr1wlA2v67jxWG5BQ==", "dev": true, "dependencies": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^8.4.1", - "read-package-json-fast": "^2.0.3" + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.0.tgz", + "integrity": "sha512-nla//68K9NU6yRiwDY/Q8aU6siKlSs64aEC7+IV56QoAuyQT2ovsJcgGYGyqMOmI/CGN1BOR6mM5EN0FBO+zyQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/@schematics/angular": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-14.0.7.tgz", - "integrity": "sha512-I0v1gNFpm9ReL/hUzwjjOa+hk0qvlXv/vjITAWnlUV5dba6FZxzwsrTGsGO6t5XMNsm6QtwpDYDRdy9uy/n/1g==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-15.1.6.tgz", + "integrity": "sha512-y2kIQ1wJL0wR6v/LM5+PFJUivrYtdaIJVRdOXLLWl0AB5aLwObiWgLzAuBsbGm/9//WPPhw9PglS5EFFxTBDzg==", "dev": true, "dependencies": { - "@angular-devkit/core": "14.0.7", - "@angular-devkit/schematics": "14.0.7", - "jsonc-parser": "3.0.0" + "@angular-devkit/core": "15.1.6", + "@angular-devkit/schematics": "15.1.6", + "jsonc-parser": "3.2.0" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" } }, "node_modules/@schematics/angular/node_modules/@angular-devkit/core": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", - "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-15.1.6.tgz", + "integrity": "sha512-jGgxyRjecVf6lEyqDxz7ltMEndNPxIg720pk6r40fgsu0dU8w9vjJSJe7k0XdJiXVRcN6wZa/J5nO/xcwWVIsA==", "dev": true, "dependencies": { - "ajv": "8.11.0", + "ajv": "8.12.0", "ajv-formats": "2.1.1", - "jsonc-parser": "3.0.0", + "jsonc-parser": "3.2.0", "rxjs": "6.6.7", - "source-map": "0.7.3" + "source-map": "0.7.4" }, "engines": { - "node": "^14.15.0 || >=16.10.0", + "node": "^14.20.0 || ^16.13.0 || >=18.10.0", "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", "yarn": ">= 1.13.0" }, @@ -3031,12 +3187,6 @@ } } }, - "node_modules/@schematics/angular/node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, "node_modules/@schematics/angular/node_modules/rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", @@ -3049,15 +3199,6 @@ "npm": ">=2.0.0" } }, - "node_modules/@schematics/angular/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, "node_modules/@schematics/angular/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -3070,12 +3211,12 @@ "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "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==", "dev": true, "engines": { - "node": ">= 6" + "node": ">= 10" } }, "node_modules/@types/body-parser": { @@ -3123,15 +3264,18 @@ "dev": true }, "node_modules/@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/eslint": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", - "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", + "version": "8.21.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.2.tgz", + "integrity": "sha512-EMpxUyystd3uZVByZap1DACsMXvb82ypQnGn89e1Y0a+LYu3JJscUd/gqhRsVFDkaD2MIiWo0MT8EfXr3DGRKw==", "dev": true, "dependencies": { "@types/estree": "*", @@ -3155,21 +3299,21 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", + "version": "4.17.33", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", + "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", "dev": true, "dependencies": { "@types/node": "*", @@ -3178,9 +3322,9 @@ } }, "node_modules/@types/http-proxy": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", - "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", + "version": "1.17.10", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.10.tgz", + "integrity": "sha512-Qs5aULi+zV1bwKAg5z1PWnDXWmsn+LxIvUGv6E2+OOMYhclZMO+OXd9pYVf2gLykf2I7IV2u7oTHwChPNsvJ7g==", "dev": true, "dependencies": { "@types/node": "*" @@ -3205,9 +3349,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", + "version": "18.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.3.tgz", + "integrity": "sha512-p6ua9zBxz5otCmbpb5D3U4B5Nanw6Pk3PPyX05xnxbB/fRv71N7CPmORg7uAD5P70T0xmx1pzAx/FUfa5X+3cw==", "dev": true }, "node_modules/@types/parse-json": { @@ -3244,9 +3388,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", "dev": true, "dependencies": { "@types/mime": "*", @@ -3272,9 +3416,9 @@ } }, "node_modules/@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz", + "integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==", "dev": true, "dependencies": { "@types/node": "*" @@ -3481,9 +3625,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -3515,9 +3659,9 @@ } }, "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -3541,28 +3685,19 @@ } }, "node_modules/agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.3.0.tgz", + "integrity": "sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==", "dev": true, "dependencies": { "debug": "^4.1.0", - "depd": "^1.1.2", + "depd": "^2.0.0", "humanize-ms": "^1.2.1" }, "engines": { "node": ">= 8.0.0" } }, - "node_modules/agentkeepalive/node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -3577,9 +3712,9 @@ } }, "node_modules/ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -3679,9 +3814,9 @@ } }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -3726,9 +3861,9 @@ "dev": true }, "node_modules/autoprefixer": { - "version": "10.4.12", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.12.tgz", - "integrity": "sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==", + "version": "10.4.13", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", + "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", "dev": true, "funding": [ { @@ -3742,7 +3877,7 @@ ], "dependencies": { "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001407", + "caniuse-lite": "^1.0.30001426", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -3759,45 +3894,20 @@ } }, "node_modules/babel-loader": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", - "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.2.tgz", + "integrity": "sha512-mN14niXW43tddohGl8HPu5yfQq70iUThvFL/4QzESA7GcZoC0eVOhvWdQ8+3UlSjaDE9MVtsW9mxDY07W7VpVA==", "dev": true, "dependencies": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" + "find-cache-dir": "^3.3.2", + "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 8.9" + "node": ">= 14.15.0" }, "peerDependencies": { - "@babel/core": "^7.0.0", - "webpack": ">=2" - } - }, - "node_modules/babel-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "dependencies": { - "object.assign": "^4.1.0" + "@babel/core": "^7.12.0", + "webpack": ">=5" } }, "node_modules/babel-plugin-istanbul": { @@ -3840,13 +3950,13 @@ } }, "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", - "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", + "integrity": "sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==", "dev": true, "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.3.2", - "core-js-compat": "^3.21.0" + "@babel/helper-define-polyfill-provider": "^0.3.3", + "core-js-compat": "^3.25.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" @@ -3935,13 +4045,13 @@ } }, "node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", "dev": true, "dependencies": { "bytes": "3.1.2", - "content-type": "~1.0.4", + "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", @@ -3949,7 +4059,7 @@ "iconv-lite": "0.4.24", "on-finished": "2.4.1", "qs": "6.11.0", - "raw-body": "2.5.1", + "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" }, @@ -3974,9 +4084,9 @@ "dev": true }, "node_modules/bonjour-service": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.14.tgz", - "integrity": "sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.0.tgz", + "integrity": "sha512-LVRinRB3k1/K0XzZ2p58COnWvkQknIY6sf0zF2rpErvcJXpMBttEPQSxK+HEXSS9VmpZlDoDnQWv8ftJT20B0Q==", "dev": true, "dependencies": { "array-flatten": "^2.1.2", @@ -4013,9 +4123,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "dev": true, "funding": [ { @@ -4028,10 +4138,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -4089,32 +4199,36 @@ } }, "node_modules/cacache": { - "version": "16.1.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.2.tgz", - "integrity": "sha512-Xx+xPlfCZIUHagysjjOAje9nRo8pRDczQCcXb4J2O0BLtH+xeVue6ba4y1kfJfQMAnM2mkcoMIAyOctlaRGWYA==", + "version": "17.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz", + "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==", "dev": true, "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", "glob": "^8.0.1", - "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", - "minipass": "^3.1.6", + "minipass": "^4.0.0", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", + "ssri": "^10.0.0", "tar": "^6.1.11", - "unique-filename": "^1.1.1" + "unique-filename": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" } }, "node_modules/call-bind": { @@ -4149,9 +4263,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001421", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001421.tgz", - "integrity": "sha512-Sw4eLbgUJAEhjLs1Fa+mk45sidp1wRn5y6GtDpHGBaNJ9OCDJaVh2tIaWWUnGfuXfKf1JCBaIarak3FkVAvEeA==", + "version": "1.0.30001467", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001467.tgz", + "integrity": "sha512-cEdN/5e+RPikvl9AHm4uuLXxeCNq8rFsQ+lPHTfe/OtypP3WwnVVbjn+6uBV7PaFL6xUFzTh+sSCOz1rKhcO+Q==", "dev": true, "funding": [ { @@ -4272,14 +4386,17 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/clone": { @@ -4471,9 +4588,9 @@ } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "engines": { "node": ">= 0.6" @@ -4548,32 +4665,13 @@ "node": ">=10.13.0" } }, - "node_modules/copy-webpack-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/core-js-compat": { - "version": "3.25.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.5.tgz", - "integrity": "sha512-ovcyhs2DEBUIE0MGEKHP4olCUW/XYte3Vroyxuh38rD1wAO4dHohsovUC4eAOuzFxE6b+RXvBU3UZ9o0YhUTkA==", + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.1.tgz", + "integrity": "sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==", "dev": true, "dependencies": { - "browserslist": "^4.21.4" + "browserslist": "^4.21.5" }, "funding": { "type": "opencollective", @@ -4600,9 +4698,9 @@ } }, "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "dependencies": { "@types/parse-json": "^4.0.0", @@ -4728,56 +4826,20 @@ "node": ">= 8" } }, - "node_modules/css-blank-pseudo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "bin": { - "css-blank-pseudo": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/css-has-pseudo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "bin": { - "css-has-pseudo": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", + "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.7", + "postcss": "^8.4.19", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" + "semver": "^7.3.8" }, "engines": { "node": ">= 12.13.0" @@ -4790,21 +4852,6 @@ "webpack": "^5.0.0" } }, - "node_modules/css-prefers-color-scheme": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "dev": true, - "bin": { - "css-prefers-color-scheme": "dist/cli.cjs" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -4833,16 +4880,6 @@ "url": "https://github.com/sponsors/fb55" } }, - "node_modules/cssdb": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.2.tgz", - "integrity": "sha512-Vm4b6P/PifADu0a76H0DKRNVWq3Rq9xa/Nx6oEMUBJlwTUuZoZ3dkZxo8Gob3UEL53Cq+Ma1GBgISed6XEBs3w==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -4919,22 +4956,6 @@ "node": ">=8" } }, - "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -5085,9 +5106,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "version": "1.4.332", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.332.tgz", + "integrity": "sha512-c1Vbv5tuUlBFp0mb3mCIjw+REEsgthRgNE8BlbEDKmvzb8rxjcVki6OkQP83vLN34s0XCxpSkq7AZNep1a6xhw==", "dev": true }, "node_modules/emoji-regex": { @@ -5136,9 +5157,9 @@ } }, "node_modules/engine.io": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", - "integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.4.1.tgz", + "integrity": "sha512-JFYQurD/nbsA5BSPmbaOSLa3tSVj8L6o4srSwXXY3NqE+gGUNmmPTbhn8tjzcCtSqhFgIeqef81ngny8JM25hw==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -5150,28 +5171,28 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "ws": "~8.11.0" }, "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io-client": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", - "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", + "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", "engine.io-parser": "~5.0.3", - "ws": "~8.2.3", + "ws": "~8.11.0", "xmlhttprequest-ssl": "~2.0.0" } }, "node_modules/engine.io-client/node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "engines": { "node": ">=10.0.0" }, @@ -5189,17 +5210,17 @@ } }, "node_modules/engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", + "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", "engines": { "node": ">=10.0.0" } }, "node_modules/engine.io/node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", "dev": true, "engines": { "node": ">=10.0.0" @@ -5218,9 +5239,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", + "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -5289,9 +5310,9 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.5.tgz", - "integrity": "sha512-VSf6S1QVqvxfIsSKb3UKr3VhUCis7wgDbtF4Vd9z84UJr05/Sp2fRKmzC+CSPG/dNAPPJZ0BTBLTT1Fhd6N9Gg==", + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.8.tgz", + "integrity": "sha512-g24ybC3fWhZddZK6R3uD2iF/RIPnRpwJAqLov6ouX3hMbY4+tKolP0VMF3zuIYCaXun+yHwS5IPQ91N2BT191g==", "dev": true, "hasInstallScript": true, "optional": true, @@ -5302,305 +5323,34 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/linux-loong64": "0.15.5", - "esbuild-android-64": "0.15.5", - "esbuild-android-arm64": "0.15.5", - "esbuild-darwin-64": "0.15.5", - "esbuild-darwin-arm64": "0.15.5", - "esbuild-freebsd-64": "0.15.5", - "esbuild-freebsd-arm64": "0.15.5", - "esbuild-linux-32": "0.15.5", - "esbuild-linux-64": "0.15.5", - "esbuild-linux-arm": "0.15.5", - "esbuild-linux-arm64": "0.15.5", - "esbuild-linux-mips64le": "0.15.5", - "esbuild-linux-ppc64le": "0.15.5", - "esbuild-linux-riscv64": "0.15.5", - "esbuild-linux-s390x": "0.15.5", - "esbuild-netbsd-64": "0.15.5", - "esbuild-openbsd-64": "0.15.5", - "esbuild-sunos-64": "0.15.5", - "esbuild-windows-32": "0.15.5", - "esbuild-windows-64": "0.15.5", - "esbuild-windows-arm64": "0.15.5" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.5.tgz", - "integrity": "sha512-dYPPkiGNskvZqmIK29OPxolyY3tp+c47+Fsc2WYSOVjEPWNCHNyqhtFqQadcXMJDQt8eN0NMDukbyQgFcHquXg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.5.tgz", - "integrity": "sha512-YyEkaQl08ze3cBzI/4Cm1S+rVh8HMOpCdq8B78JLbNFHhzi4NixVN93xDrHZLztlocEYqi45rHHCgA8kZFidFg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.5.tgz", - "integrity": "sha512-Cr0iIqnWKx3ZTvDUAzG0H/u9dWjLE4c2gTtRLz4pqOBGjfjqdcZSfAObFzKTInLLSmD0ZV1I/mshhPoYSBMMCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.5.tgz", - "integrity": "sha512-WIfQkocGtFrz7vCu44ypY5YmiFXpsxvz2xqwe688jFfSVCnUsCn2qkEVDo7gT8EpsLOz1J/OmqjExePL1dr1Kg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.5.tgz", - "integrity": "sha512-M5/EfzV2RsMd/wqwR18CELcenZ8+fFxQAAEO7TJKDmP3knhWSbD72ILzrXFMMwshlPAS1ShCZ90jsxkm+8FlaA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.5.tgz", - "integrity": "sha512-2JQQ5Qs9J0440F/n/aUBNvY6lTo4XP/4lt1TwDfHuo0DY3w5++anw+jTjfouLzbJmFFiwmX7SmUhMnysocx96w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.5.tgz", - "integrity": "sha512-gO9vNnIN0FTUGjvTFucIXtBSr1Woymmx/aHQtuU+2OllGU6YFLs99960UD4Dib1kFovVgs59MTXwpFdVoSMZoQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.5.tgz", - "integrity": "sha512-ne0GFdNLsm4veXbTnYAWjbx3shpNKZJUd6XpNbKNUZaNllDZfYQt0/zRqOg0sc7O8GQ+PjSMv9IpIEULXVTVmg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.5.tgz", - "integrity": "sha512-wvAoHEN+gJ/22gnvhZnS/+2H14HyAxM07m59RSLn3iXrQsdS518jnEWRBnJz3fR6BJa+VUTo0NxYjGaNt7RA7Q==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.5.tgz", - "integrity": "sha512-7EgFyP2zjO065XTfdCxiXVEk+f83RQ1JsryN1X/VSX2li9rnHAt2swRbpoz5Vlrl6qjHrCmq5b6yxD13z6RheA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.5.tgz", - "integrity": "sha512-KdnSkHxWrJ6Y40ABu+ipTZeRhFtc8dowGyFsZY5prsmMSr1ZTG9zQawguN4/tunJ0wy3+kD54GaGwdcpwWAvZQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.5.tgz", - "integrity": "sha512-QdRHGeZ2ykl5P0KRmfGBZIHmqcwIsUKWmmpZTOq573jRWwmpfRmS7xOhmDHBj9pxv+6qRMH8tLr2fe+ZKQvCYw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.5.tgz", - "integrity": "sha512-p+WE6RX+jNILsf+exR29DwgV6B73khEQV0qWUbzxaycxawZ8NE0wA6HnnTxbiw5f4Gx9sJDUBemh9v49lKOORA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.5.tgz", - "integrity": "sha512-J2ngOB4cNzmqLHh6TYMM/ips8aoZIuzxJnDdWutBw5482jGXiOzsPoEF4j2WJ2mGnm7FBCO4StGcwzOgic70JQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.5.tgz", - "integrity": "sha512-MmKUYGDizYjFia0Rwt8oOgmiFH7zaYlsoQ3tIOfPxOqLssAsEgG0MUdRDm5lliqjiuoog8LyDu9srQk5YwWF3w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.5.tgz", - "integrity": "sha512-2mMFfkLk3oPWfopA9Plj4hyhqHNuGyp5KQyTT9Rc8hFd8wAn5ZrbJg+gNcLMo2yzf8Uiu0RT6G9B15YN9WQyMA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.5.tgz", - "integrity": "sha512-2sIzhMUfLNoD+rdmV6AacilCHSxZIoGAU2oT7XmJ0lXcZWnCvCtObvO6D4puxX9YRE97GodciRGDLBaiC6x1SA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" + "@esbuild/android-arm": "0.17.8", + "@esbuild/android-arm64": "0.17.8", + "@esbuild/android-x64": "0.17.8", + "@esbuild/darwin-arm64": "0.17.8", + "@esbuild/darwin-x64": "0.17.8", + "@esbuild/freebsd-arm64": "0.17.8", + "@esbuild/freebsd-x64": "0.17.8", + "@esbuild/linux-arm": "0.17.8", + "@esbuild/linux-arm64": "0.17.8", + "@esbuild/linux-ia32": "0.17.8", + "@esbuild/linux-loong64": "0.17.8", + "@esbuild/linux-mips64el": "0.17.8", + "@esbuild/linux-ppc64": "0.17.8", + "@esbuild/linux-riscv64": "0.17.8", + "@esbuild/linux-s390x": "0.17.8", + "@esbuild/linux-x64": "0.17.8", + "@esbuild/netbsd-x64": "0.17.8", + "@esbuild/openbsd-x64": "0.17.8", + "@esbuild/sunos-x64": "0.17.8", + "@esbuild/win32-arm64": "0.17.8", + "@esbuild/win32-ia32": "0.17.8", + "@esbuild/win32-x64": "0.17.8" } }, "node_modules/esbuild-wasm": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.15.5.tgz", - "integrity": "sha512-lTJOEKekN/4JI/eOEq0wLcx53co2N6vaT/XjBz46D1tvIVoUEyM0o2K6txW6gEotf31szFD/J1PbxmnbkGlK9A==", + "version": "0.17.8", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.17.8.tgz", + "integrity": "sha512-zCmpxv95E0FuCmvdw1K836UHnj4EdiQnFfjTby35y3LAjRPtXMj3sbHDRHjbD8Mqg5lTwq3knacr/1qIFU51CQ==", "dev": true, "bin": { "esbuild": "bin/esbuild" @@ -5609,54 +5359,6 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-32": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.5.tgz", - "integrity": "sha512-e+duNED9UBop7Vnlap6XKedA/53lIi12xv2ebeNS4gFmu7aKyTrok7DPIZyU5w/ftHD4MUDs5PJUkQPP9xJRzg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.5.tgz", - "integrity": "sha512-v+PjvNtSASHOjPDMIai9Yi+aP+Vwox+3WVdg2JB8N9aivJ7lyhp4NVU+J0MV2OkWFPnVO8AE/7xH+72ibUUEnw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.5.tgz", - "integrity": "sha512-Yz8w/D8CUPYstvVQujByu6mlf48lKmXkq6bkeSZZxTA626efQOJb26aDGLzmFWx6eg/FwrXgt6SZs9V8Pwy/aA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -5863,6 +5565,30 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, + "node_modules/express/node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/express/node_modules/cookie": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", @@ -5905,6 +5631,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/express/node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -5963,9 +5704,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -6168,15 +5909,15 @@ } }, "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.1.tgz", + "integrity": "sha512-MhaJDcFRTuLidHrIttu0RDGyyXs/IYHVmlcxfLAEFIWjc1vdLAkdwT7Ace2u7DbitWC0toKMl5eJZRYNVreIMw==", "dev": true, "dependencies": { - "minipass": "^3.0.0" + "minipass": "^4.0.0" }, "engines": { - "node": ">= 8" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/fs-monkey": { @@ -6249,9 +5990,9 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", "dev": true, "dependencies": { "function-bind": "^1.1.1", @@ -6284,9 +6025,9 @@ } }, "node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -6330,9 +6071,9 @@ } }, "node_modules/globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.3.tgz", + "integrity": "sha512-8krCNHXvlCgHDpegPzleMq07yMYTO2sXKASmZmquEYWEmCx6J5UTRbp5RwMJkTJGtcQ44YpiUYUiN0b9mzy8Bw==", "dev": true, "dependencies": { "dir-glob": "^3.0.1", @@ -6349,9 +6090,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/handle-thing": { @@ -6381,18 +6122,6 @@ "node": ">=4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -6429,15 +6158,24 @@ "dev": true }, "node_modules/hosted-git-info": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", "dev": true, "dependencies": { "lru-cache": "^7.5.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" } }, "node_modules/hpack.js": { @@ -6453,9 +6191,9 @@ } }, "node_modules/hpack.js/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -6495,9 +6233,9 @@ "dev": true }, "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", "dev": true }, "node_modules/http-deceiver": { @@ -6552,12 +6290,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==", "dev": true, "dependencies": { - "@tootallnate/once": "1", + "@tootallnate/once": "2", "agent-base": "6", "debug": "4" }, @@ -6665,24 +6403,39 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" } }, "node_modules/ignore-walk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", - "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.1.tgz", + "integrity": "sha512-/c8MxUAqpRccq+LyDOecwF+9KqajueJHh8fz7g3YqjMZt+NSfJzx05zrKiXwa2sKwFCzaiZ5qUVfRj0pmxixEA==", "dev": true, "dependencies": { - "minimatch": "^5.0.1" + "minimatch": "^6.1.6" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz", + "integrity": "sha512-sauLxniAmvnhhRjFwPNnJKaPFYyddAgbYdeUpHULtCT/GhzdCx/MDNy+Y40lBxTQUrMzDE8e0S43Z5uqfO0REg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/image-size": { @@ -6699,9 +6452,9 @@ } }, "node_modules/immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz", + "integrity": "sha512-0AOCmOip+xgJwEVTQj1EfiDDOkPmuyllDuTuEX+DDXUgapLAsBIfkg3sxCYyCEA8mQqZrrxPUGjcOQ2JS3WLkg==", "dev": true }, "node_modules/import-fresh": { @@ -6770,9 +6523,9 @@ "dev": true }, "node_modules/ini": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.0.tgz", - "integrity": "sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.1.tgz", + "integrity": "sha512-it4HyVAUTKBc6m8e1iXWvXSTdndF7HbdN713+kvLrymxTaU4AUBWrJ4vEooP+V7fexnVD3LKcBshjGGPefSMUQ==", "dev": true, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" @@ -6908,9 +6661,9 @@ } }, "node_modules/is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -7280,9 +7033,9 @@ "dev": true }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "bin": { "json5": "lib/cli.js" @@ -7292,9 +7045,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", - "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, "node_modules/jsonfile": { @@ -7446,6 +7199,17 @@ "concat-map": "0.0.1" } }, + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/karma/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -7478,18 +7242,6 @@ "node": "*" } }, - "node_modules/karma/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/karma/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7548,9 +7300,9 @@ } }, "node_modules/klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", "dev": true, "engines": { "node": ">= 8" @@ -7583,9 +7335,9 @@ } }, "node_modules/less-loader": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.0.0.tgz", - "integrity": "sha512-9+LOWWjuoectIEx3zrfN83NAGxSUB5pWEabbbidVQVgZhN+wN68pOvuyirVlH1IK4VT1f3TmlyvAnCXh8O5KEw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", "dev": true, "dependencies": { "klona": "^2.0.4" @@ -7629,16 +7381,6 @@ "node": ">=4" } }, - "node_modules/less/node_modules/pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/less/node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -7692,9 +7434,9 @@ } }, "node_modules/loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", "dev": true, "engines": { "node": ">= 12.13.0" @@ -7811,37 +7553,37 @@ } }, "node_modules/log4js": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.7.0.tgz", - "integrity": "sha512-KA0W9ffgNBLDj6fZCq/lRbgR6ABAodRIDHrZnS48vOtfKa4PzWImb0Md1lmGCdO3n3sbCm/n1/WmrNlZ8kCI3Q==", + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", "dev": true, "dependencies": { "date-format": "^4.0.14", "debug": "^4.3.4", "flatted": "^3.2.7", "rfdc": "^1.3.0", - "streamroller": "^3.1.3" + "streamroller": "^3.1.5" }, "engines": { "node": ">=8.0" } }, "node_modules/lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "engines": { - "node": ">=12" + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/magic-string": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz", - "integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.29.0.tgz", + "integrity": "sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==", "dev": true, "dependencies": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.4.13" }, "engines": { "node": ">=12" @@ -7872,150 +7614,161 @@ } }, "node_modules/make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", "dev": true, "dependencies": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", + "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", + "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", + "negotiator": "^0.6.3", "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" }, "engines": { - "node": ">= 10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", "dev": true, "dependencies": { - "@gar/promisify": "^1.0.1", + "@gar/promisify": "^1.1.3", "semver": "^7.3.5" - } - }, - "node_modules/make-fetch-happen/node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" }, "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", "dev": true, "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" }, "engines": { - "node": ">= 10" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/make-fetch-happen/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/make-fetch-happen/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minipass": "^3.0.0" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">= 8" } }, "node_modules/make-fetch-happen/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==", + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { "yallist": "^4.0.0" }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, "engines": { "node": ">=10" } }, - "node_modules/make-fetch-happen/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", "dev": true, "dependencies": { "minipass": "^3.1.1" }, "engines": { - "node": ">= 8" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/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/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -8026,9 +7779,9 @@ } }, "node_modules/memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.13.tgz", + "integrity": "sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==", "dev": true, "dependencies": { "fs-monkey": "^1.0.3" @@ -8123,9 +7876,9 @@ } }, "node_modules/mini-css-extract-plugin": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", - "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", + "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", "dev": true, "dependencies": { "schema-utils": "^4.0.0" @@ -8141,25 +7894,6 @@ "webpack": "^5.0.0" } }, - "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -8167,9 +7901,9 @@ "dev": true }, "node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -8179,22 +7913,19 @@ } }, "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.5.tgz", + "integrity": "sha512-+yQl7SX3bIT83Lhb4BVorMAHVuqsskxRdlmO9kTpyukp8vsm2Sn/fUOV9xlnG8/a5JsypJzap21lz/y3FBMJ8Q==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { "node": ">=8" } @@ -8211,23 +7942,59 @@ "node": ">= 8" } }, - "node_modules/minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "dependencies": { - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" + "yallist": "^4.0.0" }, "engines": { "node": ">=8" + } + }, + "node_modules/minipass-collect/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/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" }, "optionalDependencies": { - "encoding": "^0.1.12" + "encoding": "^0.1.13" } }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/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/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", @@ -8240,6 +8007,24 @@ "node": ">= 8" } }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/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/minipass-json-stream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", @@ -8250,6 +8035,24 @@ "minipass": "^3.0.0" } }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream/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/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", @@ -8262,6 +8065,24 @@ "node": ">=8" } }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/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/minipass-sized": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", @@ -8274,6 +8095,24 @@ "node": ">=8" } }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/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/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -8287,16 +8126,34 @@ "node": ">= 8" } }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" + "dependencies": { + "yallist": "^4.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/minizlib/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/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" } }, "node_modules/ms": { @@ -8336,9 +8193,9 @@ } }, "node_modules/needle": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", - "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", "dev": true, "optional": true, "dependencies": { @@ -8414,9 +8271,9 @@ "optional": true }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8442,16 +8299,16 @@ } }, "node_modules/node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.3.1.tgz", + "integrity": "sha512-4Q16ZCqq3g8awk6UplT7AuxQ35XN4R/yf/+wSAwcBUAjg7l58RTactWaP8fIDTi0FzI7YcVLujwExakZlfWkXg==", "dev": true, "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", "npmlog": "^6.0.0", "rimraf": "^3.0.2", "semver": "^7.3.5", @@ -8462,13 +8319,13 @@ "node-gyp": "bin/node-gyp.js" }, "engines": { - "node": ">= 10.12.0" + "node": "^12.13 || ^14.13 || >=16" } }, "node_modules/node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", "dev": true, "optional": true, "bin": { @@ -8535,39 +8392,39 @@ } }, "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "dev": true }, "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", "dev": true, "dependencies": { - "abbrev": "1" + "abbrev": "^1.0.0" }, "bin": { "nopt": "bin/nopt.js" }, "engines": { - "node": ">=6" + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, "node_modules/normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", "dev": true, "dependencies": { - "hosted-git-info": "^5.0.0", + "hosted-git-info": "^6.0.0", "is-core-module": "^2.8.1", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/normalize-path": { @@ -8589,199 +8446,150 @@ } }, "node_modules/npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", "dev": true, "dependencies": { - "npm-normalize-package-bin": "^1.0.1" + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-install-checks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", - "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.0.0.tgz", + "integrity": "sha512-SBU9oFglRVZnfElwAtF14NivyulDqF1VKqqwNsFW9HDcbHMAPHpRSsVFgKuwFGq/hVvWZExz62Th0kvxn/XE7Q==", "dev": true, "dependencies": { "semver": "^7.1.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.0.tgz", + "integrity": "sha512-g+DPQSkusnk7HYXr75NtzkIP4+N81i3RPsGFidF3DzHd9MT9wWngmqoeg/fnHFz5MNdtG4w03s+QnhewSLTT2Q==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/npm-package-arg": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.0.2.tgz", - "integrity": "sha512-v/miORuX8cndiOheW8p2moNuPJ7QhcFh9WGlTorruG8hXSA23vMTEp5hTCmDxic0nD8KHhj/NQgFuySD3GYY3g==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", "dev": true, "dependencies": { - "hosted-git-info": "^5.0.0", + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" + "validate-npm-package-name": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-packlist": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz", - "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", "dev": true, "dependencies": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "bin": { - "npm-packlist": "bin/index.js" + "ignore-walk": "^6.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm-packlist/node_modules/npm-bundled": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz", - "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", - "dev": true, - "dependencies": { - "npm-normalize-package-bin": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/npm-packlist/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-pick-manifest": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.1.tgz", - "integrity": "sha512-IA8+tuv8KujbsbLQvselW2XQgmXWS47t3CB0ZrzsRZ82DbDfkcFunOaPm4X7qNuhMfq+FmV7hQT4iFVpHqV7mg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", "dev": true, "dependencies": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^1.0.1", - "npm-package-arg": "^9.0.0", + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", "semver": "^7.3.5" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-registry-fetch": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", - "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.3.tgz", + "integrity": "sha512-YaeRbVNpnWvsGOjX2wk5s85XJ7l1qQBGAp724h8e2CZFFhMSuw9enom7K1mWVUtvXO1uUSFIAPofQK0pPN0ZcA==", "dev": true, "dependencies": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", + "make-fetch-happen": "^11.0.0", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", "minipass-json-stream": "^1.0.1", "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/npm-registry-fetch/node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/npm-registry-fetch/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", "dev": true, "engines": { - "node": ">= 10" - } - }, - "node_modules/npm-registry-fetch/node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" + "node": ">=12" } }, "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.3.tgz", + "integrity": "sha512-oPLh5m10lRNNZDjJ2kP8UpboUx2uFXVaVweVe/lWut4iHWcQEmfqSVJt2ihZsFI8HbpwyyocaXbCAWf0g1ukIA==", "dev": true, "dependencies": { "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", + "minipass": "^4.0.0", + "minipass-fetch": "^3.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" + "ssri": "^10.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz", + "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==", "dev": true, "dependencies": { - "minipass": "^3.1.6", + "minipass": "^4.0.0", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" }, "optionalDependencies": { "encoding": "^0.1.13" } }, - "node_modules/npm-registry-fetch/node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -8831,41 +8639,14 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -8918,9 +8699,9 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.1.tgz", + "integrity": "sha512-/4b7qZNhv6Uhd7jjnREh1NjnPxlTq+XNWPG88Ydkj5AILcA5m3ajvcg57pB24EQjKv0dK62XnDqk9c/hkIG5Kg==", "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", @@ -9110,38 +8891,34 @@ } }, "node_modules/pacote": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.3.0.tgz", - "integrity": "sha512-auhJAUlfC2TALo6I0s1vFoPvVFgWGx+uz/PnIojTTgkGwlK3Np8sGJ0ghfFhiuzJXTZoTycMLk8uLskdntPbDw==", + "version": "15.0.8", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.0.8.tgz", + "integrity": "sha512-UlcumB/XS6xyyIMwg/WwMAyUmga+RivB5KgkRwA1hZNtrx+0Bt41KxHCvg1kr0pZ/ZeD8qjhW4fph6VaYRCbLw==", "dev": true, "dependencies": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^3.0.1", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.0.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^4.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "ssri": "^10.0.0", "tar": "^6.1.11" }, "bin": { "pacote": "lib/bin.js" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/pako": { @@ -9196,13 +8973,41 @@ "dev": true }, "node_modules/parse5-html-rewriting-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", - "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", "dev": true, "dependencies": { - "parse5": "^6.0.1", - "parse5-sax-parser": "^6.0.1" + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parse5-htmlparser2-tree-adapter": { @@ -9215,12 +9020,39 @@ } }, "node_modules/parse5-sax-parser": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", - "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", "dev": true, "dependencies": { - "parse5": "^6.0.1" + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser/node_modules/entities": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz", + "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parse5-sax-parser/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" } }, "node_modules/parseurl": { @@ -9299,12 +9131,13 @@ } }, "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "node_modules/piscina": { @@ -9334,9 +9167,9 @@ } }, "node_modules/postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", "dev": true, "funding": [ { @@ -9357,337 +9190,15 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-attribute-case-insensitive": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", - "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=7.6.0" - }, - "peerDependencies": { - "postcss": "^8.4.6" - } - }, - "node_modules/postcss-color-functional-notation": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", - "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-color-hex-alpha": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", - "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-color-rebeccapurple": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", - "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-custom-media": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", - "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/postcss-custom-properties": { - "version": "12.1.9", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.9.tgz", - "integrity": "sha512-/E7PRvK8DAVljBbeWrcEQJPG72jaImxF3vvCNFwv9cC8CzigVoNIpeyfnJzphnN3Fd8/auBf5wvkw6W9MfmTyg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-custom-selectors": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", - "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.4" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.3" - } - }, - "node_modules/postcss-dir-pseudo-class": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", - "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-double-position-gradients": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", - "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", - "dev": true, - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-env-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-focus-visible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-focus-within": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.9" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "dev": true, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/postcss-gap-properties": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "dev": true, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-image-set-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", - "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-import": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.0.0.tgz", - "integrity": "sha512-Y20shPQ07RitgBGv2zvkEAu9bqvrD77C9axhj/aA1BQj4czape2MdClCExvB27EwYEJdGgKZBpKanb0t1rK2Kg==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "dev": true, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-lab-function": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", - "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", - "dev": true, - "dependencies": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, "node_modules/postcss-loader": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.0.1.tgz", - "integrity": "sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.0.2.tgz", + "integrity": "sha512-fUJzV/QH7NXUAqV8dWJ9Lg4aTkDCezpTS5HgJ2DvqznexTbSTxgi/dTECvTZ15BwKTtk8G/bqI/QTu2HPd3ZCg==", "dev": true, "dependencies": { "cosmiconfig": "^7.0.0", "klona": "^2.0.5", - "semver": "^7.3.7" + "semver": "^7.3.8" }, "engines": { "node": ">= 14.15.0" @@ -9701,30 +9212,6 @@ "webpack": "^5.0.0" } }, - "node_modules/postcss-logical": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "dev": true, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, "node_modules/postcss-modules-extract-imports": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", @@ -9784,210 +9271,10 @@ "postcss": "^8.1.0" } }, - "node_modules/postcss-nesting": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", - "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", - "dev": true, - "dependencies": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-opacity-percentage": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", - "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==", - "dev": true, - "funding": [ - { - "type": "kofi", - "url": "https://ko-fi.com/mrcgrtz" - }, - { - "type": "liberapay", - "url": "https://liberapay.com/mrcgrtz" - } - ], - "engines": { - "node": "^12 || ^14 || >=16" - } - }, - "node_modules/postcss-overflow-shorthand": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", - "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "dev": true, - "peerDependencies": { - "postcss": "^8" - } - }, - "node_modules/postcss-place": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", - "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", - "dev": true, - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-preset-env": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.0.tgz", - "integrity": "sha512-leqiqLOellpLKfbHkD06E04P6d9ZQ24mat6hu4NSqun7WG0UhspHR5Myiv/510qouCjoo4+YJtNOqg5xHaFnCA==", - "dev": true, - "dependencies": { - "@csstools/postcss-cascade-layers": "^1.0.5", - "@csstools/postcss-color-function": "^1.1.1", - "@csstools/postcss-font-format-keywords": "^1.0.1", - "@csstools/postcss-hwb-function": "^1.0.2", - "@csstools/postcss-ic-unit": "^1.0.1", - "@csstools/postcss-is-pseudo-class": "^2.0.7", - "@csstools/postcss-nested-calc": "^1.0.0", - "@csstools/postcss-normalize-display-values": "^1.0.1", - "@csstools/postcss-oklab-function": "^1.1.1", - "@csstools/postcss-progressive-custom-properties": "^1.3.0", - "@csstools/postcss-stepped-value-functions": "^1.0.1", - "@csstools/postcss-text-decoration-shorthand": "^1.0.0", - "@csstools/postcss-trigonometric-functions": "^1.0.2", - "@csstools/postcss-unset-value": "^1.0.2", - "autoprefixer": "^10.4.8", - "browserslist": "^4.21.3", - "css-blank-pseudo": "^3.0.3", - "css-has-pseudo": "^3.0.4", - "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^7.0.0", - "postcss-attribute-case-insensitive": "^5.0.2", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.4", - "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^8.0.2", - "postcss-custom-properties": "^12.1.8", - "postcss-custom-selectors": "^6.0.3", - "postcss-dir-pseudo-class": "^6.0.5", - "postcss-double-position-gradients": "^3.1.2", - "postcss-env-function": "^4.0.6", - "postcss-focus-visible": "^6.0.4", - "postcss-focus-within": "^5.0.4", - "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^3.0.5", - "postcss-image-set-function": "^4.0.7", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.1", - "postcss-logical": "^5.0.4", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.1.10", - "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.4", - "postcss-page-break": "^3.0.4", - "postcss-place": "^7.0.5", - "postcss-pseudo-class-any-link": "^7.1.6", - "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^6.0.1", - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-pseudo-class-any-link": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", - "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, - "node_modules/postcss-replace-overflow-wrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "dev": true, - "peerDependencies": { - "postcss": "^8.0.3" - } - }, - "node_modules/postcss-selector-not": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", - "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", - "dev": true, - "dependencies": { - "postcss-selector-parser": "^6.0.10" - }, - "engines": { - "node": "^12 || ^14 || >=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - }, - "peerDependencies": { - "postcss": "^8.2" - } - }, "node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -10021,28 +9308,28 @@ "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA==" }, "node_modules/primeng": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-14.1.2.tgz", - "integrity": "sha512-iLMeORiLD46SNAotxCwRXoaRMXLs3ZbFzyePrPSNAFQbKEbsLfpUvsAUAatb/TA0jd8TnXgdCjZ07ee4664XVQ==", + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/primeng/-/primeng-15.2.0.tgz", + "integrity": "sha512-CLcB4RYiI4PcQ8nwov01L5CQHbhl7n1OufA2OKIq9+C4sBEv9sLsnEN2/Cah4m1jtrRkNbsac8JJE7LdPxecaQ==", "dependencies": { "tslib": "^2.3.0" }, "peerDependencies": { - "@angular/common": "^14.0.0", - "@angular/core": "^14.0.0", - "@angular/forms": "^14.0.0", + "@angular/common": "^15.1.0", + "@angular/core": "^15.1.0", + "@angular/forms": "^15.1.0", "primeicons": "^6.0.1", - "rxjs": "^6.0.0 || ^7.0.0", - "zone.js": "^0.10.2 || ^0.11.0" + "rxjs": "^6.0.0 || ^7.5.0", + "zone.js": "^0.10.2 || ^0.11.0 || ^0.12.0" } }, "node_modules/proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/process-nextick-args": { @@ -10105,9 +9392,9 @@ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "engines": { "node": ">=6" } @@ -10180,9 +9467,9 @@ } }, "node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", "dev": true, "dependencies": { "bytes": "3.1.2", @@ -10194,56 +9481,56 @@ "node": ">= 0.8" } }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "dependencies": { - "pify": "^2.3.0" - } - }, "node_modules/read-package-json": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz", - "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.0.tgz", + "integrity": "sha512-b/9jxWJ8EwogJPpv99ma+QwtqB7FSl3+V6UXS7Aaay8/5VwMY50oIFooY1UKXMWpfNCM6T/PoGqa5GD1g9xf9w==", "dev": true, "dependencies": { "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", "dev": true, "dependencies": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" }, "engines": { - "node": ">=10" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/read-package-json/node_modules/npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", "dev": true, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { "inherits": "^2.0.3", @@ -10291,15 +9578,15 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", "dev": true }, "node_modules/regenerator-transform": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", - "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", + "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", "dev": true, "dependencies": { "@babel/runtime": "^7.8.4" @@ -10312,28 +9599,22 @@ "dev": true }, "node_modules/regexpu-core": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz", - "integrity": "sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, "dependencies": { + "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", "regjsparser": "^0.9.1", "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" + "unicode-match-property-value-ecmascript": "^2.1.0" }, "engines": { "node": ">=4" } }, - "node_modules/regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, "node_modules/regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", @@ -10379,12 +9660,12 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", "dev": true, "dependencies": { - "is-core-module": "^2.8.1", + "is-core-module": "^2.9.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -10421,9 +9702,9 @@ } }, "node_modules/resolve-url-loader/node_modules/loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "dependencies": { "big.js": "^5.2.2", @@ -10605,9 +9886,9 @@ "devOptional": true }, "node_modules/sass": { - "version": "1.54.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.4.tgz", - "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==", + "version": "1.58.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.1.tgz", + "integrity": "sha512-bnINi6nPXbP1XNRaranMFEBZWUfdW/AF16Ql5+ypRxfTvCRTTKrLsMIakyDcayUt2t/RZotmL4kgJwNH5xO+bg==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -10622,9 +9903,9 @@ } }, "node_modules/sass-loader": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.2.tgz", - "integrity": "sha512-BbiqbVmbfJaWVeOOAu2o7DhYWtcNmTfvroVgFXa6k2hHheMxNAeDHLNoDy/Q5aoaVlz0LH+MbMktKwm9vN/j8Q==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz", + "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==", "dev": true, "dependencies": { "klona": "^2.0.4", @@ -10639,7 +9920,7 @@ }, "peerDependencies": { "fibers": ">= 3.1.0", - "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "sass": "^1.3.0", "sass-embedded": "*", "webpack": "^5.0.0" @@ -10663,57 +9944,28 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true + "dev": true, + "optional": true }, "node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", + "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" + "@types/json-schema": "^7.0.9", + "ajv": "^8.8.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.0.0" }, "engines": { - "node": ">= 8.9.0" + "node": ">= 12.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" } }, - "node_modules/schema-utils/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/schema-utils/node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/schema-utils/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -10733,9 +9985,9 @@ } }, "node_modules/semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -10759,6 +10011,12 @@ "node": ">=10" } }, + "node_modules/semver/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/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -10826,9 +10084,9 @@ } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", "dev": true, "dependencies": { "randombytes": "^2.1.0" @@ -11006,46 +10264,70 @@ } }, "node_modules/socket.io": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz", - "integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.6.1.tgz", + "integrity": "sha512-KMcaAi4l/8+xEjkRICl6ak8ySoxsYG+gG6/XfRCPJPQ/haCRIJBTL4wIl8YCsmtaBovcAXGLOShyVWQ/FG8GZA==", "dev": true, "dependencies": { "accepts": "~1.3.4", "base64id": "~2.0.0", "debug": "~4.3.2", - "engine.io": "~6.2.0", - "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.2.0" + "engine.io": "~6.4.1", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.1" }, "engines": { "node": ">=10.0.0" } }, "node_modules/socket.io-adapter": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz", - "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==", - "dev": true + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "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/socket.io-client": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.3.tgz", - "integrity": "sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.1.tgz", + "integrity": "sha512-5UswCV6hpaRsNg5kkEHVcbBIXEYoVbMQaHJBXJCyEQ+CiFPV1NIOY0XOFWG4XR4GZcB8Kn6AsRs/9cy9TbqVMQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", - "engine.io-client": "~6.2.3", - "socket.io-parser": "~4.2.0" + "engine.io-client": "~6.4.0", + "socket.io-parser": "~4.2.1" }, "engines": { "node": ">=10.0.0" } }, "node_modules/socket.io-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", - "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", + "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -11080,9 +10362,9 @@ } }, "node_modules/socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", "dev": true, "dependencies": { "agent-base": "^6.0.2", @@ -11112,9 +10394,9 @@ } }, "node_modules/source-map-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.0.tgz", - "integrity": "sha512-i3KVgM3+QPAHNbGavK+VBq03YoJl24m9JWNbLgsjTj8aJzXG9M61bantBTNBt7CNwY2FYf+RJRYJ3pzalKjIrw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", "dev": true, "dependencies": { "abab": "^2.0.6", @@ -11163,16 +10445,10 @@ "node": ">=0.10.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -11196,9 +10472,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "node_modules/spdy": { @@ -11238,15 +10514,15 @@ "dev": true }, "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.1.tgz", + "integrity": "sha512-WVy6di9DlPOeBWEjMScpNipeSX2jIZBGEn5Uuo8Q7aIuFEuDX0pw8RxcOjlD1TWP4obi24ki7m/13+nFpcbXrw==", "dev": true, "dependencies": { - "minipass": "^3.1.1" + "minipass": "^4.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/statuses": { @@ -11259,9 +10535,9 @@ } }, "node_modules/streamroller": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", - "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", "dev": true, "dependencies": { "date-format": "^4.0.14", @@ -11316,92 +10592,6 @@ "node": ">=6" } }, - "node_modules/stylus": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.59.0.tgz", - "integrity": "sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==", - "dev": true, - "dependencies": { - "@adobe/css-tools": "^4.0.1", - "debug": "^4.3.2", - "glob": "^7.1.6", - "sax": "~1.2.4", - "source-map": "^0.7.3" - }, - "bin": { - "stylus": "bin/stylus" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://opencollective.com/stylus" - } - }, - "node_modules/stylus-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-7.0.0.tgz", - "integrity": "sha512-WTbtLrNfOfLgzTaR9Lj/BPhQroKk/LC1hfTXSUbrxmxgfUo3Y3LpmKRVA2R1XbjvTAvOfaian9vOyfv1z99E+A==", - "dev": true, - "dependencies": { - "fast-glob": "^3.2.11", - "klona": "^2.0.5", - "normalize-path": "^3.0.0" - }, - "engines": { - "node": ">= 14.15.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "stylus": ">=0.52.4", - "webpack": "^5.0.0" - } - }, - "node_modules/stylus/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/stylus/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/stylus/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -11445,26 +10635,68 @@ } }, "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "version": "6.1.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", + "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", "dev": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", + "minipass": "^4.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "engines": { - "node": ">= 10" + "node": ">=10" } }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/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/terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "version": "5.16.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", + "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", @@ -11480,16 +10712,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.7.tgz", + "integrity": "sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.5" }, "engines": { "node": ">= 10.13.0" @@ -11562,6 +10794,24 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.16.6", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.6.tgz", + "integrity": "sha512-IBZ+ZQIA9sMaXmRZCUMDjNH0D5AQQfdn4WUjHL0+1lF4TP1IHRJbrhb6fNaXWikrYQTSkb7SLxkeXAiy1p7mbg==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -11715,9 +10965,9 @@ } }, "node_modules/tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", + "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, "node_modules/type-fest": { "version": "0.21.3", @@ -11751,9 +11001,9 @@ "dev": true }, "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -11764,9 +11014,9 @@ } }, "node_modules/ua-parser-js": { - "version": "0.7.32", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz", - "integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==", + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.34.tgz", + "integrity": "sha512-cJMeh/eOILyGu0ejgTKB95yKT3zOenSe9UGE3vj6WfiOwgGYnmATUsnDixMFvdU+rNMvWih83hrUP8VwhF9yXQ==", "dev": true, "funding": [ { @@ -11805,9 +11055,9 @@ } }, "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", "dev": true, "engines": { "node": ">=4" @@ -11823,21 +11073,27 @@ } }, "node_modules/unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", "dev": true, "dependencies": { - "unique-slug": "^2.0.0" + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/universalify": { @@ -11937,15 +11193,15 @@ } }, "node_modules/validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", "dev": true, "dependencies": { "builtins": "^5.0.0" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, "node_modules/vary": { @@ -12003,9 +11259,9 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", + "version": "5.76.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", + "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -12050,51 +11306,32 @@ } }, "node_modules/webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.0.1.tgz", + "integrity": "sha512-PZPZ6jFinmqVPJZbisfggDiC+2EeGZ1ZByyMP5sOFJcPPWSexalISz+cvm+j+oYPT7FIJyxT76esjnw9DhE5sw==", "dev": true, "dependencies": { "colorette": "^2.0.10", - "memfs": "^3.4.3", + "memfs": "^3.4.12", "mime-types": "^2.1.31", "range-parser": "^1.2.1", "schema-utils": "^4.0.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 14.15.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - }, - "engines": { - "node": ">= 12.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" + "webpack": "^5.0.0" } }, "node_modules/webpack-dev-server": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.0.tgz", - "integrity": "sha512-L5S4Q2zT57SK7tazgzjMiSMBdsw+rGYIX27MgPgx7LDhWO0lViPrHKoLS7jo5In06PWYAhlYu3PbyoC6yAThbw==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz", + "integrity": "sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw==", "dev": true, "dependencies": { "@types/bonjour": "^3.5.9", @@ -12120,7 +11357,7 @@ "p-retry": "^4.5.0", "rimraf": "^3.0.2", "schema-utils": "^4.0.0", - "selfsigned": "^2.0.1", + "selfsigned": "^2.1.1", "serve-index": "^1.9.1", "sockjs": "^0.3.24", "spdy": "^4.0.2", @@ -12146,16 +11383,17 @@ } } }, - "node_modules/webpack-dev-server/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", "dev": true, "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" }, "engines": { "node": ">= 12.13.0" @@ -12163,19 +11401,22 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "dev": true, "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -12431,9 +11672,9 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, "node_modules/yaml": { @@ -12446,18 +11687,18 @@ } }, "node_modules/yargs": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", - "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", + "version": "17.6.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", + "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" @@ -12480,8979 +11721,5 @@ "tslib": "^2.3.0" } } - }, - "dependencies": { - "@adobe/css-tools": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.0.1.tgz", - "integrity": "sha512-+u76oB43nOHrF4DDWRLWDCtci7f3QJoEBigemIdIeTi1ODqjx6Tad9NCVnPRwewWlKkVab5PlK8DCtPTyX7S8g==", - "dev": true - }, - "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@angular-devkit/architect": { - "version": "0.1402.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1402.6.tgz", - "integrity": "sha512-qTmPBD7fBXBtlSapGLUEcJvRuL/O556zCFFpH3kSlzPNTYxi2falBjGY+4aG+078RXT1vVZtFsvRTart6VbhAg==", - "dev": true, - "requires": { - "@angular-devkit/core": "14.2.6", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/build-angular": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-14.2.6.tgz", - "integrity": "sha512-XtaUwb3aZ8S0vl0y9bmbdFOH0KQCQ778twFH+ZfHW2BcPYtQz2Cy2rcVKXBQ850RyC0GxgMPfco6OGQndPpizg==", - "dev": true, - "requires": { - "@ampproject/remapping": "2.2.0", - "@angular-devkit/architect": "0.1402.6", - "@angular-devkit/build-webpack": "0.1402.6", - "@angular-devkit/core": "14.2.6", - "@babel/core": "7.18.10", - "@babel/generator": "7.18.12", - "@babel/helper-annotate-as-pure": "7.18.6", - "@babel/plugin-proposal-async-generator-functions": "7.18.10", - "@babel/plugin-transform-async-to-generator": "7.18.6", - "@babel/plugin-transform-runtime": "7.18.10", - "@babel/preset-env": "7.18.10", - "@babel/runtime": "7.18.9", - "@babel/template": "7.18.10", - "@discoveryjs/json-ext": "0.5.7", - "@ngtools/webpack": "14.2.6", - "ansi-colors": "4.1.3", - "babel-loader": "8.2.5", - "babel-plugin-istanbul": "6.1.1", - "browserslist": "^4.9.1", - "cacache": "16.1.2", - "copy-webpack-plugin": "11.0.0", - "critters": "0.0.16", - "css-loader": "6.7.1", - "esbuild": "0.15.5", - "esbuild-wasm": "0.15.5", - "glob": "8.0.3", - "https-proxy-agent": "5.0.1", - "inquirer": "8.2.4", - "jsonc-parser": "3.1.0", - "karma-source-map-support": "1.4.0", - "less": "4.1.3", - "less-loader": "11.0.0", - "license-webpack-plugin": "4.0.2", - "loader-utils": "3.2.0", - "mini-css-extract-plugin": "2.6.1", - "minimatch": "5.1.0", - "open": "8.4.0", - "ora": "5.4.1", - "parse5-html-rewriting-stream": "6.0.1", - "piscina": "3.2.0", - "postcss": "8.4.16", - "postcss-import": "15.0.0", - "postcss-loader": "7.0.1", - "postcss-preset-env": "7.8.0", - "regenerator-runtime": "0.13.9", - "resolve-url-loader": "5.0.0", - "rxjs": "6.6.7", - "sass": "1.54.4", - "sass-loader": "13.0.2", - "semver": "7.3.7", - "source-map-loader": "4.0.0", - "source-map-support": "0.5.21", - "stylus": "0.59.0", - "stylus-loader": "7.0.0", - "terser": "5.14.2", - "text-table": "0.2.0", - "tree-kill": "1.2.2", - "tslib": "2.4.0", - "webpack": "5.74.0", - "webpack-dev-middleware": "5.3.3", - "webpack-dev-server": "4.11.0", - "webpack-merge": "5.8.0", - "webpack-subresource-integrity": "5.1.0" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true - } - } - }, - "@angular-devkit/build-webpack": { - "version": "0.1402.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1402.6.tgz", - "integrity": "sha512-gKsDxQ9pze0N1qDM0kdM4FfwpkjSOb0bQzqjZi7wTfrh/WGIQMCjG9CRwWT+Z289ZKaTpcQDPsDtOSo5QpKNDg==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.1402.6", - "rxjs": "6.6.7" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/core": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.2.6.tgz", - "integrity": "sha512-qtRSdRm/h7C3ya04PJTDgQXV6mM8Y4RakANX1GTSXetCf9AVSxg74NJX76DWUgiHT4JiPYnJgJU6Hr/L0H6JOQ==", - "dev": true, - "requires": { - "ajv": "8.11.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.1.0", - "rxjs": "6.6.7", - "source-map": "0.7.4" - }, - "dependencies": { - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-14.0.7.tgz", - "integrity": "sha512-nJUJXCBQr7rmVn6IXFAXMCWAB1w6JQmFGuFVW0G3GH/A0e+A3ttzJc6qVLYluqaFoafw394cZu24YJo55E/+Zg==", - "dev": true, - "requires": { - "@angular-devkit/core": "14.0.7", - "jsonc-parser": "3.0.0", - "magic-string": "0.26.1", - "ora": "5.4.1", - "rxjs": "6.6.7" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", - "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", - "dev": true, - "requires": { - "ajv": "8.11.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.0.0", - "rxjs": "6.6.7", - "source-map": "0.7.3" - } - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular/animations": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-14.2.6.tgz", - "integrity": "sha512-Tmb3Jj016j8m8OOGSk/ReL0b+OuUCMj0KQansk3C4pCpH9oPF67Vnm0fmVC2wYjjsSS/iDgl4kaDW740wfPGNQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/cli": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-14.0.7.tgz", - "integrity": "sha512-tABt1EDwBHm0ngsutdkXXWgPgHzapGLC7rSPHXStMc24ngViFZpXGzBCpompjHvXNt6bjklmJmuRvjS6+ktBZA==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.1400.7", - "@angular-devkit/core": "14.0.7", - "@angular-devkit/schematics": "14.0.7", - "@schematics/angular": "14.0.7", - "@yarnpkg/lockfile": "1.1.0", - "ansi-colors": "4.1.1", - "debug": "4.3.4", - "ini": "3.0.0", - "inquirer": "8.2.4", - "jsonc-parser": "3.0.0", - "npm-package-arg": "9.0.2", - "npm-pick-manifest": "7.0.1", - "open": "8.4.0", - "ora": "5.4.1", - "pacote": "13.3.0", - "resolve": "1.22.0", - "semver": "7.3.7", - "symbol-observable": "4.0.0", - "uuid": "8.3.2", - "yargs": "17.4.1" - }, - "dependencies": { - "@angular-devkit/architect": { - "version": "0.1400.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1400.7.tgz", - "integrity": "sha512-8dv/Ql86dHajsHYjjr5jvpiV7uXWbt7Mz4K/rGiOi+zzDNKPcZcuCejulWhOySDcCPjT/an47Qcwr+awL4Wr4g==", - "dev": true, - "requires": { - "@angular-devkit/core": "14.0.7", - "rxjs": "6.6.7" - } - }, - "@angular-devkit/core": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", - "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", - "dev": true, - "requires": { - "ajv": "8.11.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.0.0", - "rxjs": "6.6.7", - "source-map": "0.7.3" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@angular/common": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-14.2.6.tgz", - "integrity": "sha512-WNX7xe8LKP5DHPlae+c77PDwj0iIAAPIe1lWbhQysyi8uttbtL9VVP2XTFuQ3E6oVHJr+0IR0LMVGJ+a8i6zsw==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/compiler": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-14.2.6.tgz", - "integrity": "sha512-XtmJRNQQ/bUcRjB6jG67km3EPug8frnHH50sLqxye+cljCzWQpzFN/Qr1z0abuzEX8OC4alqxCDCFgTFyyVkaQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/compiler-cli": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-14.2.6.tgz", - "integrity": "sha512-zKnpZ5WDbM31dwr5GDAbCblMIEUzWSglUyqCxJfbCg21dE0EuLfd/WzsROgM2TucOtCT5xNipqz4bc+wdEOIgQ==", - "dev": true, - "requires": { - "@babel/core": "^7.17.2", - "chokidar": "^3.0.0", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.11.0", - "magic-string": "^0.26.0", - "reflect-metadata": "^0.1.2", - "semver": "^7.0.0", - "sourcemap-codec": "^1.4.8", - "tslib": "^2.3.0", - "yargs": "^17.2.1" - } - }, - "@angular/core": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-14.2.6.tgz", - "integrity": "sha512-fEIz7E488X03tLIqmWQRpahxRRU2SMjb9i/rMUjMQJkbppJC3cykl31bCYzeixNO+zpE55GPGuQX2qI/yDenZA==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/forms": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-14.2.6.tgz", - "integrity": "sha512-t7Hd9RMnHbXRTdH/H8h8ZC3PsK1U4rH+XYaIbQNcys/XSf1uRFHx9MWqkwS5hoQEFOxkFSX5dRv2xSnHtxfq5w==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/platform-browser": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-14.2.6.tgz", - "integrity": "sha512-KQUN4YVYEK5NOL7QFnDulQta6tm9rPh/mruX/XCLkSmoRMlFBmsHyjx+VJBnBNUbUxNsBj7kknifOu9PqDgAWg==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/platform-browser-dynamic": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-14.2.6.tgz", - "integrity": "sha512-SlWEYLED4ST1AFfgeB8SyKLVJYp36XT+3Vw3yDrObsthzXCiFAuYHQZfSWgT1Sfx3uFqEdN7nskJqD05wN3mQg==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@angular/router": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-14.2.6.tgz", - "integrity": "sha512-Vz1kadGSqA7ZCZQ2woNbSBPMdiE5eTZv8cGympaFnFQQUzQTQ6zi22wY4RzovDk5Lw+EQkvOmaW2864LDzDeug==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@assemblyscript/loader": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", - "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", - "dev": true - }, - "@auth0/angular-jwt": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-5.1.0.tgz", - "integrity": "sha512-EAQoNKPQSZYphcX6FnY2e7xQpD4ZdHQ1DbHq/m+G1U1qA60m3XnhdjPPfu+blVHARlxEbRzWXc48UOVrnMsrZw==", - "requires": { - "tslib": "^2.0.0" - } - }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.19.4.tgz", - "integrity": "sha512-CHIGpJcUQ5lU9KrPHTjBMhVwQG6CQjxfg36fGXl3qk/Gik1WwWachaXFuo0uCWJT/mStOKtcbFJCaVLihC1CMw==", - "dev": true - }, - "@babel/core": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", - "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", - "dev": true, - "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.10", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-module-transforms": "^7.18.9", - "@babel/helpers": "^7.18.9", - "@babel/parser": "^7.18.10", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.18.10", - "@babel/types": "^7.18.10", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.18.12", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", - "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.10", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.19.3", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.19.3.tgz", - "integrity": "sha512-65ESqLGyGmLvgR0mst5AdW1FkNlj9rQsCKduzEoEPhBCDFGXvz2jW6bXFG6i0/MrV2s7hhXjjb2yAzcPuQlLwg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.19.3", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.19.0.tgz", - "integrity": "sha512-NRz8DwF4jT3UfrmUoZjd0Uph9HQnP30t7Ash+weACcyNkiYTywpIjDBgReJMKgr+n86sn2nPVVmJ28Dm053Kqw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz", - "integrity": "sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.1.0" - } - }, - "@babel/helper-define-polyfill-provider": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz", - "integrity": "sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.17.7", - "@babel/helper-plugin-utils": "^7.16.7", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2", - "semver": "^6.1.2" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "dev": true - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", - "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.19.0.tgz", - "integrity": "sha512-3HBZ377Fe14RbLIA+ac3sY4PTgpxHVkFrESaWhoI5PuyXPBBX8+C34qblV9G89ZtycGJCmCI/Ut+VUDK4bltNQ==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.18.6", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", - "integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==", - "dev": true - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-replace-supers": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz", - "integrity": "sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.18.9", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/traverse": "^7.19.1", - "@babel/types": "^7.19.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.19.4.tgz", - "integrity": "sha512-f9Xq6WqBFqaDfbCzn2w85hwklswz5qsKlh7f08w4Y9yhJHpnNC0QemtSkK5YyOY8kPGvyiwdzZksGUhnGdaUIg==", - "dev": true, - "requires": { - "@babel/types": "^7.19.4" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", - "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", - "dev": true, - "requires": { - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz", - "integrity": "sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.0", - "@babel/types": "^7.19.0" - } - }, - "@babel/helpers": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.19.4.tgz", - "integrity": "sha512-G+z3aOx2nfDHwX/kyVii5fJq+bgscg89/dJNWpYeKeBv3v9xX8EIabmx1k6u9LS04H7nROFVRVK+e3k0VHp+sw==", - "dev": true, - "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.19.4", - "@babel/types": "^7.19.4" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.4.tgz", - "integrity": "sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==", - "dev": true - }, - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", - "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", - "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-proposal-optional-chaining": "^7.18.9" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", - "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", - "dev": true, - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-class-static-block": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", - "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", - "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", - "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.19.4.tgz", - "integrity": "sha512-wHmj6LDxVDnL+3WhXteUBaoM1aVILZODAUjg11kHqG4cOlfgMQGxw6aCgvrXrmaJR3Bn14oZhImyCPZzRpC93Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.19.4", - "@babel/helper-compilation-targets": "^7.19.3", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.18.8" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", - "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-private-property-in-object": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", - "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-import-assertions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", - "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", - "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", - "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-remap-async-to-generator": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.19.4.tgz", - "integrity": "sha512-934S2VLLlt2hRJwPf4MczaOr4hYF0z+VKPwqTNxyKX7NthTiPfhuKFWQZHXRM0vh/wo/VyXB3s4bZUNA08l+tQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.19.0.tgz", - "integrity": "sha512-YfeEE9kCjqTS9IitkgfJuxjcEtLUHMqa8yUJ6zdz8vR7hKuo6mOy2C05P0F1tdMmDCeuyidKnlrw/iTppHcr2A==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.19.0", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-replace-supers": "^7.18.9", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", - "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.19.4.tgz", - "integrity": "sha512-t0j0Hgidqf0aM86dF8U+vXYReUgJnlv4bZLsyoPnwZNrGY+7/38o8YjaELrvHeVfTZao15kjR0PVv0nju2iduA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dev": true, - "requires": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", - "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", - "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-simple-access": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.0.tgz", - "integrity": "sha512-x9aiR0WXAWmOWsqcsnrzGR+ieaTMVyGyffPVA7F8cXAGt/UxefYv6uSHZLkAFChN5M5Iy1+wjE+xJuPt22H39A==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-validator-identifier": "^7.18.6", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz", - "integrity": "sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.19.0", - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", - "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", - "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "regenerator-transform": "^0.15.0" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-runtime": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz", - "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.9", - "babel-plugin-polyfill-corejs2": "^0.3.2", - "babel-plugin-polyfill-corejs3": "^0.5.3", - "babel-plugin-polyfill-regenerator": "^0.4.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz", - "integrity": "sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/preset-env": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", - "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.18.8", - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.18.10", - "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", - "@babel/plugin-proposal-dynamic-import": "^7.18.6", - "@babel/plugin-proposal-export-namespace-from": "^7.18.9", - "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", - "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.18.9", - "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", - "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", - "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.18.9", - "@babel/plugin-transform-classes": "^7.18.9", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.18.9", - "@babel/plugin-transform-dotall-regex": "^7.18.6", - "@babel/plugin-transform-duplicate-keys": "^7.18.9", - "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", - "@babel/plugin-transform-function-name": "^7.18.9", - "@babel/plugin-transform-literals": "^7.18.9", - "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.18.6", - "@babel/plugin-transform-modules-commonjs": "^7.18.6", - "@babel/plugin-transform-modules-systemjs": "^7.18.9", - "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", - "@babel/plugin-transform-new-target": "^7.18.6", - "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.18.8", - "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", - "@babel/plugin-transform-reserved-words": "^7.18.6", - "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.18.9", - "@babel/plugin-transform-sticky-regex": "^7.18.6", - "@babel/plugin-transform-template-literals": "^7.18.9", - "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", - "@babel/plugin-transform-unicode-regex": "^7.18.6", - "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.18.10", - "babel-plugin-polyfill-corejs2": "^0.3.2", - "babel-plugin-polyfill-corejs3": "^0.5.3", - "babel-plugin-polyfill-regenerator": "^0.4.0", - "core-js-compat": "^3.22.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", - "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" - } - }, - "@babel/traverse": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.4.tgz", - "integrity": "sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.19.4", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.19.4", - "@babel/types": "^7.19.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/generator": { - "version": "7.19.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.5.tgz", - "integrity": "sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==", - "dev": true, - "requires": { - "@babel/types": "^7.19.4", - "@jridgewell/gen-mapping": "^0.3.2", - "jsesc": "^2.5.1" - } - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@babel/types": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.4.tgz", - "integrity": "sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==", - "dev": true, - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true - }, - "@csstools/postcss-cascade-layers": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz", - "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==", - "dev": true, - "requires": { - "@csstools/selector-specificity": "^2.0.2", - "postcss-selector-parser": "^6.0.10" - } - }, - "@csstools/postcss-color-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz", - "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-font-format-keywords": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz", - "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-hwb-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz", - "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-ic-unit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz", - "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-is-pseudo-class": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz", - "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==", - "dev": true, - "requires": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - } - }, - "@csstools/postcss-nested-calc": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz", - "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-normalize-display-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz", - "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-oklab-function": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz", - "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-progressive-custom-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz", - "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-stepped-value-functions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz", - "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-text-decoration-shorthand": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz", - "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-trigonometric-functions": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz", - "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "@csstools/postcss-unset-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz", - "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==", - "dev": true, - "requires": {} - }, - "@csstools/selector-specificity": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz", - "integrity": "sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==", - "dev": true, - "requires": {} - }, - "@discoveryjs/json-ext": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", - "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", - "dev": true - }, - "@esbuild/linux-loong64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.5.tgz", - "integrity": "sha512-UHkDFCfSGTuXq08oQltXxSZmH1TXyWsL+4QhZDWvvLl6mEJQqk3u7/wq1LjhrrAXYIllaTtRSzUXl4Olkf2J8A==", - "dev": true, - "optional": true - }, - "@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true - }, - "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", - "dev": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@leichtgewicht/ip-codec": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", - "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", - "dev": true - }, - "@microsoft/signalr": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-6.0.10.tgz", - "integrity": "sha512-ND9LiIYac+ZDgCgW2QzpNfe9BTiOtjc2AX/2GtFIhRGhEzx5CixcNANg2VGj27IAxycAPPnEoy7+QA31Eil7QQ==", - "requires": { - "abort-controller": "^3.0.0", - "eventsource": "^1.0.7", - "fetch-cookie": "^0.11.0", - "node-fetch": "^2.6.7", - "ws": "^7.4.5" - } - }, - "@ngtools/webpack": { - "version": "14.2.6", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-14.2.6.tgz", - "integrity": "sha512-HdfoHLGPzyP135BOlvTQcpeWisVfiH0u40YNTBVK3QAsrLnY17e2QG5BWBOrVYipRu1975cZtTC9rPjcCY8aLQ==", - "dev": true, - "requires": {} - }, - "@ngx-translate/core": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-14.0.0.tgz", - "integrity": "sha512-UevdwNCXMRCdJv//0kC8h2eSfmi02r29xeE8E9gJ1Al4D4jEJ7eiLPdjslTMc21oJNGguqqWeEVjf64SFtvw2w==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@ngx-translate/http-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-7.0.0.tgz", - "integrity": "sha512-j+NpXXlcGVdyUNyY/qsJrqqeAdJdizCd+GKh3usXExSqy1aE9866jlAIL+xrfDU4w+LiMoma5pgE4emvFebZmA==", - "requires": { - "tslib": "^2.3.0" - } - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - } - }, - "@npmcli/git": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-3.0.2.tgz", - "integrity": "sha512-CAcd08y3DWBJqJDpfuVL0uijlq5oaXaOJEKHKc4wqrjd00gkvTZB+nFuLn+doOOKddaQS9JfqtNoFCO2LCvA3w==", - "dev": true, - "requires": { - "@npmcli/promise-spawn": "^3.0.0", - "lru-cache": "^7.4.4", - "mkdirp": "^1.0.4", - "npm-pick-manifest": "^7.0.0", - "proc-log": "^2.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^2.0.2" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "@npmcli/installed-package-contents": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-1.0.7.tgz", - "integrity": "sha512-9rufe0wnJusCQoLpV9ZPKIVP55itrM5BxOXs10DmdbRfgWtHy1LDyskbwRnBghuB0PrF7pNPOqREVtpz4HqzKw==", - "dev": true, - "requires": { - "npm-bundled": "^1.1.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "@npmcli/node-gyp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz", - "integrity": "sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==", - "dev": true - }, - "@npmcli/promise-spawn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz", - "integrity": "sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==", - "dev": true, - "requires": { - "infer-owner": "^1.0.4" - } - }, - "@npmcli/run-script": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.3.tgz", - "integrity": "sha512-ZXL6qgC5NjwfZJ2nET+ZSLEz/PJgJ/5CU90C2S66dZY4Jw73DasS4ZCXuy/KHWYP0imjJ4VtA+Gebb5BxxKp9Q==", - "dev": true, - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^8.4.1", - "read-package-json-fast": "^2.0.3" - } - }, - "@schematics/angular": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-14.0.7.tgz", - "integrity": "sha512-I0v1gNFpm9ReL/hUzwjjOa+hk0qvlXv/vjITAWnlUV5dba6FZxzwsrTGsGO6t5XMNsm6QtwpDYDRdy9uy/n/1g==", - "dev": true, - "requires": { - "@angular-devkit/core": "14.0.7", - "@angular-devkit/schematics": "14.0.7", - "jsonc-parser": "3.0.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "14.0.7", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.0.7.tgz", - "integrity": "sha512-XBqK2OMVKkV1Ltkh4aBsoHoDJQlins5a6qa/ZMjW4reYx90qLERs8ZfeWlRUWhvn2/ohx4aPq77jwSR5avp/Cw==", - "dev": true, - "requires": { - "ajv": "8.11.0", - "ajv-formats": "2.1.1", - "jsonc-parser": "3.0.0", - "rxjs": "6.6.7", - "source-map": "0.7.3" - } - }, - "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", - "dev": true - }, - "rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - } - } - }, - "@socket.io/component-emitter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/bonjour": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", - "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/connect-history-api-fallback": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz", - "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/node": "*" - } - }, - "@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true - }, - "@types/cors": { - "version": "2.8.12", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", - "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", - "dev": true - }, - "@types/eslint": { - "version": "8.4.6", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.6.tgz", - "integrity": "sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==", - "dev": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", - "dev": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "0.0.51", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", - "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==", - "dev": true - }, - "@types/express": { - "version": "4.17.14", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", - "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.18", - "@types/qs": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.17.31", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz", - "integrity": "sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*" - } - }, - "@types/http-proxy": { - "version": "1.17.9", - "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.9.tgz", - "integrity": "sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/jasmine": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.0.3.tgz", - "integrity": "sha512-Opp1LvvEuZdk8fSSvchK2mZwhVrsNT0JgJE9Di6MjnaIpmEXM8TLCPPrVtNTYh8+5MPdY8j9bAHMu2SSfwpZJg==", - "dev": true - }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", - "dev": true - }, - "@types/node": { - "version": "18.11.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", - "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==", - "dev": true - }, - "@types/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", - "dev": true - }, - "@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", - "dev": true - }, - "@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true - }, - "@types/serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", - "dev": true, - "requires": { - "@types/mime": "*", - "@types/node": "*" - } - }, - "@types/socket.io-client": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-3.0.0.tgz", - "integrity": "sha512-s+IPvFoEIjKA3RdJz/Z2dGR4gLgysKi8owcnrVwNjgvc01Lk68LJDDsG2GRqegFITcxmvCMYM7bhMpwEMlHmDg==", - "requires": { - "socket.io-client": "*" - } - }, - "@types/sockjs": { - "version": "0.3.33", - "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", - "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz", - "integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", - "dev": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", - "dev": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", - "dev": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.11.1", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@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==", - "dev": true - }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "abab": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", - "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", - "dev": true - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "dev": true, - "requires": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", - "dev": true - }, - "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", - "dev": true, - "requires": {} - }, - "adjust-sourcemap-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", - "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "regex-parser": "^2.2.11" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "agentkeepalive": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz", - "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", - "humanize-ms": "^1.2.1" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - } - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-html-community": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", - "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "array-flatten": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", - "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", - "dev": true - }, - "autoprefixer": { - "version": "10.4.12", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.12.tgz", - "integrity": "sha512-WrCGV9/b97Pa+jtwf5UGaRjgQIg7OK3D06GnoYoZNcG1Xb8Gt3EfuKjlhh9i/VtT16g6PYjZ69jdJ2g8FxSC4Q==", - "dev": true, - "requires": { - "browserslist": "^4.21.4", - "caniuse-lite": "^1.0.30001407", - "fraction.js": "^4.2.0", - "normalize-range": "^0.1.2", - "picocolors": "^1.0.0", - "postcss-value-parser": "^4.2.0" - } - }, - "babel-loader": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.5.tgz", - "integrity": "sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==", - "dev": true, - "requires": { - "find-cache-dir": "^3.3.1", - "loader-utils": "^2.0.0", - "make-dir": "^3.1.0", - "schema-utils": "^2.6.5" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-polyfill-corejs2": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz", - "integrity": "sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.17.7", - "@babel/helper-define-polyfill-provider": "^0.3.3", - "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "babel-plugin-polyfill-corejs3": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", - "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.2", - "core-js-compat": "^3.21.0" - } - }, - "babel-plugin-polyfill-regenerator": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz", - "integrity": "sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==", - "dev": true, - "requires": { - "@babel/helper-define-polyfill-provider": "^0.3.3" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "dev": true - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "bonjour-service": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.0.14.tgz", - "integrity": "sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ==", - "dev": true, - "requires": { - "array-flatten": "^2.1.2", - "dns-equal": "^1.0.0", - "fast-deep-equal": "^3.1.3", - "multicast-dns": "^7.2.5" - } - }, - "boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" - } - }, - "buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "builtins": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", - "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", - "dev": true, - "requires": { - "semver": "^7.0.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true - }, - "cacache": { - "version": "16.1.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.2.tgz", - "integrity": "sha512-Xx+xPlfCZIUHagysjjOAje9nRo8pRDczQCcXb4J2O0BLtH+xeVue6ba4y1kfJfQMAnM2mkcoMIAyOctlaRGWYA==", - "dev": true, - "requires": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^1.1.1" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001421", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001421.tgz", - "integrity": "sha512-Sw4eLbgUJAEhjLs1Fa+mk45sidp1wRn5y6GtDpHGBaNJ9OCDJaVh2tIaWWUnGfuXfKf1JCBaIarak3FkVAvEeA==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", - "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", - "dev": true - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-spinners": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", - "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", - "dev": true - }, - "cli-width": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", - "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", - "dev": true - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", - "dev": true, - "requires": { - "mime-db": ">= 1.43.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "connect-history-api-fallback": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", - "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "content-disposition": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", - "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", - "dev": true, - "requires": { - "safe-buffer": "5.2.1" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "dev": true - }, - "copy-anything": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", - "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", - "dev": true, - "requires": { - "is-what": "^3.14.1" - } - }, - "copy-webpack-plugin": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", - "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", - "dev": true, - "requires": { - "fast-glob": "^3.2.11", - "glob-parent": "^6.0.1", - "globby": "^13.1.1", - "normalize-path": "^3.0.0", - "schema-utils": "^4.0.0", - "serialize-javascript": "^6.0.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "core-js-compat": { - "version": "3.25.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.5.tgz", - "integrity": "sha512-ovcyhs2DEBUIE0MGEKHP4olCUW/XYte3Vroyxuh38rD1wAO4dHohsovUC4eAOuzFxE6b+RXvBU3UZ9o0YhUTkA==", - "dev": true, - "requires": { - "browserslist": "^4.21.4" - } - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - } - }, - "critters": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.16.tgz", - "integrity": "sha512-JwjgmO6i3y6RWtLYmXwO5jMd+maZt8Tnfu7VVISmEWyQqfLpB8soBswf8/2bu6SBXxtKA68Al3c+qIG1ApT68A==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "css-select": "^4.2.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "postcss": "^8.3.7", - "pretty-bytes": "^5.3.0" - }, - "dependencies": { - "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, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "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, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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 - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "css-blank-pseudo": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz", - "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "css-has-pseudo": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz", - "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "css-loader": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz", - "integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==", - "dev": true, - "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.7", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.5" - } - }, - "css-prefers-color-scheme": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz", - "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==", - "dev": true, - "requires": {} - }, - "css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "dev": true, - "requires": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - } - }, - "css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true - }, - "cssdb": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.0.2.tgz", - "integrity": "sha512-Vm4b6P/PifADu0a76H0DKRNVWq3Rq9xa/Nx6oEMUBJlwTUuZoZ3dkZxo8Gob3UEL53Cq+Ma1GBgISed6XEBs3w==", - "dev": true - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", - "dev": true - }, - "date-format": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", - "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "default-gateway": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", - "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", - "dev": true, - "requires": { - "execa": "^5.0.0" - } - }, - "defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true - }, - "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "dependency-graph": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", - "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", - "dev": true - }, - "destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, - "di": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", - "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", - "dev": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "dns-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", - "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==", - "dev": true - }, - "dns-packet": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.4.0.tgz", - "integrity": "sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==", - "dev": true, - "requires": { - "@leichtgewicht/ip-codec": "^2.0.1" - } - }, - "dom-serialize": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", - "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", - "dev": true, - "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } - }, - "dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", - "dev": true, - "requires": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - } - }, - "domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true - }, - "domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "dev": true, - "requires": { - "domelementtype": "^2.2.0" - } - }, - "domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "dev": true, - "requires": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "dev": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "optional": true, - "requires": { - "iconv-lite": "^0.6.2" - }, - "dependencies": { - "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==", - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "engine.io": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", - "integrity": "sha512-4KzwW3F3bk+KlzSOY57fj/Jx6LyRQ1nbcyIadehl+AnXjKT7gDO0ORdRi/84ixvMKTym6ZKuxvbzN62HDDU1Lg==", - "dev": true, - "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "dev": true, - "requires": {} - } - } - }, - "engine.io-client": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.3.tgz", - "integrity": "sha512-aXPtgF1JS3RuuKcpSrBtimSjYvrbhKW9froICH4s0F3XQWLxsKNxqzG39nnvQZQnva4CMvUK63T7shevxRyYHw==", - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3", - "xmlhttprequest-ssl": "~2.0.0" - }, - "dependencies": { - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "requires": {} - } - } - }, - "engine.io-parser": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz", - "integrity": "sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==" - }, - "enhanced-resolve": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz", - "integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "ent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", - "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", - "dev": true - }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "dev": true - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true - }, - "errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "optional": true, - "requires": { - "prr": "~1.0.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true - }, - "esbuild": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.5.tgz", - "integrity": "sha512-VSf6S1QVqvxfIsSKb3UKr3VhUCis7wgDbtF4Vd9z84UJr05/Sp2fRKmzC+CSPG/dNAPPJZ0BTBLTT1Fhd6N9Gg==", - "dev": true, - "optional": true, - "requires": { - "@esbuild/linux-loong64": "0.15.5", - "esbuild-android-64": "0.15.5", - "esbuild-android-arm64": "0.15.5", - "esbuild-darwin-64": "0.15.5", - "esbuild-darwin-arm64": "0.15.5", - "esbuild-freebsd-64": "0.15.5", - "esbuild-freebsd-arm64": "0.15.5", - "esbuild-linux-32": "0.15.5", - "esbuild-linux-64": "0.15.5", - "esbuild-linux-arm": "0.15.5", - "esbuild-linux-arm64": "0.15.5", - "esbuild-linux-mips64le": "0.15.5", - "esbuild-linux-ppc64le": "0.15.5", - "esbuild-linux-riscv64": "0.15.5", - "esbuild-linux-s390x": "0.15.5", - "esbuild-netbsd-64": "0.15.5", - "esbuild-openbsd-64": "0.15.5", - "esbuild-sunos-64": "0.15.5", - "esbuild-windows-32": "0.15.5", - "esbuild-windows-64": "0.15.5", - "esbuild-windows-arm64": "0.15.5" - } - }, - "esbuild-android-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.5.tgz", - "integrity": "sha512-dYPPkiGNskvZqmIK29OPxolyY3tp+c47+Fsc2WYSOVjEPWNCHNyqhtFqQadcXMJDQt8eN0NMDukbyQgFcHquXg==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.5.tgz", - "integrity": "sha512-YyEkaQl08ze3cBzI/4Cm1S+rVh8HMOpCdq8B78JLbNFHhzi4NixVN93xDrHZLztlocEYqi45rHHCgA8kZFidFg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.5.tgz", - "integrity": "sha512-Cr0iIqnWKx3ZTvDUAzG0H/u9dWjLE4c2gTtRLz4pqOBGjfjqdcZSfAObFzKTInLLSmD0ZV1I/mshhPoYSBMMCQ==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.5.tgz", - "integrity": "sha512-WIfQkocGtFrz7vCu44ypY5YmiFXpsxvz2xqwe688jFfSVCnUsCn2qkEVDo7gT8EpsLOz1J/OmqjExePL1dr1Kg==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.5.tgz", - "integrity": "sha512-M5/EfzV2RsMd/wqwR18CELcenZ8+fFxQAAEO7TJKDmP3knhWSbD72ILzrXFMMwshlPAS1ShCZ90jsxkm+8FlaA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.5.tgz", - "integrity": "sha512-2JQQ5Qs9J0440F/n/aUBNvY6lTo4XP/4lt1TwDfHuo0DY3w5++anw+jTjfouLzbJmFFiwmX7SmUhMnysocx96w==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.5.tgz", - "integrity": "sha512-gO9vNnIN0FTUGjvTFucIXtBSr1Woymmx/aHQtuU+2OllGU6YFLs99960UD4Dib1kFovVgs59MTXwpFdVoSMZoQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.5.tgz", - "integrity": "sha512-ne0GFdNLsm4veXbTnYAWjbx3shpNKZJUd6XpNbKNUZaNllDZfYQt0/zRqOg0sc7O8GQ+PjSMv9IpIEULXVTVmg==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.5.tgz", - "integrity": "sha512-wvAoHEN+gJ/22gnvhZnS/+2H14HyAxM07m59RSLn3iXrQsdS518jnEWRBnJz3fR6BJa+VUTo0NxYjGaNt7RA7Q==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.5.tgz", - "integrity": "sha512-7EgFyP2zjO065XTfdCxiXVEk+f83RQ1JsryN1X/VSX2li9rnHAt2swRbpoz5Vlrl6qjHrCmq5b6yxD13z6RheA==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.5.tgz", - "integrity": "sha512-KdnSkHxWrJ6Y40ABu+ipTZeRhFtc8dowGyFsZY5prsmMSr1ZTG9zQawguN4/tunJ0wy3+kD54GaGwdcpwWAvZQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.5.tgz", - "integrity": "sha512-QdRHGeZ2ykl5P0KRmfGBZIHmqcwIsUKWmmpZTOq573jRWwmpfRmS7xOhmDHBj9pxv+6qRMH8tLr2fe+ZKQvCYw==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.5.tgz", - "integrity": "sha512-p+WE6RX+jNILsf+exR29DwgV6B73khEQV0qWUbzxaycxawZ8NE0wA6HnnTxbiw5f4Gx9sJDUBemh9v49lKOORA==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.5.tgz", - "integrity": "sha512-J2ngOB4cNzmqLHh6TYMM/ips8aoZIuzxJnDdWutBw5482jGXiOzsPoEF4j2WJ2mGnm7FBCO4StGcwzOgic70JQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.5.tgz", - "integrity": "sha512-MmKUYGDizYjFia0Rwt8oOgmiFH7zaYlsoQ3tIOfPxOqLssAsEgG0MUdRDm5lliqjiuoog8LyDu9srQk5YwWF3w==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.5.tgz", - "integrity": "sha512-2mMFfkLk3oPWfopA9Plj4hyhqHNuGyp5KQyTT9Rc8hFd8wAn5ZrbJg+gNcLMo2yzf8Uiu0RT6G9B15YN9WQyMA==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.5.tgz", - "integrity": "sha512-2sIzhMUfLNoD+rdmV6AacilCHSxZIoGAU2oT7XmJ0lXcZWnCvCtObvO6D4puxX9YRE97GodciRGDLBaiC6x1SA==", - "dev": true, - "optional": true - }, - "esbuild-wasm": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.15.5.tgz", - "integrity": "sha512-lTJOEKekN/4JI/eOEq0wLcx53co2N6vaT/XjBz46D1tvIVoUEyM0o2K6txW6gEotf31szFD/J1PbxmnbkGlK9A==", - "dev": true - }, - "esbuild-windows-32": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.5.tgz", - "integrity": "sha512-e+duNED9UBop7Vnlap6XKedA/53lIi12xv2ebeNS4gFmu7aKyTrok7DPIZyU5w/ftHD4MUDs5PJUkQPP9xJRzg==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.5.tgz", - "integrity": "sha512-v+PjvNtSASHOjPDMIai9Yi+aP+Vwox+3WVdg2JB8N9aivJ7lyhp4NVU+J0MV2OkWFPnVO8AE/7xH+72ibUUEnw==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.5", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.5.tgz", - "integrity": "sha512-Yz8w/D8CUPYstvVQujByu6mlf48lKmXkq6bkeSZZxTA626efQOJb26aDGLzmFWx6eg/FwrXgt6SZs9V8Pwy/aA==", - "dev": true, - "optional": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "dev": true - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "eventemitter-asyncresource": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", - "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", - "dev": true - }, - "eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true - }, - "eventsource": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", - "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==" - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", - "dev": true, - "requires": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.1", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.5.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.2.0", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.7", - "qs": "6.11.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", - "dev": true - }, - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "faye-websocket": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", - "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "fetch-cookie": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.11.0.tgz", - "integrity": "sha512-BQm7iZLFhMWFy5CZ/162sAGjBfdNWb7a8LEqqnzsHFhxT/X/SVj/z2t2nu3aJvjlbQkrAlTUApplPRjWyH4mhA==", - "requires": { - "tough-cookie": "^2.3.3 || ^3.0.1 || ^4.0.0" - } - }, - "figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - } - } - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", - "dev": true - }, - "forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "dev": true - }, - "fraction.js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", - "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", - "dev": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "fs-monkey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", - "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", - "dev": true, - "requires": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.11", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^4.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true - }, - "handle-thing": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", - "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "hdr-histogram-js": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", - "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", - "dev": true, - "requires": { - "@assemblyscript/loader": "^0.10.1", - "base64-js": "^1.2.0", - "pako": "^1.0.3" - } - }, - "hdr-histogram-percentiles-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", - "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", - "dev": true - }, - "hosted-git-info": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.1.0.tgz", - "integrity": "sha512-Ek+QmMEqZF8XrbFdwoDjSbm7rT23pCgEMOJmz6GPk/s4yH//RQfNPArhIxbguNxROq/+5lNBwCDHMhA903Kx1Q==", - "dev": true, - "requires": { - "lru-cache": "^7.5.1" - } - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "html-entities": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz", - "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "dev": true, - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", - "dev": true - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "dev": true, - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "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==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "http-proxy-middleware": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", - "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", - "dev": true, - "requires": { - "@types/http-proxy": "^1.17.8", - "http-proxy": "^1.18.1", - "is-glob": "^4.0.1", - "is-plain-obj": "^3.0.0", - "micromatch": "^4.0.2" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true, - "requires": {} - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "ignore-walk": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-5.0.1.tgz", - "integrity": "sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==", - "dev": true, - "requires": { - "minimatch": "^5.0.1" - } - }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", - "dev": true, - "optional": true - }, - "immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-3.0.0.tgz", - "integrity": "sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw==", - "dev": true - }, - "inquirer": { - "version": "8.2.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", - "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^4.1.1", - "cli-cursor": "^3.1.0", - "cli-width": "^3.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.21", - "mute-stream": "0.0.8", - "ora": "^5.4.1", - "run-async": "^2.4.0", - "rxjs": "^7.5.5", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "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, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "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, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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 - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "ip": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", - "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", - "dev": true - }, - "ipaddr.js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", - "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-core-module": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", - "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true - }, - "is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "is-what": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", - "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", - "dev": true - }, - "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "requires": { - "is-docker": "^2.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true - }, - "isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "requires": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "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 - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jasmine-core": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.1.1.tgz", - "integrity": "sha512-lmUfT5XcK9KKvt3lLYzn93hc4MGzlUBowExFVgzbSW0ZCrdeyS574dfsyfRhxbg81Wj4gk+RxUiTnj7KBfDA1g==", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "dependencies": { - "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 - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true - }, - "jsonc-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz", - "integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true - }, - "karma": { - "version": "6.3.20", - "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.20.tgz", - "integrity": "sha512-HRNQhMuKOwKpjYlWiJP0DUrJOh+QjaI/DTaD8b9rEm4Il3tJ8MijutVZH4ts10LuUFst/CedwTS6vieCN8yTSw==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", - "dev": true, - "requires": { - "rimraf": "^3.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - } - } - }, - "karma-chrome-launcher": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", - "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", - "dev": true, - "requires": { - "which": "^1.2.1" - } - }, - "karma-coverage": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.0.tgz", - "integrity": "sha512-gPVdoZBNDZ08UCzdMHHhEImKrw1+PAOQOIiffv1YsvxFhBjqvo/SVXNk4tqn1SYqX0BJZT6S/59zgxiBe+9OuA==", - "dev": true, - "requires": { - "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" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "karma-jasmine": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.0.1.tgz", - "integrity": "sha512-FkL1Kk+JAKmim8VWU8RXKZBpl0lLI7J8LijM0/q7oP7emfB6QMZV1Az+JgqGKSLpF0tYaav+KUVFQroZUxQTHA==", - "dev": true, - "requires": { - "jasmine-core": "^4.1.0" - } - }, - "karma-jasmine-html-reporter": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-1.7.0.tgz", - "integrity": "sha512-pzum1TL7j90DTE86eFt48/s12hqwQuiD+e5aXx2Dc9wDEn2LfGq6RoAxEZZjFiN0RDSCOnosEKRZWxbQ+iMpQQ==", - "dev": true, - "requires": {} - }, - "karma-source-map-support": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", - "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", - "dev": true, - "requires": { - "source-map-support": "^0.5.5" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "klona": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.5.tgz", - "integrity": "sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==", - "dev": true - }, - "less": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", - "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", - "dev": true, - "requires": { - "copy-anything": "^2.0.1", - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "make-dir": "^2.1.0", - "mime": "^1.4.1", - "needle": "^3.1.0", - "parse-node-version": "^1.0.1", - "source-map": "~0.6.0", - "tslib": "^2.3.0" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "optional": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true, - "optional": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "optional": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "optional": true - } - } - }, - "less-loader": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.0.0.tgz", - "integrity": "sha512-9+LOWWjuoectIEx3zrfN83NAGxSUB5pWEabbbidVQVgZhN+wN68pOvuyirVlH1IK4VT1f3TmlyvAnCXh8O5KEw==", - "dev": true, - "requires": { - "klona": "^2.0.4" - } - }, - "license-webpack-plugin": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", - "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", - "dev": true, - "requires": { - "webpack-sources": "^3.0.0" - } - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "loader-runner": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", - "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true - }, - "loader-utils": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.0.tgz", - "integrity": "sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "dependencies": { - "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, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "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, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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 - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "log4js": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.7.0.tgz", - "integrity": "sha512-KA0W9ffgNBLDj6fZCq/lRbgR6ABAodRIDHrZnS48vOtfKa4PzWImb0Md1lmGCdO3n3sbCm/n1/WmrNlZ8kCI3Q==", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "flatted": "^3.2.7", - "rfdc": "^1.3.0", - "streamroller": "^3.1.3" - } - }, - "lru-cache": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.0.tgz", - "integrity": "sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==", - "dev": true - }, - "magic-string": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.1.tgz", - "integrity": "sha512-ndThHmvgtieXe8J/VGPjG+Apu7v7ItcD5mhEIvOscWjPF/ccOiLxHaSuCAS2G+3x4GKsAbT8u7zdyamupui8Tg==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "make-fetch-happen": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", - "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", - "dev": true, - "requires": { - "agentkeepalive": "^4.1.3", - "cacache": "^15.2.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^6.0.0", - "minipass": "^3.1.3", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^1.3.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.2", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^6.0.0", - "ssri": "^8.0.0" - }, - "dependencies": { - "@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "dev": true, - "requires": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "dev": true, - "requires": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "dev": true, - "requires": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "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, - "requires": { - "yallist": "^4.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ssri": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", - "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - } - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "dev": true - }, - "memfs": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.7.tgz", - "integrity": "sha512-ygaiUSNalBX85388uskeCyhSAoOSgzBbtVCr9jA2RROssFL9Q19/ZXFqS+2Th2sr1ewNIWgFdLzLC3Yl1Zv+lw==", - "dev": true, - "requires": { - "fs-monkey": "^1.0.3" - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", - "dev": true - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz", - "integrity": "sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg==", - "dev": true, - "requires": { - "schema-utils": "^4.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - }, - "minipass": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.4.tgz", - "integrity": "sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-fetch": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", - "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", - "dev": true, - "requires": { - "encoding": "^0.1.12", - "minipass": "^3.1.0", - "minipass-sized": "^1.0.3", - "minizlib": "^2.0.0" - } - }, - "minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-json-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", - "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", - "dev": true, - "requires": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - } - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "multicast-dns": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", - "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", - "dev": true, - "requires": { - "dns-packet": "^5.2.2", - "thunky": "^1.0.2" - } - }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true - }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true - }, - "needle": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz", - "integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==", - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.6.3", - "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nice-napi": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", - "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", - "dev": true, - "optional": true, - "requires": { - "node-addon-api": "^3.0.0", - "node-gyp-build": "^4.2.2" - } - }, - "node-addon-api": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", - "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", - "dev": true, - "optional": true - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "node-gyp": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", - "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^9.1.0", - "nopt": "^5.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", - "dev": true, - "optional": true - }, - "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", - "dev": true - }, - "nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.1.tgz", - "integrity": "sha512-EBk5QKKuocMJhB3BILuKhmaPjI8vNRSpIfO9woLC6NyHVkKKdVEdAO1mrT0ZfxNR1lKwCcTkuZfmGIFdizZ8Pg==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true - }, - "npm-bundled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.2.tgz", - "integrity": "sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-install-checks": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-5.0.0.tgz", - "integrity": "sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==", - "dev": true, - "requires": { - "semver": "^7.1.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, - "npm-package-arg": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-9.0.2.tgz", - "integrity": "sha512-v/miORuX8cndiOheW8p2moNuPJ7QhcFh9WGlTorruG8hXSA23vMTEp5hTCmDxic0nD8KHhj/NQgFuySD3GYY3g==", - "dev": true, - "requires": { - "hosted-git-info": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^4.0.0" - } - }, - "npm-packlist": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-5.1.3.tgz", - "integrity": "sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==", - "dev": true, - "requires": { - "glob": "^8.0.1", - "ignore-walk": "^5.0.1", - "npm-bundled": "^2.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-bundled": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-2.0.1.tgz", - "integrity": "sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^2.0.0" - } - }, - "npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true - } - } - }, - "npm-pick-manifest": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-7.0.1.tgz", - "integrity": "sha512-IA8+tuv8KujbsbLQvselW2XQgmXWS47t3CB0ZrzsRZ82DbDfkcFunOaPm4X7qNuhMfq+FmV7hQT4iFVpHqV7mg==", - "dev": true, - "requires": { - "npm-install-checks": "^5.0.0", - "npm-normalize-package-bin": "^1.0.1", - "npm-package-arg": "^9.0.0", - "semver": "^7.3.5" - } - }, - "npm-registry-fetch": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-13.3.1.tgz", - "integrity": "sha512-eukJPi++DKRTjSBRcDZSDDsGqRK3ehbxfFUcgaRd0Yp6kRwOwh2WVn0r+8rMB4nnuzvAk6rQVzl6K5CkYOmnvw==", - "dev": true, - "requires": { - "make-fetch-happen": "^10.0.6", - "minipass": "^3.1.6", - "minipass-fetch": "^2.0.3", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^9.0.1", - "proc-log": "^2.0.0" - }, - "dependencies": { - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "requires": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - } - }, - "minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "requires": { - "encoding": "^0.1.13", - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - } - }, - "socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - } - } - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, - "nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "dev": true, - "requires": { - "boolbase": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true - }, - "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", - "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", - "dev": true, - "requires": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - } - }, - "ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "requires": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "dependencies": { - "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, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "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, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - }, - "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 - }, - "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, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "requires": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "dependencies": { - "retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true - } - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pacote": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-13.3.0.tgz", - "integrity": "sha512-auhJAUlfC2TALo6I0s1vFoPvVFgWGx+uz/PnIojTTgkGwlK3Np8sGJ0ghfFhiuzJXTZoTycMLk8uLskdntPbDw==", - "dev": true, - "requires": { - "@npmcli/git": "^3.0.0", - "@npmcli/installed-package-contents": "^1.0.7", - "@npmcli/promise-spawn": "^3.0.0", - "@npmcli/run-script": "^3.0.1", - "cacache": "^16.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "infer-owner": "^1.0.4", - "minipass": "^3.1.6", - "mkdirp": "^1.0.4", - "npm-package-arg": "^9.0.0", - "npm-packlist": "^5.0.0", - "npm-pick-manifest": "^7.0.0", - "npm-registry-fetch": "^13.0.1", - "proc-log": "^2.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^5.0.0", - "read-package-json-fast": "^2.0.3", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11" - } - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse-node-version": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", - "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", - "dev": true - }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, - "parse5-html-rewriting-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-6.0.1.tgz", - "integrity": "sha512-vwLQzynJVEfUlURxgnf51yAJDQTtVpNyGD8tKi2Za7m+akukNHxCcUQMAa/mUGLhCeicFdpy7Tlvj8ZNKadprg==", - "dev": true, - "requires": { - "parse5": "^6.0.1", - "parse5-sax-parser": "^6.0.1" - } - }, - "parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parse5-sax-parser": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-6.0.1.tgz", - "integrity": "sha512-kXX+5S81lgESA0LsDuGjAlBybImAChYRMT+/uKCEXFBFOeEhS52qUCydGhU3qLRD8D9DVjaUo821WK7DM4iCeg==", - "dev": true, - "requires": { - "parse5": "^6.0.1" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true - }, - "piscina": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/piscina/-/piscina-3.2.0.tgz", - "integrity": "sha512-yn/jMdHRw+q2ZJhFhyqsmANcbF6V2QwmD84c6xRau+QpQOmtrBCoRGdvTfeuFDYXB5W2m6MfLkjkvQa9lUSmIA==", - "dev": true, - "requires": { - "eventemitter-asyncresource": "^1.0.0", - "hdr-histogram-js": "^2.0.1", - "hdr-histogram-percentiles-obj": "^3.0.0", - "nice-napi": "^1.0.2" - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", - "dev": true, - "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - } - }, - "postcss-attribute-case-insensitive": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz", - "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-clamp": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz", - "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-functional-notation": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz", - "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-hex-alpha": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz", - "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-color-rebeccapurple": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz", - "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-media": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz", - "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-properties": { - "version": "12.1.9", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.9.tgz", - "integrity": "sha512-/E7PRvK8DAVljBbeWrcEQJPG72jaImxF3vvCNFwv9cC8CzigVoNIpeyfnJzphnN3Fd8/auBf5wvkw6W9MfmTyg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-custom-selectors": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz", - "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-dir-pseudo-class": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz", - "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-double-position-gradients": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz", - "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-env-function": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz", - "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-focus-visible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz", - "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-focus-within": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz", - "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.9" - } - }, - "postcss-font-variant": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz", - "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==", - "dev": true, - "requires": {} - }, - "postcss-gap-properties": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz", - "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==", - "dev": true, - "requires": {} - }, - "postcss-image-set-function": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz", - "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-import": { - "version": "15.0.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.0.0.tgz", - "integrity": "sha512-Y20shPQ07RitgBGv2zvkEAu9bqvrD77C9axhj/aA1BQj4czape2MdClCExvB27EwYEJdGgKZBpKanb0t1rK2Kg==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - } - }, - "postcss-initial": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz", - "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==", - "dev": true, - "requires": {} - }, - "postcss-lab-function": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz", - "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==", - "dev": true, - "requires": { - "@csstools/postcss-progressive-custom-properties": "^1.1.0", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-loader": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.0.1.tgz", - "integrity": "sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.7" - } - }, - "postcss-logical": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz", - "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==", - "dev": true, - "requires": {} - }, - "postcss-media-minmax": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz", - "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==", - "dev": true, - "requires": {} - }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, - "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.4" - } - }, - "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", - "dev": true, - "requires": { - "icss-utils": "^5.0.0" - } - }, - "postcss-nesting": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", - "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", - "dev": true, - "requires": { - "@csstools/selector-specificity": "^2.0.0", - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-opacity-percentage": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz", - "integrity": "sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==", - "dev": true - }, - "postcss-overflow-shorthand": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz", - "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-page-break": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz", - "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==", - "dev": true, - "requires": {} - }, - "postcss-place": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz", - "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==", - "dev": true, - "requires": { - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-preset-env": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.0.tgz", - "integrity": "sha512-leqiqLOellpLKfbHkD06E04P6d9ZQ24mat6hu4NSqun7WG0UhspHR5Myiv/510qouCjoo4+YJtNOqg5xHaFnCA==", - "dev": true, - "requires": { - "@csstools/postcss-cascade-layers": "^1.0.5", - "@csstools/postcss-color-function": "^1.1.1", - "@csstools/postcss-font-format-keywords": "^1.0.1", - "@csstools/postcss-hwb-function": "^1.0.2", - "@csstools/postcss-ic-unit": "^1.0.1", - "@csstools/postcss-is-pseudo-class": "^2.0.7", - "@csstools/postcss-nested-calc": "^1.0.0", - "@csstools/postcss-normalize-display-values": "^1.0.1", - "@csstools/postcss-oklab-function": "^1.1.1", - "@csstools/postcss-progressive-custom-properties": "^1.3.0", - "@csstools/postcss-stepped-value-functions": "^1.0.1", - "@csstools/postcss-text-decoration-shorthand": "^1.0.0", - "@csstools/postcss-trigonometric-functions": "^1.0.2", - "@csstools/postcss-unset-value": "^1.0.2", - "autoprefixer": "^10.4.8", - "browserslist": "^4.21.3", - "css-blank-pseudo": "^3.0.3", - "css-has-pseudo": "^3.0.4", - "css-prefers-color-scheme": "^6.0.3", - "cssdb": "^7.0.0", - "postcss-attribute-case-insensitive": "^5.0.2", - "postcss-clamp": "^4.1.0", - "postcss-color-functional-notation": "^4.2.4", - "postcss-color-hex-alpha": "^8.0.4", - "postcss-color-rebeccapurple": "^7.1.1", - "postcss-custom-media": "^8.0.2", - "postcss-custom-properties": "^12.1.8", - "postcss-custom-selectors": "^6.0.3", - "postcss-dir-pseudo-class": "^6.0.5", - "postcss-double-position-gradients": "^3.1.2", - "postcss-env-function": "^4.0.6", - "postcss-focus-visible": "^6.0.4", - "postcss-focus-within": "^5.0.4", - "postcss-font-variant": "^5.0.0", - "postcss-gap-properties": "^3.0.5", - "postcss-image-set-function": "^4.0.7", - "postcss-initial": "^4.0.1", - "postcss-lab-function": "^4.2.1", - "postcss-logical": "^5.0.4", - "postcss-media-minmax": "^5.0.0", - "postcss-nesting": "^10.1.10", - "postcss-opacity-percentage": "^1.1.2", - "postcss-overflow-shorthand": "^3.0.4", - "postcss-page-break": "^3.0.4", - "postcss-place": "^7.0.5", - "postcss-pseudo-class-any-link": "^7.1.6", - "postcss-replace-overflow-wrap": "^4.0.0", - "postcss-selector-not": "^6.0.1", - "postcss-value-parser": "^4.2.0" - } - }, - "postcss-pseudo-class-any-link": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz", - "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-replace-overflow-wrap": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz", - "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==", - "dev": true, - "requires": {} - }, - "postcss-selector-not": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz", - "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==", - "dev": true, - "requires": { - "postcss-selector-parser": "^6.0.10" - } - }, - "postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true - }, - "pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true - }, - "primeicons": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz", - "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA==" - }, - "primeng": { - "version": "14.1.2", - "resolved": "https://registry.npmjs.org/primeng/-/primeng-14.1.2.tgz", - "integrity": "sha512-iLMeORiLD46SNAotxCwRXoaRMXLs3ZbFzyePrPSNAFQbKEbsLfpUvsAUAatb/TA0jd8TnXgdCjZ07ee4664XVQ==", - "requires": { - "tslib": "^2.3.0" - } - }, - "proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true - }, - "promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "requires": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - } - }, - "proxy-addr": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", - "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", - "dev": true, - "requires": { - "forwarded": "0.2.0", - "ipaddr.js": "1.9.1" - }, - "dependencies": { - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "dev": true - } - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", - "dev": true, - "optional": true - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qjobs": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", - "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "dev": true, - "requires": { - "side-channel": "^1.0.4" - } - }, - "querystringify": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dev": true, - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "requires": { - "pify": "^2.3.0" - } - }, - "read-package-json": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-5.0.2.tgz", - "integrity": "sha512-BSzugrt4kQ/Z0krro8zhTwV1Kd79ue25IhNN/VtHFy1mG/6Tluyi+msc0UpwaoQzxSHa28mntAjIZY6kEgfR9Q==", - "dev": true, - "requires": { - "glob": "^8.0.1", - "json-parse-even-better-errors": "^2.3.1", - "normalize-package-data": "^4.0.0", - "npm-normalize-package-bin": "^2.0.0" - }, - "dependencies": { - "npm-normalize-package-bin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-2.0.0.tgz", - "integrity": "sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==", - "dev": true - } - } - }, - "read-package-json-fast": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-2.0.3.tgz", - "integrity": "sha512-W/BKtbL+dUjTuRL2vziuYhp76s5HZ9qQhd/dKfWIZveD0O40453QNyZhC0e63lqZrAQ4jiOapVoeJ7JrszenQQ==", - "dev": true, - "requires": { - "json-parse-even-better-errors": "^2.3.0", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", - "dev": true - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "regenerator-transform": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", - "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-parser": { - "version": "2.2.11", - "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", - "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", - "dev": true - }, - "regexpu-core": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.1.tgz", - "integrity": "sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.0.0" - } - }, - "regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" - }, - "resolve": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", - "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, - "requires": { - "is-core-module": "^2.8.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve-url-loader": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", - "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", - "dev": true, - "requires": { - "adjust-sourcemap-loader": "^4.0.0", - "convert-source-map": "^1.7.0", - "loader-utils": "^2.0.0", - "postcss": "^8.2.14", - "source-map": "0.6.1" - }, - "dependencies": { - "loader-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz", - "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.5.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", - "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "devOptional": true - }, - "sass": { - "version": "1.54.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.4.tgz", - "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==", - "dev": true, - "requires": { - "chokidar": ">=3.0.0 <4.0.0", - "immutable": "^4.0.0", - "source-map-js": ">=0.6.2 <2.0.0" - } - }, - "sass-loader": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.0.2.tgz", - "integrity": "sha512-BbiqbVmbfJaWVeOOAu2o7DhYWtcNmTfvroVgFXa6k2hHheMxNAeDHLNoDy/Q5aoaVlz0LH+MbMktKwm9vN/j8Q==", - "dev": true, - "requires": { - "klona": "^2.0.4", - "neo-async": "^2.6.2" - } - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "dev": true - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - } - } - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", - "dev": true - }, - "selfsigned": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", - "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", - "dev": true, - "requires": { - "node-forge": "^1" - } - }, - "semver": { - "version": "7.3.7", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", - "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "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, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - } - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "dev": true - } - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - } - }, - "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 - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "dev": true - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", - "dev": true - }, - "smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true - }, - "socket.io": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.3.tgz", - "integrity": "sha512-zdpnnKU+H6mOp7nYRXH4GNv1ux6HL6+lHL8g7Ds7Lj8CkdK1jJK/dlwsKDculbyOHifcJ0Pr/yeXnZQ5GeFrcg==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.2.0", - "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.2.0" - } - }, - "socket.io-adapter": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.4.0.tgz", - "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==", - "dev": true - }, - "socket.io-client": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.3.tgz", - "integrity": "sha512-I/hqDYpQ6JKwtJOf5ikM+Qz+YujZPMEl6qBLhxiP0nX+TfXKhW4KZZG8lamrD6Y5ngjmYHreESVasVCgi5Kl3A==", - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.2", - "engine.io-client": "~6.2.3", - "socket.io-parser": "~4.2.0" - } - }, - "socket.io-parser": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz", - "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==", - "requires": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1" - } - }, - "sockjs": { - "version": "0.3.24", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", - "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", - "dev": true, - "requires": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" - } - }, - "socks": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", - "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", - "dev": true, - "requires": { - "ip": "^2.0.0", - "smart-buffer": "^4.2.0" - } - }, - "socks-proxy-agent": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", - "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", - "dev": true, - "requires": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - } - }, - "source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true - }, - "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true - }, - "source-map-loader": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.0.tgz", - "integrity": "sha512-i3KVgM3+QPAHNbGavK+VBq03YoJl24m9JWNbLgsjTj8aJzXG9M61bantBTNBt7CNwY2FYf+RJRYJ3pzalKjIrw==", - "dev": true, - "requires": { - "abab": "^2.0.6", - "iconv-lite": "^0.6.3", - "source-map-js": "^1.0.2" - }, - "dependencies": { - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - } - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true - }, - "spdy": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", - "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "handle-thing": "^2.0.0", - "http-deceiver": "^1.2.7", - "select-hose": "^2.0.0", - "spdy-transport": "^3.0.0" - } - }, - "spdy-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", - "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", - "dev": true, - "requires": { - "debug": "^4.1.0", - "detect-node": "^2.0.4", - "hpack.js": "^2.1.6", - "obuf": "^1.1.2", - "readable-stream": "^3.0.6", - "wbuf": "^1.7.3" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "requires": { - "minipass": "^3.1.1" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", - "dev": true - }, - "streamroller": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.3.tgz", - "integrity": "sha512-CphIJyFx2SALGHeINanjFRKQ4l7x2c+rXYJ4BMq0gd+ZK0gi4VT8b+eHe2wi58x4UayBAKx4xtHpXT/ea1cz8w==", - "dev": true, - "requires": { - "date-format": "^4.0.14", - "debug": "^4.3.4", - "fs-extra": "^8.1.0" - } - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "stylus": { - "version": "0.59.0", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.59.0.tgz", - "integrity": "sha512-lQ9w/XIOH5ZHVNuNbWW8D822r+/wBSO/d6XvtyHLF7LW4KaCIDeVbvn5DF8fGCJAUCwVhVi/h6J0NUcnylUEjg==", - "dev": true, - "requires": { - "@adobe/css-tools": "^4.0.1", - "debug": "^4.3.2", - "glob": "^7.1.6", - "sax": "~1.2.4", - "source-map": "^0.7.3" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "stylus-loader": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-7.0.0.tgz", - "integrity": "sha512-WTbtLrNfOfLgzTaR9Lj/BPhQroKk/LC1hfTXSUbrxmxgfUo3Y3LpmKRVA2R1XbjvTAvOfaian9vOyfv1z99E+A==", - "dev": true, - "requires": { - "fast-glob": "^3.2.11", - "klona": "^2.0.5", - "normalize-path": "^3.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "symbol-observable": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", - "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", - "dev": true - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - }, - "terser": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", - "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", - "dev": true, - "requires": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.14", - "jest-worker": "^27.4.5", - "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "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 - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "thunky": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", - "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "dev": true - }, - "tough-cookie": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz", - "integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==", - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" - }, - "dependencies": { - "universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==" - } - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true - }, - "tslib": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", - "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typed-assert": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", - "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", - "dev": true - }, - "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.32", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.32.tgz", - "integrity": "sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", - "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "dev": true - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "dev": true, - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "requires": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", - "dev": true - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz", - "integrity": "sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==", - "dev": true, - "requires": { - "builtins": "^5.0.0" - } - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true - }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", - "dev": true - }, - "watchpack": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", - "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", - "dev": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "webpack": { - "version": "5.74.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz", - "integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.7.6", - "browserslist": "^4.14.5", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.2.0", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", - "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.4.0", - "webpack-sources": "^3.2.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, - "requires": {} - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - } - } - }, - "webpack-dev-middleware": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", - "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", - "dev": true, - "requires": { - "colorette": "^2.0.10", - "memfs": "^3.4.3", - "mime-types": "^2.1.31", - "range-parser": "^1.2.1", - "schema-utils": "^4.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - } - } - }, - "webpack-dev-server": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.11.0.tgz", - "integrity": "sha512-L5S4Q2zT57SK7tazgzjMiSMBdsw+rGYIX27MgPgx7LDhWO0lViPrHKoLS7jo5In06PWYAhlYu3PbyoC6yAThbw==", - "dev": true, - "requires": { - "@types/bonjour": "^3.5.9", - "@types/connect-history-api-fallback": "^1.3.5", - "@types/express": "^4.17.13", - "@types/serve-index": "^1.9.1", - "@types/serve-static": "^1.13.10", - "@types/sockjs": "^0.3.33", - "@types/ws": "^8.5.1", - "ansi-html-community": "^0.0.8", - "bonjour-service": "^1.0.11", - "chokidar": "^3.5.3", - "colorette": "^2.0.10", - "compression": "^1.7.4", - "connect-history-api-fallback": "^2.0.0", - "default-gateway": "^6.0.3", - "express": "^4.17.3", - "graceful-fs": "^4.2.6", - "html-entities": "^2.3.2", - "http-proxy-middleware": "^2.0.3", - "ipaddr.js": "^2.0.1", - "open": "^8.0.9", - "p-retry": "^4.5.0", - "rimraf": "^3.0.2", - "schema-utils": "^4.0.0", - "selfsigned": "^2.0.1", - "serve-index": "^1.9.1", - "sockjs": "^0.3.24", - "spdy": "^4.0.2", - "webpack-dev-middleware": "^5.3.1", - "ws": "^8.4.2" - }, - "dependencies": { - "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" - } - }, - "ws": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.9.0.tgz", - "integrity": "sha512-Ja7nszREasGaYUYCI2k4lCKIRTt+y7XuqVoHR44YpI49TtryyqbqvDMn5eqfW7e6HzTukDRIsXqzVHScqRcafg==", - "dev": true, - "requires": {} - } - } - }, - "webpack-merge": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", - "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "wildcard": "^2.0.0" - } - }, - "webpack-sources": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", - "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true - }, - "webpack-subresource-integrity": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", - "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", - "dev": true, - "requires": { - "typed-assert": "^1.0.8" - } - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "wildcard": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", - "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "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, - "requires": { - "color-convert": "^2.0.1" - } - }, - "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, - "requires": { - "color-name": "~1.1.4" - } - }, - "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 - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "requires": {} - }, - "xmlhttprequest-ssl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", - "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==" - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true - }, - "yargs": { - "version": "17.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", - "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.0.0" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - }, - "zone.js": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.11.8.tgz", - "integrity": "sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==", - "requires": { - "tslib": "^2.3.0" - } - } } } diff --git a/kdb-web/package.json b/kdb-web/package.json index 9a7aadca..e9366174 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -1,6 +1,6 @@ { "name": "kdb-web", - "version": "0.3.0", + "version": "1.0.0", "scripts": { "ng": "ng", "update-version": "ts-node-esm update-version.ts", @@ -10,35 +10,36 @@ "build": "ng build", "watch": "ng build --watch --configuration development", "test": "ng test", + "predocker-build": "npm run update-version", "docker-build": "export VERSION=$npm_package_version; ng build; docker build -t kdb-web/kdb-web:$VERSION .", "docker-build-dev": "export VERSION=$npm_package_version; ng build --configuration development; docker build -t kdb-web/kdb-web:$VERSION .", "docker-build-stage": "export VERSION=$npm_package_version; ng build --configuration staging; docker build -t kdb-web/kdb-web:$VERSION ." }, "private": true, "dependencies": { - "@angular/animations": "^14.0.0", - "@angular/common": "^14.0.0", - "@angular/compiler": "^14.0.0", - "@angular/core": "^14.0.0", - "@angular/forms": "^14.0.0", - "@angular/platform-browser": "^14.0.0", - "@angular/platform-browser-dynamic": "^14.0.0", - "@angular/router": "^14.0.0", + "@angular/animations": "^15.1.4", + "@angular/common": "^15.1.4", + "@angular/compiler": "^15.1.4", + "@angular/core": "^15.1.4", + "@angular/forms": "^15.1.4", + "@angular/platform-browser": "^15.1.4", + "@angular/platform-browser-dynamic": "^15.1.4", + "@angular/router": "^15.1.4", "@auth0/angular-jwt": "^5.1.0", "@microsoft/signalr": "^6.0.9", "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", "@types/socket.io-client": "^3.0.0", "primeicons": "^6.0.1", - "primeng": "^14.1.2", + "primeng": "^15.2.0", "rxjs": "~7.5.0", "socket.io-client": "^4.5.3", "zone.js": "~0.11.4" }, "devDependencies": { - "@angular-devkit/build-angular": "^14.0.0", - "@angular/cli": "~14.0.0", - "@angular/compiler-cli": "^14.0.0", + "@angular-devkit/build-angular": "^15.1.5", + "@angular/cli": "~15.1.5", + "@angular/compiler-cli": "^15.1.4", "@types/jasmine": "~4.0.0", "@types/node": "^18.11.9", "jasmine-core": "~4.1.0", @@ -48,6 +49,6 @@ "karma-jasmine": "~5.0.0", "karma-jasmine-html-reporter": "~1.7.0", "tslib": "^2.4.1", - "typescript": "~4.7.2" + "typescript": "~4.9.5" } -} +} \ No newline at end of file diff --git a/kdb-web/src/app/app-routing.module.ts b/kdb-web/src/app/app-routing.module.ts index 1a1c9c3b..1ae6ad4b 100644 --- a/kdb-web/src/app/app-routing.module.ts +++ b/kdb-web/src/app/app-routing.module.ts @@ -7,7 +7,7 @@ import { AuthGuard } from './modules/shared/guards/auth/auth.guard'; const routes: Routes = [ { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, { path: 'dashboard', loadChildren: () => import('./modules/view/dashboard/dashboard.module').then(m => m.DashboardModule), canActivate: [AuthGuard] }, - { path: 'server', loadChildren: () => import('./modules/view/server/server.module').then(m => m.ServerModule), canActivate: [AuthGuard] }, + { path: 'server/:serverId', loadChildren: () => import('./modules/view/server/server.module').then(m => m.ServerModule), canActivate: [AuthGuard] }, { path: 'change-password', loadChildren: () => import('./modules/view/change-password/change-password.module').then(m => m.ChangePasswordModule), canActivate: [AuthGuard] }, { path: 'user-settings', loadChildren: () => import('./modules/view/user-settings/user-settings.module').then(m => m.UserSettingsModule), canActivate: [AuthGuard] }, { path: 'auth', loadChildren: () => import('./modules/auth/auth.module').then(m => m.AuthModule) }, diff --git a/kdb-web/src/app/app.component.html b/kdb-web/src/app/app.component.html index a2dc5b50..8c0cfa4f 100644 --- a/kdb-web/src/app/app.component.html +++ b/kdb-web/src/app/app.component.html @@ -1,4 +1,5 @@
+ @@ -33,4 +34,4 @@ -
\ No newline at end of file + diff --git a/kdb-web/src/app/app.component.ts b/kdb-web/src/app/app.component.ts index 1a2cf35f..d6b87c69 100644 --- a/kdb-web/src/app/app.component.ts +++ b/kdb-web/src/app/app.component.ts @@ -1,51 +1,67 @@ -import { Component, OnInit } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; -import { PrimeNGConfig } from 'primeng/api'; -import { AuthService } from './services/auth/auth.service'; -import { SocketService } from './services/socket/socket.service'; -import { ThemeService } from './services/theme/theme.service'; +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; +import { PrimeNGConfig } from "primeng/api"; +import { AuthService } from "./services/auth/auth.service"; +import { SocketService } from "./services/socket/socket.service"; +import { ThemeService } from "./services/theme/theme.service"; +import { Subject } from "rxjs"; +import { Themes } from "./models/view/themes.enum"; +import { takeUntil } from "rxjs/operators"; @Component({ - selector: 'app-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: "app-root", + templateUrl: "./app.component.html", + styleUrls: ["./app.component.scss"] }) -export class AppComponent implements OnInit { +export class AppComponent implements OnInit, OnDestroy { - themeName!: string; - sidebarWidth!: string; + themeName: string = Themes.Default; + sidebarWidth: string = '175px'; isLoggedIn: boolean = false; + private unsubscriber = new Subject(); + constructor( private authService: AuthService, private themeService: ThemeService, private socket: SocketService, private translateService: TranslateService, - private config: PrimeNGConfig + private config: PrimeNGConfig, ) { - this.themeService.sidebarWidth$.subscribe(value => { + this.themeService.sidebarWidth$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.sidebarWidth = value; }); - this.themeService.themeName$.subscribe(value => { + this.themeService.themeName$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.themeName = value; }); - this.authService.isLoggedIn$.subscribe(value => { + this.authService.isLoggedIn$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { this.isLoggedIn = value; }); } ngOnInit(): void { - this.translateService.setDefaultLang('en'); + this.translateService.setDefaultLang("en"); this.themeService.loadTheme(); this.socket.startSocket(); } + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + loadLang(): void { let lang = localStorage.getItem(`default_lang`); if (!lang) { - lang = 'en'; + lang = "en"; this.setLang(lang); } this.translate(lang); @@ -57,7 +73,7 @@ export class AppComponent implements OnInit { translate(lang: string) { this.translateService.use(lang); - this.translateService.get('primeng').subscribe(res => this.config.setTranslation(res)); + this.translateService.get("primeng").subscribe(res => this.config.setTranslation(res)); } diff --git a/kdb-web/src/app/app.module.ts b/kdb-web/src/app/app.module.ts index 2753cf18..3e2b348b 100644 --- a/kdb-web/src/app/app.module.ts +++ b/kdb-web/src/app/app.module.ts @@ -1,4 +1,4 @@ -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpClientModule } from '@angular/common/http'; import { APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; @@ -47,7 +47,8 @@ import { SettingsService } from './services/settings/settings.service'; useFactory: HttpLoaderFactory, deps: [HttpClient] } - }) + }), + HttpClientModule ], providers: [ { diff --git a/kdb-web/src/app/components/footer/footer.component.html b/kdb-web/src/app/components/footer/footer.component.html index 240f8583..2b104231 100644 --- a/kdb-web/src/app/components/footer/footer.component.html +++ b/kdb-web/src/app/components/footer/footer.component.html @@ -1,26 +1,28 @@
-
-
+
+
{{'footer.frontend' | translate}}: - + {{frontendVersion.getVersionString()}} -
- +
+ | -
+
{{'footer.backend' | translate}}: - + {{backendVersion.getVersionString()}} -
- -
\ No newline at end of file + +
+ + | + +
+ diff --git a/kdb-web/src/app/components/footer/footer.component.ts b/kdb-web/src/app/components/footer/footer.component.ts index bb2fa2eb..ef02100c 100644 --- a/kdb-web/src/app/components/footer/footer.component.ts +++ b/kdb-web/src/app/components/footer/footer.component.ts @@ -1,10 +1,10 @@ -import { Component, OnInit } from '@angular/core'; -import { type } from 'os'; -import { catchError } from 'rxjs/operators'; -import { SoftwareVersion } from 'src/app/models/config/software-version'; -import { GuiService } from 'src/app/services/gui/gui.service'; -import { SettingsService } from 'src/app/services/settings/settings.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; +import { Component, OnInit } from "@angular/core"; +import { catchError } from "rxjs/operators"; +import { SoftwareVersion } from "src/app/models/config/software-version"; +import { GuiService } from "src/app/services/gui/gui.service"; +import { SettingsService } from "src/app/services/settings/settings.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { throwError } from "rxjs"; @Component({ selector: 'app-footer', @@ -14,33 +14,43 @@ import { SpinnerService } from 'src/app/services/spinner/spinner.service'; export class FooterComponent implements OnInit { - frontendVersion!: SoftwareVersion; - backendVersion!: SoftwareVersion; + public frontendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); + public backendVersion: SoftwareVersion = new SoftwareVersion("0", "0", "0"); + + public privacy: string = ""; + public imprint: string = ""; constructor( private settings: SettingsService, private guiService: GuiService, private spinnerService: SpinnerService - ) { } + ) {} ngOnInit(): void { this.frontendVersion = this.settings.getWebVersion() ?? new SoftwareVersion('0', '0', '0'); this.spinnerService.showSpinner(); this.guiService.getApiVersion() - .pipe(catchError(err => { + .pipe(catchError(error => { this.spinnerService.hideSpinner(); - throw err; + return throwError(() => error); })) .subscribe(version => { this.spinnerService.hideSpinner(); - const webVersion = new SoftwareVersion( + this.backendVersion = new SoftwareVersion( version.major, version.minor, version.micro ); - this.backendVersion = webVersion; }); } + public navigateToPrivacy(): void { + window.open(this.settings.getPrivacyURL(), "_blank"); + } + + public navigateToImprint(): void { + window.open(this.settings.getImprintURL(), "_blank"); + } + } diff --git a/kdb-web/src/app/components/header/header.component.ts b/kdb-web/src/app/components/header/header.component.ts index 441ceb58..ce80b5d9 100644 --- a/kdb-web/src/app/components/header/header.component.ts +++ b/kdb-web/src/app/components/header/header.component.ts @@ -1,17 +1,19 @@ -import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; -import { MenuItem, PrimeNGConfig } from 'primeng/api'; -import { catchError } from 'rxjs/operators'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { SettingsService } from 'src/app/services/settings/settings.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ThemeService } from 'src/app/services/theme/theme.service'; +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { LangChangeEvent, TranslateService } from "@ngx-translate/core"; +import { MenuItem, PrimeNGConfig } from "primeng/api"; +import { catchError } from "rxjs/operators"; +import { AuthService } from "src/app/services/auth/auth.service"; +import { SettingsService } from "src/app/services/settings/settings.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ThemeService } from "src/app/services/theme/theme.service"; +import { throwError } from "rxjs"; +import { SidebarService } from "../../services/sidebar/sidebar.service"; @Component({ - selector: 'app-header', - templateUrl: './header.component.html', - styleUrls: ['./header.component.scss'] + selector: "app-header", + templateUrl: "./header.component.html", + styleUrls: ["./header.component.scss"] }) export class HeaderComponent implements OnInit { langList: MenuItem[] = []; @@ -25,8 +27,10 @@ export class HeaderComponent implements OnInit { private spinnerService: SpinnerService, private settings: SettingsService, private translateService: TranslateService, - private config: PrimeNGConfig - ) { } + private config: PrimeNGConfig, + private sidebarService: SidebarService, + ) { + } ngOnInit(): void { this.initMenuLists(); @@ -37,17 +41,20 @@ export class HeaderComponent implements OnInit { } initUserMenuList(): void { + if (!this.authService.isLoggedIn$.value) { + return; + } this.spinnerService.showSpinner(); const mail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken()); - this.authService.getUserByEMail(mail ?? '') - .pipe(catchError(err => { + this.authService.getUserByEMail(mail ?? "") + .pipe(catchError(error => { this.spinnerService.hideSpinner(); this.authService.logout(); - throw err; + return throwError(() => error); })) .subscribe(user => { this.spinnerService.hideSpinner(); - + this.sidebarService.setMenu(true); this.userMenuList = [ { @@ -58,22 +65,22 @@ export class HeaderComponent implements OnInit { separator: true }, { - label: this.translateService.instant('header.change_password'), command: () => { + label: this.translateService.instant("header.change_password"), command: () => { this.changePassword(); }, - icon: 'pi pi-key' + icon: "pi pi-key" }, { - label: this.translateService.instant('header.settings'), command: () => { + label: this.translateService.instant("header.settings"), command: () => { this.userSettings(); }, - icon: 'pi pi-cog' + icon: "pi pi-cog" }, { - label: this.translateService.instant('header.logout'), command: () => { + label: this.translateService.instant("header.logout"), command: () => { this.logout(); }, - icon: 'pi pi-sign-out' + icon: "pi pi-sign-out" } ]; }); @@ -82,17 +89,17 @@ export class HeaderComponent implements OnInit { initMenuLists(): void { this.langList = [ { - label: 'English', command: () => { - this.translate('en'); - this.setLang('en'); - }, + label: "English", command: () => { + this.translate("en"); + this.setLang("en"); + } }, { - label: 'Deutsch', command: () => { - this.translate('de'); - this.setLang('de'); - }, - }, + label: "Deutsch", command: () => { + this.translate("de"); + this.setLang("de"); + } + } ]; this.initUserMenuList(); @@ -116,11 +123,11 @@ export class HeaderComponent implements OnInit { } changePassword(): void { - this.router.navigate(['/change-password']); + this.router.navigate(["/change-password"]); } userSettings(): void { - this.router.navigate(['/user-settings']); + this.router.navigate(["/user-settings"]); } logout(): void { @@ -129,7 +136,7 @@ export class HeaderComponent implements OnInit { translate(lang: string) { this.translateService.use(lang); - this.translateService.get('primeng').subscribe(res => this.config.setTranslation(res)); + this.translateService.get("primeng").subscribe(res => this.config.setTranslation(res)); } loadLang(): void { @@ -137,28 +144,26 @@ export class HeaderComponent implements OnInit { const mail = this.authService.getEMailFromDecodedToken(token); if (!mail) { - this.translate('en'); + this.translate("en"); return; } let lang = localStorage.getItem(`${mail}_lang`); if (!lang) { - lang = 'en'; + lang = "en"; this.setLang(lang); } this.translate(lang); } setLang(lang: string): void { - this.authService.isUserLoggedInAsync().then(result => { - if (!result) { - return; - } + if (!this.authService.isLoggedIn$.value) { + return; + } - const token = this.authService.getDecodedToken(); - const mail = this.authService.getEMailFromDecodedToken(token); - localStorage.setItem(`${mail}_lang`, lang); - }); + const token = this.authService.getDecodedToken(); + const mail = this.authService.getEMailFromDecodedToken(token); + localStorage.setItem(`${mail}_lang`, lang); } } diff --git a/kdb-web/src/app/components/sidebar/sidebar.component.ts b/kdb-web/src/app/components/sidebar/sidebar.component.ts index d43b42e5..82df2511 100644 --- a/kdb-web/src/app/components/sidebar/sidebar.component.ts +++ b/kdb-web/src/app/components/sidebar/sidebar.component.ts @@ -1,47 +1,32 @@ -import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; -import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; -import { MenuItem } from 'primeng/api'; -import { AuthRoles } from 'src/app/models/auth/auth-roles.enum'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { ServerService } from 'src/app/services/data/server.service'; -import { ThemeService } from 'src/app/services/theme/theme.service'; +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { TranslateService } from "@ngx-translate/core"; +import { MenuItem } from "primeng/api"; +import { AuthService } from "src/app/services/auth/auth.service"; +import { ThemeService } from "src/app/services/theme/theme.service"; +import { SidebarService } from "../../services/sidebar/sidebar.service"; +import { Subject } from "rxjs"; +import { takeUntil } from "rxjs/operators"; @Component({ - selector: 'app-sidebar', - templateUrl: './sidebar.component.html', - styleUrls: ['./sidebar.component.scss'] + selector: "app-sidebar", + templateUrl: "./sidebar.component.html", + styleUrls: ["./sidebar.component.scss"] }) -export class SidebarComponent implements OnInit { +export class SidebarComponent implements OnInit, OnDestroy { - isSidebarOpen: boolean = true; - menuItems!: MenuItem[]; - - private serverId!: number; + menuItems: MenuItem[]= []; + private unsubscriber = new Subject(); constructor( private authService: AuthService, private translateService: TranslateService, private themeService: ThemeService, - private route: ActivatedRoute, - private serverService: ServerService + private sidebar: SidebarService ) { - this.themeService.isSidebarOpen$.subscribe(value => { - this.isSidebarOpen = value; - this.setMenu(); - }); - - this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { - this.setMenu(); - }); - - this.serverService.server$.subscribe(server => { - if (!server) { - return; - } - - this.serverId = server.serverId; - this.setMenu(); + this.sidebar.menuItems$.pipe( + takeUntil(this.unsubscriber) + ).subscribe(value => { + this.menuItems = value; }); } @@ -49,44 +34,9 @@ export class SidebarComponent implements OnInit { this.themeService.loadMenu(); } - setMenu() { - this.authService.hasUserPermission(AuthRoles.Admin).then(hasPermission => { - this.menuItems = []; - this.menuItems = [ - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.dashboard') : '', icon: 'pi pi-th-large', routerLink: 'dashboard' } - ]; - - if (this.serverId) { - this.addServerMenu(); - } - - if (hasPermission) { - this.addAdminMenu(); - } - this.menuItems = this.menuItems.slice(); - }); - } - - addServerMenu() { - this.menuItems.push( - { - label: this.isSidebarOpen ? this.translateService.instant('sidebar.server') : '', icon: 'pi pi-server', items: [ - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.settings') : '', icon: 'pi pi-cog', routerLink: 'server/settings' }, - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.members') : '', icon: 'pi pi-users', routerLink: 'server/members' }, - ] - } - ); - } - - addAdminMenu() { - this.menuItems.push( - { - label: this.isSidebarOpen ? this.translateService.instant('sidebar.administration') : '', icon: 'pi pi-cog', items: [ - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.config') : '', icon: 'pi pi-cog', routerLink: '/admin/settings' }, - { label: this.isSidebarOpen ? this.translateService.instant('sidebar.auth_user_list') : '', icon: 'pi pi-user-edit', routerLink: '/admin/users' }, - ] - }, - ); + ngOnDestroy() { + this.unsubscriber.next(); + this.unsubscriber.complete(); } } diff --git a/kdb-web/src/app/components/spinner/spinner.component.html b/kdb-web/src/app/components/spinner/spinner.component.html index b4f52b87..658b9ba2 100644 --- a/kdb-web/src/app/components/spinner/spinner.component.html +++ b/kdb-web/src/app/components/spinner/spinner.component.html @@ -1,7 +1,7 @@ - +
-
\ No newline at end of file +
diff --git a/kdb-web/src/app/components/spinner/spinner.component.ts b/kdb-web/src/app/components/spinner/spinner.component.ts index 4753534c..4bae2cd0 100644 --- a/kdb-web/src/app/components/spinner/spinner.component.ts +++ b/kdb-web/src/app/components/spinner/spinner.component.ts @@ -8,9 +8,15 @@ import { SpinnerService } from 'src/app/services/spinner/spinner.service'; }) export class SpinnerComponent implements OnInit { + showSpinnerState: boolean = false; + constructor( public spinnerService: SpinnerService - ) { } + ) { + this.spinnerService.showSpinnerState$.subscribe(value => { + this.showSpinnerState = value; + }); + } ngOnInit(): void { } diff --git a/kdb-web/src/app/models/auth/auth-user.dto.ts b/kdb-web/src/app/models/auth/auth-user.dto.ts index 17604288..4b1e90e4 100644 --- a/kdb-web/src/app/models/auth/auth-user.dto.ts +++ b/kdb-web/src/app/models/auth/auth-user.dto.ts @@ -1,11 +1,27 @@ -import { AuthRoles } from "./auth-roles.enum"; +import {AuthRoles} from "./auth-roles.enum"; export interface AuthUserDTO { - id?: number; - firstName: string | null; - lastName: string | null; - email: string | null; - password: string | null; - isConfirmed?: boolean - authRole?: AuthRoles; -} \ No newline at end of file + id?: number; + firstName: string | null; + lastName: string | null; + email: string | null; + password: string | null; + isConfirmed?: boolean; + authRole?: AuthRoles; + users?: UserDTO[]; + createdAt?: string; + modifiedAt?: string; +} + + +export interface UserDTO { + id: number; + discordId: number; + xp: number; + server: number; + createdAt: string; + modifiedAt: string; + isTechnician: boolean; + isAdmin: boolean; + isModerator: boolean; +} diff --git a/kdb-web/src/app/models/auth/token.dto.ts b/kdb-web/src/app/models/auth/token.dto.ts index 10e8b7c4..69f452e6 100644 --- a/kdb-web/src/app/models/auth/token.dto.ts +++ b/kdb-web/src/app/models/auth/token.dto.ts @@ -1,4 +1,5 @@ export interface TokenDTO { token: string; refreshToken: string; -} \ No newline at end of file + firstLogin?: boolean; +} diff --git a/kdb-web/src/app/models/config/appsettings.ts b/kdb-web/src/app/models/config/appsettings.ts index de434a03..f3f5796b 100644 --- a/kdb-web/src/app/models/config/appsettings.ts +++ b/kdb-web/src/app/models/config/appsettings.ts @@ -3,6 +3,8 @@ import { Theme } from '../view/theme'; export interface Appsettings { ApiURL: string; + PrivacyURL: string; + ImprintURL: string; WebVersion: SoftwareVersion; Themes: Theme[]; -} \ No newline at end of file +} diff --git a/kdb-web/src/app/models/config/software-version.ts b/kdb-web/src/app/models/config/software-version.ts index 4025b2b7..8d7912de 100644 --- a/kdb-web/src/app/models/config/software-version.ts +++ b/kdb-web/src/app/models/config/software-version.ts @@ -1,19 +1,19 @@ export class SoftwareVersion { - Major: string; - Minor: string; - Micro: string; + Major: string; + Minor: string; + Micro: string; - constructor( - major: string, - minor: string, - micro: string - ) { - this.Major = major; - this.Minor = minor; - this.Micro = micro; - } + constructor( + major: string, + minor: string, + micro: string + ) { + this.Major = major; + this.Minor = minor; + this.Micro = micro; + } - getVersionString(): string { - return `${this.Major}.${this.Minor}.${this.Micro}`; - } -} \ No newline at end of file + getVersionString(): string { + return `${this.Major}.${this.Minor}.${this.Micro}`; + } +} diff --git a/kdb-web/src/app/models/data/auto_role.model.ts b/kdb-web/src/app/models/data/auto_role.model.ts new file mode 100644 index 00000000..2d9c35c5 --- /dev/null +++ b/kdb-web/src/app/models/data/auto_role.model.ts @@ -0,0 +1,36 @@ +import { Data } from "./data.model"; +import { Server, ServerFilter } from "./server.model"; + +export interface AutoRole extends Data { + id?: number; + channelId?: string; + channelName?: string; + messageId?: string; + server?: Server; + + autoRoleRuleCount?: number; + autoRoleRules?: AutoRoleRule[]; +} + +export interface AutoRoleFilter { + id?: number; + channelId?: string; + channelName?: string; + messageId?: string; + server?: ServerFilter; +} + +export interface AutoRoleRule extends Data { + id?: number; + emojiName?: string; + roleId?: string; + roleName?: string; + autoRole?: AutoRole; +} + +export interface AutoRoleRuleFilter { + id?: number; + emojiName?: string; + roleId?: string; + autoRole?: AutoRoleFilter; +} diff --git a/kdb-web/src/app/models/data/client.model.ts b/kdb-web/src/app/models/data/client.model.ts new file mode 100644 index 00000000..0ed0585f --- /dev/null +++ b/kdb-web/src/app/models/data/client.model.ts @@ -0,0 +1,16 @@ +import {Server} from "./server.model"; +import {Data} from "./data.model"; + +export interface Client extends Data { + + id?: number; + discordId?: string; + name?: string; + sentMessageCount?: number; + receivedMessageCount?: number; + deletedMessageCount?: number; + receivedCommandCount?: number; + movedUsersCount?: number; + server?: Server; + +} diff --git a/kdb-web/src/app/models/data/data.model.ts b/kdb-web/src/app/models/data/data.model.ts new file mode 100644 index 00000000..768d637f --- /dev/null +++ b/kdb-web/src/app/models/data/data.model.ts @@ -0,0 +1,17 @@ +export interface Data { + createdAt?: string; + modifiedAt?: string; +} + +export interface DataWithHistory { + createdAt?: string; + modifiedAt?: string; + history?: History[]; +} + +export interface History { + deleted?: boolean; + dateFrom?: string; + dateTo?: string; + [x: string | number | symbol]: unknown; +} diff --git a/kdb-web/src/app/models/data/discord.model.ts b/kdb-web/src/app/models/data/discord.model.ts new file mode 100644 index 00000000..680225ef --- /dev/null +++ b/kdb-web/src/app/models/data/discord.model.ts @@ -0,0 +1,31 @@ +export interface Guild { + id?: string; + name?: string; + + channels: Channel[]; + roles: Role[]; + emojis: Emoji[]; +} + +export interface Channel { + id?: string; + name?: string; + type?: ChannelType; +} + +export enum ChannelType { + category = "category", + text = "text", + voice = "voice" +} + +export interface Role { + id?: string; + name?: string; +} + +export interface Emoji { + id?: string; + name?: string; + url?: string; +} diff --git a/kdb-web/src/app/models/data/level.model.ts b/kdb-web/src/app/models/data/level.model.ts new file mode 100644 index 00000000..f747628f --- /dev/null +++ b/kdb-web/src/app/models/data/level.model.ts @@ -0,0 +1,17 @@ +import {Data} from "./data.model"; +import {Server, ServerFilter} from "./server.model"; + +export interface Level extends Data { + id?: number; + name?: string; + color?: string; + minXp?: number; + permissions?: string; + server?: Server; +} + +export interface LevelFilter { + id?: number; + name?: string; + server?: ServerFilter; +} diff --git a/kdb-web/src/app/models/data/server.model.ts b/kdb-web/src/app/models/data/server.model.ts new file mode 100644 index 00000000..cc160e68 --- /dev/null +++ b/kdb-web/src/app/models/data/server.model.ts @@ -0,0 +1,26 @@ +import {Data} from "./data.model"; +import {User} from "./user.model"; +import {Level} from "./level.model"; +import {Client} from "./client.model"; +import { AutoRole } from "./auto_role.model"; + +export interface Server extends Data { + id?: number; + discordId?: String; + name?: string; + iconURL?: string; + autoRoleCount?: number; + autoRoles?: AutoRole[]; + clientCount?: number; + clients?: Client[]; + levelCount?: number; + levels?: Level[]; + userCount?: number; + users?: User[]; +} + +export interface ServerFilter { + id?: number; + discordId?: String; + name?: String; +} diff --git a/kdb-web/src/app/models/data/user.model.ts b/kdb-web/src/app/models/data/user.model.ts new file mode 100644 index 00000000..671da870 --- /dev/null +++ b/kdb-web/src/app/models/data/user.model.ts @@ -0,0 +1,48 @@ +import { DataWithHistory } from "./data.model"; +import { Level, LevelFilter } from "./level.model"; +import { Server, ServerFilter } from "./server.model"; +import { UserJoinedServer } from "./user_joined_server.model"; +import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model"; +import { UserJoinedGameServer } from "./user_joined_game_server.model"; + +export interface User extends DataWithHistory { + id?: number; + discordId?: number; + name?: string; + xp?: number; + ontime?: number; + level?: Level; + server?: Server; + leftServer?: boolean; + + joinedServerCount?: number; + joinedServers?: UserJoinedServer[]; + + joinedVoiceChannelCount?: number; + joinedVoiceChannels?: UserJoinedVoiceChannel[]; + + userJoinedGameServerCount?: number; + userJoinedGameServers?: UserJoinedGameServer[]; + + // history?: UserHistory[]; +} + +export interface UserHistory extends History { + id?: number; + discordId?: number; + xp?: number; + level?: number; + server?: number; + leftServer?: boolean; +} + +export interface UserFilter { + id?: number; + discordId?: number; + name?: string; + xp?: number; + ontime?: number; + level?: LevelFilter; + server?: ServerFilter; + leftServer?: boolean; +} diff --git a/kdb-web/src/app/models/data/user_joined_game_server.model.ts b/kdb-web/src/app/models/data/user_joined_game_server.model.ts new file mode 100644 index 00000000..b8ce5e72 --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_game_server.model.ts @@ -0,0 +1,11 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedGameServer extends Data { + id: number; + gameServer: string; + user: User; + time: number; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/data/user_joined_server.model.ts b/kdb-web/src/app/models/data/user_joined_server.model.ts new file mode 100644 index 00000000..7828dece --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_server.model.ts @@ -0,0 +1,9 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedServer extends Data { + id: number; + user: User; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts b/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts new file mode 100644 index 00000000..9c49ff2e --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts @@ -0,0 +1,12 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedVoiceChannel extends Data { + id: number; + channelId: string; + channelName: string; + user: User; + time: number; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/discord/server.dto.ts b/kdb-web/src/app/models/discord/server.dto.ts deleted file mode 100644 index a97625b5..00000000 --- a/kdb-web/src/app/models/discord/server.dto.ts +++ /dev/null @@ -1,7 +0,0 @@ -export interface ServerDTO { - serverId: number; - discordId: number; - name: string; - memberCount: number; - iconURL: string | null; -} \ No newline at end of file diff --git a/kdb-web/src/app/models/graphql/filter/page.model.ts b/kdb-web/src/app/models/graphql/filter/page.model.ts new file mode 100644 index 00000000..49adbf15 --- /dev/null +++ b/kdb-web/src/app/models/graphql/filter/page.model.ts @@ -0,0 +1,4 @@ +export interface Page { + pageIndex?: number; + pageSize?: number; +} diff --git a/kdb-web/src/app/models/graphql/filter/sort.model.ts b/kdb-web/src/app/models/graphql/filter/sort.model.ts new file mode 100644 index 00000000..aca195a4 --- /dev/null +++ b/kdb-web/src/app/models/graphql/filter/sort.model.ts @@ -0,0 +1,9 @@ +export interface Sort { + sortColumn?: string; + sortDirection?: SortDirection; +} + +export enum SortDirection { + ASC = "ASC", + DESC = "DESC", +} diff --git a/kdb-web/src/app/models/graphql/mutations.model.ts b/kdb-web/src/app/models/graphql/mutations.model.ts new file mode 100644 index 00000000..0cba6ef3 --- /dev/null +++ b/kdb-web/src/app/models/graphql/mutations.model.ts @@ -0,0 +1,124 @@ +export class Mutations { + static updateUser = ` + mutation updateUser($id: ID, $xp: Int, $levelId: ID) { + user { + updateUser(input: { id: $id, xp: $xp, levelId: $levelId }) { + id + name + xp + level { + id + name + } + } + } + } + `; + + static createAutoRole = ` + mutation createAutoRole($serverId: ID, $channelId: String, $messageId: String) { + autoRole { + createAutoRole(input: { serverId: $serverId, channelId: $channelId, messageId: $messageId }) { + id + channelId + channelName + messageId + } + } + } + `; + + static deleteAutoRole = ` + mutation deleteAutoRole($id: ID) { + autoRole { + deleteAutoRole(id: $id) { + id + channelId + channelName + messageId + } + } + } + `; + + static createAutoRoleRule = ` + mutation createAutoRoleRule($autoRoleId: ID, $emojiName: String, $roleId: String) { + autoRoleRule { + createAutoRoleRule(input: { autoRoleId: $autoRoleId, emojiName: $emojiName, roleId: $roleId }) { + id + emojiName + roleId + roleName + } + } + } + `; + + static updateAutoRoleRule = ` + mutation updateAutoRoleRule($id: ID, $emojiName: String, $roleId: String) { + autoRoleRule { + updateAutoRoleRule(input: { id: $id, emojiName: $emojiName, roleId: $roleId }) { + id + emojiName + roleId + roleName + } + } + } + `; + + static deleteAutoRoleRule = ` + mutation deleteAutoRoleRule($id: ID) { + autoRoleRule { + deleteAutoRoleRule(id: $id) { + id + emojiName + roleId + roleName + } + } + } + `; + + static createLevel = ` + mutation createLevel($name: String, $color: String, $minXp: Int, $permissions: String, $serverId: ID) { + level { + createLevel(input: { name: $name, color: $color, minXp: $minXp, permissions: $permissions, serverId: $serverId}) { + id + name + color + minXp + permissions + server { + id + } + } + } + } + `; + + static updateLevel = ` + mutation updateLevel($id: ID, $name: String, $color: String, $minXp: Int, $permissions: String) { + level { + updateLevel(input: { id: $id, name: $name, color: $color, minXp: $minXp, permissions: $permissions }) { + id + name + color + minXp + permissions + } + } + } + `; + + static deleteLevel = ` + mutation deleteLevel($id: ID) { + level { + deleteLevel(id: $id) { + id + name + } + } + } + `; +} diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts new file mode 100644 index 00000000..29b8dbcf --- /dev/null +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -0,0 +1,209 @@ +export class Queries { + + static guildsQuery = ` + query GuildsQuery($id: ID) { + guilds(filter: {id: $id}) { + id + name + + channels { + id + name + type + } + roles { + id + name + } + emojis { + id + name + url + } + } + } + `; + + static serversQuery = ` + query ServerInfo($filter: ServerFilter, $page: Page, $sort: Sort) { + serverCount + servers(filter: $filter, page: $page, sort: $sort) { + id + name + iconURL + userCount + clients{ + id + discordId + name + sentMessageCount + receivedMessageCount + deletedMessageCount + receivedCommandCount + movedUsersCount + } + } + } + `; + + static levelQuery = ` + query LevelsList($serverId: ID, $filter: LevelFilter, $page: Page, $sort: Sort) { + servers(filter: {id: $serverId}) { + levelCount + levels(filter: $filter, page: $page, sort: $sort) { + id + name + color + minXp + permissions + server { + id + name + } + createdAt + modifiedAt + + history { + id + name + color + minXp + permissions + server + deleted + dateFrom + dateTo + } + } + } + } + `; + + static usersQuery = ` + query UsersList($serverId: ID, $filter: UserFilter, $page: Page, $sort: Sort) { + servers(filter: {id: $serverId}) { + userCount + users(filter: $filter, page: $page, sort: $sort) { + id + discordId + name + xp + ontime + level { + id + name + } + leftServer + server { + id + name + } + + joinedServerCount + joinedServers { + id + joinedOn + leavedOn + } + + joinedVoiceChannelCount + joinedVoiceChannels { + id + channelId + channelName + time + joinedOn + leavedOn + } + + userJoinedGameServerCount + userJoinedGameServers { + id + gameServer + time + joinedOn + leavedOn + } + + createdAt + modifiedAt + + history { + id + discordId + xp + server + deleted + dateFrom + dateTo + } + } + } + } + `; + + static autoRolesQuery = ` + query AutoRoleQuery($serverId: ID, $filter: AutoRoleFilter, $page: Page, $sort: Sort) { + servers(filter: {id: $serverId}) { + autoRoleCount + autoRoles(filter: $filter, page: $page, sort: $sort) { + id + channelId + channelName + messageId + autoRoleRuleCount + + server { + id + } + + createdAt + modifiedAt + + history { + id + channelId + messageId + server + deleted + dateFrom + dateTo + } + } + } + } + `; + + static autoRoleRulesQuery = ` + query AutoRoleRuleQuery($serverId: ID, $autoRoleId: ID, $filter: AutoRoleRuleFilter, $page: Page, $sort: Sort) { + servers(filter: {id: $serverId}) { + autoRoles(filter: {id: $autoRoleId}) { + autoRoleRuleCount + autoRoleRules(filter: $filter, page: $page, sort: $sort) { + id + emojiName + roleId + roleName + + autoRole { + id + } + + createdAt + modifiedAt + + history { + id + emojiName + roleId + autoRole + deleted + dateFrom + dateTo + } + } + } + } + } + `; +} diff --git a/kdb-web/src/app/models/graphql/query.model.ts b/kdb-web/src/app/models/graphql/query.model.ts new file mode 100644 index 00000000..3f7e85a1 --- /dev/null +++ b/kdb-web/src/app/models/graphql/query.model.ts @@ -0,0 +1,35 @@ +import { Server } from "../data/server.model"; +import { User } from "../data/user.model"; +import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; +import { Guild } from "../data/discord.model"; +import { Level } from "../data/level.model"; + +export interface Query { + serverCount: number; + servers: Server[]; +} + +export interface SingleDiscordQuery { + guilds: Guild[]; +} + +export interface UserListQuery { + userCount: number; + users: User[]; +} + +export interface LevelListQuery { + levelCount: number; + levels: Level[]; +} + +export interface AutoRoleQuery { + autoRoleCount: number; + autoRoles: AutoRole[]; +} + +export interface AutoRoleRuleQuery { + autoRoleRuleCount: number; + autoRoleRules: AutoRoleRule[]; +} + diff --git a/kdb-web/src/app/models/graphql/result.model.ts b/kdb-web/src/app/models/graphql/result.model.ts new file mode 100644 index 00000000..d3d6e4a4 --- /dev/null +++ b/kdb-web/src/app/models/graphql/result.model.ts @@ -0,0 +1,47 @@ +import { User } from "../data/user.model"; +import { AutoRole, AutoRoleRule } from "../data/auto_role.model"; +import { Level } from "../data/level.model"; +import { Server } from "../data/server.model"; + +export interface GraphQLResult { + data: { + servers?: Server[]; + }; + errors?: []; +} + +export interface QueryResult { + data: { + servers?: Server[]; + }; +} + +export interface UpdateUserMutationResult { + user: { + updateUser: User + }; +} + +export interface AutoRoleMutationResult { + autoRole: { + createAutoRole?: AutoRole + updateAutoRole?: AutoRole + deleteAutoRole?: AutoRole + }; +} + +export interface AutoRoleRuleMutationResult { + autoRoleRule: { + createAutoRoleRule?: AutoRoleRule + updateAutoRoleRule?: AutoRoleRule + deleteAutoRoleRule?: AutoRoleRule + }; +} + +export interface LevelMutationResult { + level: { + createLevel?: Level + updateLevel?: Level + deleteLevel?: Level + }; +} diff --git a/kdb-web/src/app/models/graphql/variables.model.ts b/kdb-web/src/app/models/graphql/variables.model.ts new file mode 100644 index 00000000..8acb41a6 --- /dev/null +++ b/kdb-web/src/app/models/graphql/variables.model.ts @@ -0,0 +1,9 @@ +import { Page } from "./filter/page.model"; +import { Sort } from "./filter/sort.model"; + +export interface Variables { + filter?: object; + page?: Page; + sort?: Sort; + [x: string | number | symbol]: unknown; +} diff --git a/kdb-web/src/app/models/selection/server/get-filtered-servers-result.dto.ts b/kdb-web/src/app/models/selection/server/get-filtered-servers-result.dto.ts deleted file mode 100644 index 4dfe801a..00000000 --- a/kdb-web/src/app/models/selection/server/get-filtered-servers-result.dto.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { AuthUserDTO } from "../../auth/auth-user.dto"; -import { ServerDTO } from "../../discord/server.dto"; - -export interface GetFilteredServersResultDTO { - servers: ServerDTO[]; - totalCount: number; -} \ No newline at end of file diff --git a/kdb-web/src/app/models/selection/server/server-select-criterion.dto.ts b/kdb-web/src/app/models/selection/server/server-select-criterion.dto.ts deleted file mode 100644 index 08b9ea59..00000000 --- a/kdb-web/src/app/models/selection/server/server-select-criterion.dto.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { SelectCriterion } from "../select-criterion.model"; - -export interface ServerSelectCriterion extends SelectCriterion { - name: string | null; -} \ No newline at end of file diff --git a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html index 9f810bda..58f5eb9d 100644 --- a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html +++ b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html @@ -1,201 +1,236 @@

- {{'admin.auth_users.header' | translate}} + {{'admin.auth_users.header' | translate}}

-
- +
+ - -
-
- {{users.length}} {{'admin.auth_users.of' | translate}} - {{dt.totalRecords}} - - {{'admin.auth_users.users' | translate}} -
+ +
+
+ {{users.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'admin.auth_users.users' | translate}} +
-
- - -
-
-
+
+ + +
+
+
- - - -
-
{{'admin.auth_users.headers.first_name' | translate}}
- -
- + + + +
+
{{'admin.auth_users.headers.first_name' | translate}}
+ +
+ - -
-
{{'admin.auth_users.headers.last_name' | translate}}
- -
- + +
+
{{'admin.auth_users.headers.last_name' | translate}}
+ +
+ - -
-
{{'admin.auth_users.headers.e_mail' | translate}}
- -
- + +
+
{{'common.email' | translate}}
+ +
+ - -
-
{{'admin.auth_users.headers.active' | translate}}
- -
- + +
+
{{'admin.auth_users.headers.active' | translate}}
+ +
+ - -
-
{{'admin.auth_users.headers.role' | translate}}
- -
- + +
+
{{'admin.auth_users.headers.role' | translate}}
+ +
+ - -
-
{{'admin.auth_users.headers.password' | translate}}
-
- + +
+
{{'admin.auth_users.headers.password' | translate}}
+
+ - -
-
{{'admin.auth_users.headers.actions' | translate}}
-
- - - - -
- -
- - -
- -
- - -
- -
- - - -
- -
- - - - -
+ +
+
{{'common.created_at' | translate}}
+
+ - - - - - - - - - {{user.firstName}} - - - - - - - - - - {{user.lastName}} - - - - - - - - - - {{user.email}} - - - - - - - - - - - - - - - - - - - - - - {{user.authRole | authRole}} - - - - - - - - - - - - - -
- - + +
+
{{'common.modified_at' | translate}}
+
+ - - -
- - -
+ +
+
{{'common.actions' | translate}}
+
+ + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + + +
+ +
+ + + + + + +
- - - {{'admin.auth_users.no_entries_found' | translate}} - - + + + + + + + + + {{user.firstName}} + + + + + + + + + + {{user.lastName}} + + + + + + + + + + {{user.email}} + + + + + + + + + + + + + + + + + + + + + + {{user.authRole | authRole}} + + + + + + + + + + + + + + + + {{user.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{user.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{user.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{user.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + +
+ + + + + +
+ + +
+ + + + {{'common.no_entries_found' | translate}} + + + + + +
+
+
- - - -
- \ No newline at end of file diff --git a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts index a9243563..e4a53ca7 100644 --- a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts +++ b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.ts @@ -1,28 +1,28 @@ -import { Component, OnInit } from '@angular/core'; -import { catchError, debounceTime, last } from 'rxjs/operators'; -import { AuthRoles } from 'src/app/models/auth/auth-roles.enum'; -import { AuthUserDTO } from 'src/app/models/auth/auth-user.dto'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { ConfirmationDialogService } from 'src/app/services/confirmation-dialog/confirmation-dialog.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ToastService } from 'src/app/services/toast/toast.service'; -import { Table } from 'primeng/table'; -import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; -import { RegisterErrorMessages } from 'src/app/models/auth/register-error-messages.enum'; -import { ErrorDTO } from 'src/app/models/error/error-dto'; -import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { AuthUserSelectCriterion } from 'src/app/models/selection/auth-user/auth-user-select-criterion.dto'; -import { LazyLoadEvent } from 'primeng/api'; -import { throwError } from 'rxjs'; -import { TranslateService } from '@ngx-translate/core'; +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; +import { AuthRoles } from "src/app/models/auth/auth-roles.enum"; +import { AuthUserDTO } from "src/app/models/auth/auth-user.dto"; +import { AuthService } from "src/app/services/auth/auth.service"; +import { ConfirmationDialogService } from "src/app/services/confirmation-dialog/confirmation-dialog.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { Table } from "primeng/table"; +import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; +import { RegisterErrorMessages } from "src/app/models/auth/register-error-messages.enum"; +import { ErrorDTO } from "src/app/models/error/error-dto"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { AuthUserSelectCriterion } from "src/app/models/selection/auth-user/auth-user-select-criterion.dto"; +import { LazyLoadEvent } from "primeng/api"; +import { Subject, throwError } from "rxjs"; +import { TranslateService } from "@ngx-translate/core"; @Component({ - selector: 'app-auth-user', - templateUrl: './auth-user.component.html', - styleUrls: ['./auth-user.component.scss'] + selector: "app-auth-user", + templateUrl: "./auth-user.component.html", + styleUrls: ["./auth-user.component.scss"] }) -export class AuthUserComponent implements OnInit { +export class AuthUserComponent implements OnInit, OnDestroy { users!: AuthUserDTO[]; statuses!: any[]; @@ -35,7 +35,7 @@ export class AuthUserComponent implements OnInit { authRoles = [ { label: AuthRoles[AuthRoles.Normal].toString(), value: AuthRoles.Normal }, { label: AuthRoles[AuthRoles.Admin].toString(), value: AuthRoles.Admin } - ] + ]; newUserTemplate: AuthUserDTO = { id: 0, @@ -62,6 +62,8 @@ export class AuthUserComponent implements OnInit { searchCriterions!: AuthUserSelectCriterion; totalRecords!: number; + private unsubscriber = new Subject(); + constructor( private authService: AuthService, private spinnerService: SpinnerService, @@ -69,10 +71,11 @@ export class AuthUserComponent implements OnInit { private confirmDialog: ConfirmationDialogService, private fb: FormBuilder, private translate: TranslateService - ) { } + ) { + } ngOnInit(): void { - this.loggedInUserEMail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken()) ?? ''; + this.loggedInUserEMail = this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken()) ?? ""; this.searchCriterions = { firstName: null, lastName: null, @@ -88,15 +91,21 @@ export class AuthUserComponent implements OnInit { this.loadNextPage(); } + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + setFilterForm() { this.filterForm = this.fb.group({ - firstName: [''], - lastName: [''], - email: [''], - authRole: [''] + firstName: [""], + lastName: [""], + email: [""], + authRole: [""] }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) ).subscribe(changes => { if (changes.firstName) { @@ -149,29 +158,29 @@ export class AuthUserComponent implements OnInit { if (event.first != null && event.rows != null) this.searchCriterions.pageIndex = event.first / event.rows; this.searchCriterions.sortColumn = event.sortField ?? null; - this.searchCriterions.sortDirection = event.sortOrder === 1 ? 'asc' : event.sortOrder === -1 ? 'desc' : 'asc'; + this.searchCriterions.sortDirection = event.sortOrder === 1 ? "asc" : event.sortOrder === -1 ? "desc" : "asc"; if (event.filters) { // + "" => convert to string - this.searchCriterions.firstName = event.filters['firstName'] ? event.filters['firstName'] + "" : null; - this.searchCriterions.lastName = event.filters['lastName'] ? event.filters['lastName'] + "" : null; - this.searchCriterions.email = event.filters['email'] ? event.filters['email'] + "" : null; - this.searchCriterions.authRole = event.filters['authRole'] ? +event.filters['authRole'] : null; + this.searchCriterions.firstName = event.filters["firstName"] ? event.filters["firstName"] + "" : null; + this.searchCriterions.lastName = event.filters["lastName"] ? event.filters["lastName"] + "" : null; + this.searchCriterions.email = event.filters["email"] ? event.filters["email"] + "" : null; + this.searchCriterions.authRole = event.filters["authRole"] ? +event.filters["authRole"] : null; } this.loadNextPage(); } - resetFilters(table: Table) { + resetFilters() { this.filterForm.reset(); } initUserList(): void { this.spinnerService.showSpinner(); this.authService.getAllUsers() - .pipe(catchError(err => { + .pipe(catchError(error => { this.spinnerService.hideSpinner(); - throw err; + return throwError(() => error); })) .subscribe(users => { this.users = users; @@ -223,22 +232,22 @@ export class AuthUserComponent implements OnInit { if (err.errorCode === ServiceErrorCode.InvalidData && err.message === RegisterErrorMessages.InvalidEMail) { this.isEMailInvalid = true; - this.toastService.error(this.translate.instant('admin.auth_users.message.invalid_email'), this.translate.instant('admin.auth_users.message.invalid_email_d', { email: newUser.email })); + this.toastService.error(this.translate.instant("admin.auth_users.message.invalid_email"), this.translate.instant("admin.auth_users.message.invalid_email_d", { email: newUser.email })); } else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === RegisterErrorMessages.UserAlreadyExists) { this.isEMailInvalid = true; - this.toastService.error(this.translate.instant('admin.auth_users.message.user_already_exists'), this.translate.instant('admin.auth_users.message.user_already_exists_d', { email: newUser.email })); + this.toastService.error(this.translate.instant("admin.auth_users.message.user_already_exists"), this.translate.instant("admin.auth_users.message.user_already_exists_d", { email: newUser.email })); } error.error = null; table.initRowEdit(newUser); } this.spinnerService.hideSpinner(); - throw error; + return throwError(() => error); })) .subscribe(_ => { this.initUserList(); this.spinnerService.hideSpinner(); - this.toastService.success(this.translate.instant('admin.auth_users.message.user_added'), this.translate.instant('admin.auth_users.message.user_added_d', { email: newUser.email })); + this.toastService.success(this.translate.instant("admin.auth_users.message.user_added"), this.translate.instant("admin.auth_users.message.user_added_d", { email: newUser.email })); this.isEditingNew = false; }); this.triggerUserChangeDetection(); @@ -250,16 +259,16 @@ export class AuthUserComponent implements OnInit { authUserDTO: oldUser, newAuthUserDTO: newUser, changePassword: newUser.password != "" - }).pipe(catchError(err => { + }).pipe(catchError(error => { this.spinnerService.hideSpinner(); - this.toastService.error(this.translate.instant('admin.auth_users.message.user_change_failed'), this.translate.instant('admin.auth_users.message.user_change_failed_d', { email: newUser.email })); + this.toastService.error(this.translate.instant("admin.auth_users.message.user_change_failed"), this.translate.instant("admin.auth_users.message.user_change_failed_d", { email: newUser.email })); this.initUserList(); - throw err; + return throwError(() => error); })) .subscribe(_ => { this.initUserList(); this.spinnerService.hideSpinner(); - this.toastService.success(this.translate.instant('admin.auth_users.message.user_changed'), this.translate.instant('admin.auth_users.message.user_changed_d', { email: newUser.email })); + this.toastService.success(this.translate.instant("admin.auth_users.message.user_changed"), this.translate.instant("admin.auth_users.message.user_changed_d", { email: newUser.email })); }); this.triggerUserChangeDetection(); } @@ -285,31 +294,32 @@ export class AuthUserComponent implements OnInit { deleteUser(user: AuthUserDTO) { if (user.email == this.loggedInUserEMail) { - this.toastService.error(this.translate.instant('admin.auth_users.message.cannot_delete_user'), this.translate.instant('admin.auth_users.message.logon_with_another_user')); + this.toastService.error(this.translate.instant("admin.auth_users.message.cannot_delete_user"), this.translate.instant("admin.auth_users.message.logon_with_another_user")); return; } this.confirmDialog.confirmDialog( - this.translate.instant('admin.auth_users.message.user_delete'), this.translate.instant('admin.auth_users.message.user_delete_q', { email: user.email }), + this.translate.instant("admin.auth_users.message.user_delete"), this.translate.instant("admin.auth_users.message.user_delete_q", { email: user.email }), () => { this.spinnerService.showSpinner(); - this.authService.deleteUserByMail(user.email ?? '') - .pipe(catchError(err => { + this.authService.deleteUserByMail(user.email ?? "") + .pipe(catchError(error => { this.spinnerService.hideSpinner(); - throw err; + return throwError(() => error); })) .subscribe(_ => { this.initUserList(); this.spinnerService.hideSpinner(); - this.toastService.success(this.translate.instant('admin.auth_users.message.user_deleted'), this.translate.instant('admin.auth_users.message.user_deleted_d', { email: user.email })); + this.toastService.success(this.translate.instant("admin.auth_users.message.user_deleted"), this.translate.instant("admin.auth_users.message.user_deleted_d", { email: user.email })); }); }); } addUser(table: Table) { const newUser = JSON.parse(JSON.stringify(this.newUserTemplate)); - newUser.id = Math.max.apply(Math, this.users.map(u => { return u.id ?? 0; })) + 1; - console.log(newUser); + newUser.id = Math.max.apply(Math, this.users.map(u => { + return u.id ?? 0; + })) + 1; this.users.push(newUser); this.triggerUserChangeDetection(); diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html index 067d3ebb..3c78d1a6 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.html @@ -65,42 +65,42 @@

- {{'admin.settings.e_mail.header' | translate}} + {{'admin.settings.email.header' | translate}}

-
{{'admin.settings.e_mail.user' | translate}}:
+
{{'admin.settings.email.user' | translate}}:
{{data.mailUser}}
-
{{'admin.settings.e_mail.host' | translate}}:
+
{{'admin.settings.email.host' | translate}}:
{{data.mailHost}}
-
{{'admin.settings.e_mail.port' | translate}}:
+
{{'admin.settings.email.port' | translate}}:
{{data.mailPort}}
-
{{'admin.settings.e_mail.transceiver' | translate}}:
+
{{'admin.settings.email.transceiver' | translate}}:
{{data.mailTransceiver}}
-
{{'admin.settings.e_mail.e_mail_address' | translate}}:
+
{{'admin.settings.email.email_address' | translate}}:
{{data.mailTransceiverAddress}}
@@ -109,17 +109,17 @@
- +
- \ No newline at end of file + diff --git a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts index 020a8f0e..0f88f42e 100644 --- a/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts +++ b/kdb-web/src/app/modules/admin/settings/components/settings/settings.component.ts @@ -1,15 +1,15 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { TranslateService } from '@ngx-translate/core'; -import { catchError } from 'rxjs/operators'; -import { SettingsDTO } from 'src/app/models/config/settings.dto'; -import { ErrorDTO } from 'src/app/models/error/error-dto'; -import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { GuiService } from 'src/app/services/gui/gui.service'; -import { SettingsService } from 'src/app/services/settings/settings.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ToastService } from 'src/app/services/toast/toast.service'; +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { TranslateService } from "@ngx-translate/core"; +import { catchError } from "rxjs/operators"; +import { SettingsDTO } from "src/app/models/config/settings.dto"; +import { ErrorDTO } from "src/app/models/error/error-dto"; +import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; +import { GuiService } from "src/app/services/gui/gui.service"; +import { SettingsService } from "src/app/services/settings/settings.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { throwError } from "rxjs"; @Component({ selector: 'app-settings', @@ -50,9 +50,9 @@ export class SettingsComponent implements OnInit { this.initForms(); this.guiService.getSettings() - .pipe(catchError(err => { + .pipe(catchError(error => { this.spinnerService.hideSpinner(); - throw err; + return throwError(() => error); })) .subscribe(settings => { this.spinnerService.hideSpinner(); @@ -109,7 +109,7 @@ export class SettingsComponent implements OnInit { this.spinnerService.hideSpinner(); this.toastService.error(header, message); - throw error; + return throwError(() => error); })) .subscribe(res => { this.spinnerService.hideSpinner(); diff --git a/kdb-web/src/app/modules/auth/auth.module.ts b/kdb-web/src/app/modules/auth/auth.module.ts index e0afca6a..a2a83a73 100644 --- a/kdb-web/src/app/modules/auth/auth.module.ts +++ b/kdb-web/src/app/modules/auth/auth.module.ts @@ -7,6 +7,7 @@ import { AuthHeaderComponent } from './components/auth-header/auth-header.compon import { ForgetPasswordComponent } from './components/forget-password/forget-password.component'; import { LoginComponent } from './components/login/login.component'; import { RegistrationComponent } from './components/registration/registration.component'; +import { AuthFooterComponent } from "./components/auth-footer/auth-footer.component"; @NgModule({ @@ -14,7 +15,8 @@ import { RegistrationComponent } from './components/registration/registration.co ForgetPasswordComponent, LoginComponent, RegistrationComponent, - AuthHeaderComponent + AuthHeaderComponent, + AuthFooterComponent ], imports: [ CommonModule, diff --git a/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.html b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.html new file mode 100644 index 00000000..98a35a1e --- /dev/null +++ b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.html @@ -0,0 +1,7 @@ + diff --git a/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.scss b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.spec.ts b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.spec.ts new file mode 100644 index 00000000..98d7ddb7 --- /dev/null +++ b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AuthFooterComponent } from './auth-footer.component'; + +describe('AuthFooterComponent', () => { + let component: AuthFooterComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AuthFooterComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AuthFooterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.ts b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.ts new file mode 100644 index 00000000..763f1f92 --- /dev/null +++ b/kdb-web/src/app/modules/auth/components/auth-footer/auth-footer.component.ts @@ -0,0 +1,32 @@ +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { SettingsService } from "../../../../services/settings/settings.service"; + +@Component({ + selector: "app-auth-footer", + templateUrl: "./auth-footer.component.html", + styleUrls: ["./auth-footer.component.scss"] +}) +export class AuthFooterComponent implements OnInit { + private privacy: string = ""; + private imprint: string = ""; + + constructor( + private settings: SettingsService + ) { + } + + ngOnInit(): void { + this.privacy = this.settings.getPrivacyURL(); + this.imprint = this.settings.getImprintURL(); + } + + public navigateToPrivacy(): void { + window.open(this.settings.getPrivacyURL(), "_blank"); + } + + public navigateToImprint(): void { + window.open(this.settings.getImprintURL(), "_blank"); + } + +} diff --git a/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.html b/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.html index 1b48c147..8a147def 100644 --- a/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.html +++ b/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.html @@ -1,10 +1,10 @@
-
- - -
-
- - -
-
\ No newline at end of file +
+ + +
+
+ + +
+ diff --git a/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.ts b/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.ts index 0858dc8a..8019406c 100644 --- a/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.ts +++ b/kdb-web/src/app/modules/auth/components/auth-header/auth-header.component.ts @@ -1,12 +1,10 @@ -import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; -import { TranslateService, LangChangeEvent } from '@ngx-translate/core'; -import { MenuItem, PrimeNGConfig } from 'primeng/api'; -import { catchError } from 'rxjs'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { SettingsService } from 'src/app/services/settings/settings.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ThemeService } from 'src/app/services/theme/theme.service'; +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; +import { MenuItem, PrimeNGConfig } from "primeng/api"; +import { SettingsService } from "src/app/services/settings/settings.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ThemeService } from "src/app/services/theme/theme.service"; @Component({ selector: 'app-auth-header', @@ -14,9 +12,8 @@ import { ThemeService } from 'src/app/services/theme/theme.service'; styleUrls: ['./auth-header.component.scss'] }) export class AuthHeaderComponent implements OnInit { - langList: MenuItem[] = []; - themeList: MenuItem[] = []; - userMenuList!: MenuItem[]; + public langList: MenuItem[] = []; + public themeList: MenuItem[] = []; constructor( private router: Router, @@ -27,12 +24,12 @@ export class AuthHeaderComponent implements OnInit { private config: PrimeNGConfig ) { } - ngOnInit(): void { + public ngOnInit(): void { this.initMenuLists(); this.loadLang(); } - initMenuLists(): void { + private initMenuLists(): void { this.langList = [ { label: 'English', command: () => { @@ -58,16 +55,16 @@ export class AuthHeaderComponent implements OnInit { }); } - changeTheme(name: string): void { + private changeTheme(name: string): void { this.themeService.setTheme(name, true); } - translate(lang: string) { + private translate(lang: string) { this.translateService.use(lang); this.translateService.get('primeng').subscribe(res => this.config.setTranslation(res)); } - loadLang(): void { + private loadLang(): void { let lang = localStorage.getItem(`default_lang`); if (!lang) { lang = 'en'; @@ -76,7 +73,7 @@ export class AuthHeaderComponent implements OnInit { this.translate(lang); } - setLang(lang: string): void { + private setLang(lang: string): void { localStorage.setItem(`default_lang`, lang); } diff --git a/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.html b/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.html index 71f7761e..a35906ec 100644 --- a/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.html +++ b/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.html @@ -1,63 +1,64 @@ \ No newline at end of file + + + diff --git a/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.ts b/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.ts index f73bd20e..66d570db 100644 --- a/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.ts +++ b/kdb-web/src/app/modules/auth/components/forget-password/forget-password.component.ts @@ -1,17 +1,18 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { ActivatedRoute, Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { catchError } from 'rxjs/operators'; -import { ResetPasswordDTO } from 'src/app/models/auth/reset-password.dto'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ToastService } from 'src/app/services/toast/toast.service'; +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormGroup, Validators } from "@angular/forms"; +import { ActivatedRoute, Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; +import { catchError } from "rxjs/operators"; +import { ResetPasswordDTO } from "src/app/models/auth/reset-password.dto"; +import { AuthService } from "src/app/services/auth/auth.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { throwError } from "rxjs"; @Component({ - selector: 'app-forget-password', - templateUrl: './forget-password.component.html', - styleUrls: ['./forget-password.component.scss'] + selector: "app-forget-password", + templateUrl: "./forget-password.component.html", + styleUrls: ["./forget-password.component.scss"] }) export class ForgetPasswordComponent implements OnInit { @@ -34,20 +35,18 @@ export class ForgetPasswordComponent implements OnInit { private route: ActivatedRoute, private toastService: ToastService, private translate: TranslateService - ) { } + ) { + } ngOnInit(): void { - console.log('test'); this.spinnerService.showSpinner(); - this.authService.isUserLoggedInAsync().then(result => { - if (result) { - this.router.navigate(['/dashboard']); - } + if (!this.authService.isLoggedIn$.value) { + this.router.navigate(["/dashboard"]); + } - this.initForms(); - this.checkResetPasswordId(); - this.spinnerService.hideSpinner(); - }); + this.initForms(); + this.checkResetPasswordId(); + this.spinnerService.hideSpinner(); } initForms(): void { @@ -62,11 +61,11 @@ export class ForgetPasswordComponent implements OnInit { } login(): void { - this.router.navigate(['/auth/login']); + this.router.navigate(["/auth/login"]); } register(): void { - this.router.navigate(['/auth/register']); + this.router.navigate(["/auth/register"]); } forgotPassword(): void { @@ -78,39 +77,41 @@ export class ForgetPasswordComponent implements OnInit { this.spinnerService.showSpinner(); this.authService.forgotPassword(this.emailForm.value.email) - .pipe(catchError(err => { + .pipe(catchError(error => { this.spinnerService.hideSpinner(); - throw err; + return throwError(() => error); })).subscribe(res => { - this.spinnerService.hideSpinner(); - this.ready = true; - setTimeout(() => { this.router.navigate(['/dashboard']); }, 5000); - }); + this.spinnerService.hideSpinner(); + this.ready = true; + setTimeout(() => { + this.router.navigate(["/dashboard"]); + }, 5000); + }); } checkResetPasswordId(): void { - const id = this.route.snapshot.params['id']; + const id = this.route.snapshot.params["id"]; if (id) { this.resetPasswordId = id; this.spinnerService.showSpinner(); this.authService.getEMailFromforgotPasswordId(id) - .pipe(catchError(err => { + .pipe(catchError(error => { this.spinnerService.hideSpinner(); - this.router.navigate(['/auth/forgot-password']); - throw err; + this.router.navigate(["/auth/forgot-password"]); + return throwError(() => error); })).subscribe(email => { - this.spinnerService.hideSpinner(); - if (email) { - this.emailForm.value.email = email; - } else { - this.router.navigate(['/auth/forgot-password']); - } - }); + this.spinnerService.hideSpinner(); + if (email) { + this.emailForm.value.email = email; + } else { + this.router.navigate(["/auth/forgot-password"]); + } + }); } } resetPassword(): void { - const id = this.route.snapshot.params['id']; + const id = this.route.snapshot.params["id"]; if (this.emailForm.value.password !== this.emailForm.value.passwordRepeat) { this.repeatErrors.password = true; return; @@ -124,14 +125,14 @@ export class ForgetPasswordComponent implements OnInit { this.authService.resetPassword(resetPasswordDTO) .pipe(catchError(error => { - this.router.navigate(['/auth/login']); + this.router.navigate(["/auth/login"]); this.spinnerService.hideSpinner(); - throw error; + return throwError(() => error); })) .subscribe(resp => { this.spinnerService.hideSpinner(); - this.toastService.success(this.translate.instant('auth.forgot_password.message.reset_password'), this.translate.instant('auth.forgot_password.message.reset_password_d')); - this.router.navigate(['/auth/login']); + this.toastService.success(this.translate.instant("auth.forgot_password.message.reset_password"), this.translate.instant("auth.forgot_password.message.reset_password_d")); + this.router.navigate(["/auth/login"]); }); } } diff --git a/kdb-web/src/app/modules/auth/components/login/login.component.html b/kdb-web/src/app/modules/auth/components/login/login.component.html index d26ca6d4..f9809db0 100644 --- a/kdb-web/src/app/modules/auth/components/login/login.component.html +++ b/kdb-web/src/app/modules/auth/components/login/login.component.html @@ -4,7 +4,7 @@

{{'auth.header' | translate}}

-
- {{'auth.login.e_mail_required' | translate}}
+ {{'auth.login.email_required' | translate}}
{{'auth.login.user_not_found' | translate}}
-
{{'auth.login.e_mail_not_confirmed' | translate}}
+
{{'auth.login.email_not_confirmed' | translate}}
@@ -24,10 +24,10 @@ styleClass="p-password p-component p-inputwrapper p-input-icon-right" Remove after update! --> -
@@ -62,4 +62,5 @@
+ diff --git a/kdb-web/src/app/modules/auth/components/login/login.component.ts b/kdb-web/src/app/modules/auth/components/login/login.component.ts index 8ab34cf9..fa9d79ac 100644 --- a/kdb-web/src/app/modules/auth/components/login/login.component.ts +++ b/kdb-web/src/app/modules/auth/components/login/login.component.ts @@ -11,6 +11,8 @@ import { AuthUserAtrErrors } from "src/app/models/auth/auth-user-atr-errors"; import { SpinnerService } from "src/app/services/spinner/spinner.service"; import { ThemeService } from "src/app/services/theme/theme.service"; import { throwError } from "rxjs"; +import { TranslateService } from "@ngx-translate/core"; +import { ConfirmationDialogService } from "../../../../services/confirmation-dialog/confirmation-dialog.service"; @Component({ selector: "app-login", @@ -37,23 +39,23 @@ export class LoginComponent implements OnInit { private router: Router, private spinnerService: SpinnerService, private themeService: ThemeService, - private route: ActivatedRoute + private route: ActivatedRoute, + private confirmDialog: ConfirmationDialogService, + private translate: TranslateService ) { } ngOnInit(): void { + this.initLoginForm(); this.spinnerService.showSpinner(); - this.authService.isUserLoggedInAsync().then(result => { - if (result) { - this.router.navigate(["/dashboard"]); - return; - } + if (this.authService.isLoggedIn$.value) { + this.router.navigate(["/dashboard"]); + return; + } - this.checkDiscordLogin(); - this.initLoginForm(); - this.resetStateFlags(); - this.spinnerService.hideSpinner(); - }); + this.checkDiscordLogin(); + this.resetStateFlags(); + this.spinnerService.hideSpinner(); } checkDiscordLogin() { @@ -74,8 +76,21 @@ export class LoginComponent implements OnInit { this.spinnerService.hideSpinner(); this.router.navigate(["auth", "login"]).then(() => { }); + this.state = ""; + this.code = ""; return throwError(() => err); })).subscribe(token => { + if (token.firstLogin) { + this.confirmDialog.confirmDialog( + this.translate.instant( + "auth.login.message.confirm_email"), + this.translate.instant( + "auth.login.message.confirm_email_d", + { email: this.authService.getEMailFromDecodedToken(this.authService.getDecodedToken(token)) } + ) + ); + } + this.authService.saveToken(token); this.themeService.loadTheme(); this.themeService.loadMenu(); @@ -129,17 +144,20 @@ export class LoginComponent implements OnInit { if (err.errorCode === ServiceErrorCode.InvalidData && err.message === AuthErrorMessages.UserIsEmpty) { this.authUserAtrErrors.email.required = true; this.authUserAtrErrors.password.required = true; + error.error = null; } else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === AuthErrorMessages.UserNotFound) { this.authUserAtrErrors.email.wrongData = true; + error.error = null; } else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === AuthErrorMessages.WrongPassword) { this.authUserAtrErrors.password.wrongData = true; + error.error = null; } else if (err.errorCode === ServiceErrorCode.InvalidUser && err.message === AuthErrorMessages.EMailNotConfirmed) { this.authUserAtrErrors.email.notConfirmed = true; + error.error = null; } - error.error = null; } this.spinnerService.hideSpinner(); - throw error; + return throwError(() => error); })) .subscribe(token => { this.authService.saveToken(token); diff --git a/kdb-web/src/app/modules/auth/components/registration/registration.component.html b/kdb-web/src/app/modules/auth/components/registration/registration.component.html index 11a154ef..23772056 100644 --- a/kdb-web/src/app/modules/auth/components/registration/registration.component.html +++ b/kdb-web/src/app/modules/auth/components/registration/registration.component.html @@ -26,29 +26,29 @@
-
- {{'auth.register.e_mail_required' | translate}}
+ {{'auth.register.email_required' | translate}}
{{'auth.register.user_already_exists' | translate}}
-
-
{{'auth.register.e_mails_not_match' | translate}}
+
{{'auth.register.emails_not_match' | translate}}
- +
- @@ -67,11 +67,16 @@
+
+ +   + +
+ -
- {{servers.length}} {{'view.dashboard.of' | translate}} {{totalRecords}} {{'view.dashboard.servers' | translate}}: + {{servers.length}} {{'common.of' | translate}} {{totalRecords}} {{'view.dashboard.servers' | translate}}:
@@ -38,7 +38,7 @@
- {{server.memberCount}} + {{server.userCount}} {{'view.dashboard.server.member_count' | translate}}
@@ -47,4 +47,4 @@
-
\ No newline at end of file + diff --git a/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts b/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts index 046e00c6..f28ae00b 100644 --- a/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts +++ b/kdb-web/src/app/modules/view/dashboard/components/dashboard/dashboard.component.ts @@ -1,40 +1,46 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; -import { Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { LazyLoadEvent } from 'primeng/api'; -import { catchError, debounceTime, throwError } from 'rxjs'; -import { ServerDTO } from 'src/app/models/discord/server.dto'; -import { ServerSelectCriterion } from 'src/app/models/selection/server/server-select-criterion.dto'; -import { ConfirmationDialogService } from 'src/app/services/confirmation-dialog/confirmation-dialog.service'; -import { DataService } from 'src/app/services/data/data.service'; -import { ServerService } from 'src/app/services/data/server.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ToastService } from 'src/app/services/toast/toast.service'; +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; +import { debounceTime, Subject, throwError } from "rxjs"; +import { ConfirmationDialogService } from "src/app/services/confirmation-dialog/confirmation-dialog.service"; +import { DataService } from "src/app/services/data/data.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { Server, ServerFilter } from "../../../../../models/data/server.model"; +import { catchError, takeUntil } from "rxjs/operators"; +import { Queries } from "../../../../../models/graphql/queries.model"; +import { Page } from "../../../../../models/graphql/filter/page.model"; +import { Sort } from "../../../../../models/graphql/filter/sort.model"; +import { Query } from "../../../../../models/graphql/query.model"; +import { SidebarService } from "../../../../../services/sidebar/sidebar.service"; @Component({ - selector: 'app-dashboard', - templateUrl: './dashboard.component.html', - styleUrls: ['./dashboard.component.scss'] + selector: "app-dashboard", + templateUrl: "./dashboard.component.html", + styleUrls: ["./dashboard.component.scss"] }) -export class DashboardComponent implements OnInit { +export class DashboardComponent implements OnInit, OnDestroy { - servers: ServerDTO[] = []; + servers: Server[] = []; - searchCriterions: ServerSelectCriterion = { - name: null, + totalRecords: number = 0; + + filter: ServerFilter = {}; + + page: Page = { pageIndex: 0, - pageSize: 10, - sortColumn: null, - sortDirection: null + pageSize: 10 }; - totalRecords!: number; + sort: Sort = {}; filterForm!: FormGroup<{ name: FormControl, }>; + private unsubscriber = new Subject(); + constructor( private data: DataService, private spinnerService: SpinnerService, @@ -43,73 +49,66 @@ export class DashboardComponent implements OnInit { private fb: FormBuilder, private translate: TranslateService, private router: Router, - private serverService: ServerService - ) { } + private sidebar: SidebarService + ) { + } - ngOnInit(): void { + async ngOnInit(): Promise { this.spinnerService.showSpinner(); + this.setFilterForm(); this.loadNextPage(); } + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + setFilterForm() { this.filterForm = this.fb.group({ - name: [''], + name: new FormControl(null) }); this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), debounceTime(600) - ).subscribe(changes => { - if (changes.name) { - this.searchCriterions.name = changes.name; - } else { - this.searchCriterions.name = null; + ).subscribe(async changes => { + if (changes.name == "") { + this.filter.name = undefined; + } else if (changes.name) { + this.filter.name = changes.name; } - if (this.searchCriterions.pageSize) - this.searchCriterions.pageSize = 10; + if (this.page.pageSize) + this.page.pageSize = 10; - if (this.searchCriterions.pageSize) - this.searchCriterions.pageIndex = 0; + if (this.page.pageSize) + this.page.pageIndex = 0; - this.loadNextPage(); + await this.loadNextPage(); }); } loadNextPage() { this.spinnerService.showSpinner(); - this.data.getFilteredServers(this.searchCriterions).pipe(catchError(err => { + this.data.query(Queries.serversQuery, { + filter: this.filter, + page: this.page, + sort: this.sort + }).pipe(catchError(err => { this.spinnerService.hideSpinner(); return throwError(() => err); - })).subscribe(list => { - this.totalRecords = list.totalCount; - this.servers = list.servers; + })).subscribe(data => { + this.totalRecords = data.serverCount; + this.servers = data.servers; this.spinnerService.hideSpinner(); }); } - nextPage(event: LazyLoadEvent) { - this.searchCriterions.pageSize = event.rows ?? 0; - if (event.first != null && event.rows != null) - this.searchCriterions.pageIndex = event.first / event.rows; - this.searchCriterions.sortColumn = event.sortField ?? null; - this.searchCriterions.sortDirection = event.sortOrder === 1 ? 'asc' : event.sortOrder === -1 ? 'desc' : 'asc'; - - if (event.filters) { - // + "" => convert to string - this.searchCriterions.name = event.filters['name'] ? event.filters['name'] + "" : null; - } - - this.loadNextPage(); - } - - resetFilters() { - this.filterForm.reset(); - } - - selectServer(server: ServerDTO) { - this.serverService.server$.next(server); - this.router.navigate(['/server']); + selectServer(server: Server) { + this.sidebar.setServer(server); + this.router.navigate(["/server", server.id]); } } diff --git a/kdb-web/src/app/modules/view/server/auto-role/auto-role-routing.module.ts b/kdb-web/src/app/modules/view/server/auto-role/auto-role-routing.module.ts new file mode 100644 index 00000000..fa90d850 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/auto-role-routing.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from "@angular/core"; +import { RouterModule, Routes } from "@angular/router"; +import { AutoRolesComponent } from "./components/auto-roles/auto-roles.component"; +import { AutoRolesRulesComponent } from "./components/auto-roles-rules/auto-roles-rules.component"; + +const routes: Routes = [ + + { path: "", component: AutoRolesComponent }, + { path: ":autoRoleId/rules", component: AutoRolesRulesComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class AutoRoleRoutingModule { + +} diff --git a/kdb-web/src/app/modules/view/server/auto-role/auto-role.module.ts b/kdb-web/src/app/modules/view/server/auto-role/auto-role.module.ts new file mode 100644 index 00000000..6d5b3248 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/auto-role.module.ts @@ -0,0 +1,21 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; + +import { AutoRoleRoutingModule } from "./auto-role-routing.module"; +import { AutoRolesComponent } from "./components/auto-roles/auto-roles.component"; +import { AutoRolesRulesComponent } from "./components/auto-roles-rules/auto-roles-rules.component"; +import { SharedModule } from "../../../shared/shared.module"; + + +@NgModule({ + declarations: [ + AutoRolesComponent, + AutoRolesRulesComponent + ], + imports: [ + CommonModule, + AutoRoleRoutingModule, + SharedModule, + ] +}) +export class AutoRoleModule { } diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html new file mode 100644 index 00000000..60c0d0eb --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.html @@ -0,0 +1,189 @@ +

+ {{'view.server.auto_roles.rules.header' | translate}} +

+
+
+ + + +
+
+ {{rules.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.auto_roles.rules.auto_roles' | translate}} +
+ +
+ + +
+
+
+ + + + +
+
{{'common.id' | translate}}
+ +
+ + + +
+
{{'view.server.auto_roles.rules.headers.role' | translate}}
+ +
+ + + +
+
{{'view.server.auto_roles.rules.headers.emoji' | translate}}
+
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'common.actions' | translate}}
+
+ + + + + + + + + + +
+ +
+ + + + + + +
+ + + + + + + {{autoRoleRule.id}} + + + {{autoRoleRule.id}} + + + + + + + + + + + {{autoRoleRule.roleName}} + + + + + + + + + + + + + + + + + + + + + + + + + + {{autoRoleRule.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{autoRoleRule.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + + {{autoRoleRule.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{autoRoleRule.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + + +
+ + + + + + +
+ + +
+ + + + + {{'common.no_entries_found' | translate}} + + + + + + +
+
+
diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.scss b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.spec.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.spec.ts new file mode 100644 index 00000000..33059010 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AutoRolesRulesComponent } from './auto-roles-rules.component'; + +describe('AutoRolesRulesComponent', () => { + let component: AutoRolesRulesComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AutoRolesRulesComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AutoRolesRulesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts new file mode 100644 index 00000000..a4b9db54 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles-rules/auto-roles-rules.component.ts @@ -0,0 +1,299 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { DataService } from "../../../../../../services/data/data.service"; +import { ActivatedRoute, Router } from "@angular/router"; +import { AutoRoleRule, AutoRoleRuleFilter } from "../../../../../../models/data/auto_role.model"; +import { Guild } from "../../../../../../models/data/discord.model"; +import { LazyLoadEvent, MenuItem } from "primeng/api"; +import { User } from "../../../../../../models/data/user.model"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Page } from "../../../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; +import { AuthService } from "../../../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { TranslateService } from "@ngx-translate/core"; +import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; +import { AutoRoleRuleQuery, SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { Server } from "../../../../../../models/data/server.model"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; +import { Table } from "primeng/table"; +import { AutoRoleMutationResult, AutoRoleRuleMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; +import { Subject, throwError } from "rxjs"; + +@Component({ + selector: "app-auto-roles-rules", + templateUrl: "./auto-roles-rules.component.html", + styleUrls: ["./auto-roles-rules.component.scss"] +}) +export class AutoRolesRulesComponent implements OnInit, OnDestroy { + + rules: AutoRoleRule[] = []; + guild: Guild = { channels: [], emojis: [], roles: [] }; + emojis: MenuItem[] = []; + roles: MenuItem[] = []; + loading = true; + + autoRoleId!: number; + + clonedUsers: { [s: string]: User; } = {}; + isEditingNew: boolean = false; + + newAutoRoleTemplate: AutoRoleRule = { + createdAt: "", + modifiedAt: "" + }; + + filterForm!: FormGroup<{ + id: FormControl, + emojiName: FormControl, + roleId: FormControl, + }>; + + filter: AutoRoleRuleFilter = {}; + page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + totalRecords: number = 0; + private unsubscriber = new Subject(); + private server: Server = {}; + + constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private sidebar: SidebarService, + private route: ActivatedRoute, + private router: Router + ) { + } + + public getEmojiUrl(name: string): string { + return this.guild?.emojis.filter(x => x.name == name)[0].url ?? ""; + } + + public ngOnInit(): void { + this.setFilterForm(); + this.data.getServerFromRoute(this.route).then(server => { + this.server = server; + this.spinner.showSpinner(); + if (!this.route.snapshot.params["autoRoleId"]) { + this.spinner.hideSpinner(); + this.router.navigate(["../"]); + return; + } + this.autoRoleId = +this.route.snapshot.params["autoRoleId"]; + + this.spinner.showSpinner(); + this.data.query(Queries.guildsQuery, { + filter: { + id: server.discordId + } + } + ).subscribe(data => { + this.guild = data.guilds[0]; + this.emojis = this.guild.emojis + .map(x => { + return { label: x.name, value: x }; + }); + this.roles = this.guild.roles + .map(x => { + return { label: x.name, value: x }; + }); + this.spinner.hideSpinner(); + }); + this.loadNextPage(); + }); + } + + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + + public loadNextPage(): void { + this.loading = true; + this.data.query(Queries.autoRoleRulesQuery, { + serverId: this.server.id, autoRoleId: this.autoRoleId, filter: this.filter, page: this.page, sort: this.sort + }, + (x: { servers: Server[] }) => { + if (!x.servers[0].autoRoles || x.servers[0].autoRoles?.length == 0) { + return undefined; + } + return x.servers[0].autoRoles[0]; + } + ).subscribe(data => { + this.totalRecords = data.autoRoleRuleCount; + this.rules = data.autoRoleRules; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + public setFilterForm(): void { + this.filterForm = this.fb.group({ + id: new FormControl(null), + emojiName: new FormControl(null), + roleId: new FormControl(null) + }); + + this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.emojiName) { + this.filter.emojiName = changes.emojiName; + } else { + this.filter.emojiName = undefined; + } + + if (changes.roleId) { + this.filter.roleId = changes.roleId; + } else { + this.filter.roleId = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + public nextPage(event: LazyLoadEvent): void { + this.page.pageSize = event.rows ?? 0; + if (event.first != null && event.rows != null) + this.page.pageIndex = event.first / event.rows; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + + public resetFilters(): void { + this.filterForm.reset(); + } + + public onRowEditInit(table: Table, autoRoleRule: AutoRoleRule, index: number): void { + this.clonedUsers[index] = { ...autoRoleRule }; + } + + public onRowEditSave(table: Table, newAutoRoleRule: AutoRoleRule, index: number): void { + if (this.isEditingNew && JSON.stringify(newAutoRoleRule) === JSON.stringify(this.newAutoRoleTemplate)) { + this.isEditingNew = false; + this.rules.splice(index, 1); + return; + } + + if (!newAutoRoleRule.id && !this.isEditingNew || !newAutoRoleRule.emojiName && !newAutoRoleRule.roleId) { + return; + } + + if (this.isEditingNew) { + this.spinner.showSpinner(); + this.data.mutation(Mutations.createAutoRoleRule, { + autoRoleId: this.autoRoleId, + emojiName: newAutoRoleRule.emojiName, + roleId: newAutoRoleRule.roleId + } + ).pipe(catchError(err => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_failed_d")); + return throwError(err); + })).subscribe(result => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_created"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_create_d", { id: result.autoRoleRule.createAutoRoleRule?.id })); + this.loadNextPage(); + }); + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateAutoRoleRule, { + id: newAutoRoleRule.id, + emojiName: newAutoRoleRule.emojiName, + roleId: newAutoRoleRule.roleId + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_failed_d")); + return throwError(err); + })).subscribe(result => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_updated"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_update_d", { id: result.autoRole.createAutoRole?.id })); + this.loadNextPage(); + }); + } + + public onRowEditCancel(index: number): void { + if (this.isEditingNew) { + this.rules.splice(index, 1); + delete this.clonedUsers[index]; + this.isEditingNew = false; + return; + } + + this.rules[index] = this.clonedUsers[index]; + delete this.clonedUsers[index]; + } + + public deleteAutoRoleRule(autoRoleRule: AutoRoleRule): void { + this.confirmDialog.confirmDialog( + this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_q", { id: autoRoleRule.id }), + () => { + this.spinner.showSpinner(); + this.data.mutation(Mutations.deleteAutoRoleRule, { + id: autoRoleRule.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_delete_failed_d", { id: autoRoleRule.id })); + return throwError(err); + })).subscribe(_ => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_deleted"), this.translate.instant("view.server.auto_roles.rules.message.auto_role_rule_deleted_d", { id: autoRoleRule.id })); + this.loadNextPage(); + }); + }); + } + + public addAutoRoleRule(table: Table): void { + const newAutoRole = JSON.parse(JSON.stringify(this.newAutoRoleTemplate)); + newAutoRole.id = Math.max.apply(Math, this.rules.map(u => { + return u.id ?? 0; + })) + 1; + + this.rules.push(newAutoRole); + + table.initRowEdit(newAutoRole); + + const index = this.rules.findIndex(u => u.id == newAutoRole.id); + this.onRowEditInit(table, newAutoRole, index); + + this.isEditingNew = true; + } + +} diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.html b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.html new file mode 100644 index 00000000..f6695fca --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.html @@ -0,0 +1,222 @@ +

+ {{'view.server.auto_roles.header' | translate}} +

+
+
+ + + +
+
+ {{auto_roles.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.auto_roles.auto_roles' | translate}} +
+ +
+ + +
+
+
+ + + + +
+
{{'common.id' | translate}}
+ +
+ + + +
+
{{'view.server.auto_roles.headers.channel_id' | translate}}
+ +
+ + + +
+
{{'view.server.auto_roles.headers.channel_name' | translate}}
+ +
+ + + +
+
{{'view.server.auto_roles.headers.message_id' | translate}}
+ +
+ + + +
+
{{'view.server.auto_roles.headers.role_count' | translate}}
+
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'common.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + + + +
+ + + + + + + {{autoRole.id}} + + + {{autoRole.id}} + + + + + + + + + + + {{autoRole.channelId}} + + + + + + + + {{autoRole.channelName}} + + + {{autoRole.channelName}} + + + + + + + + + + + {{autoRole.messageId}} + + + + + + + + {{autoRole.autoRoleRuleCount}} + + + {{autoRole.autoRoleRuleCount}} + + + + + + + + {{autoRole.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{autoRole.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + + {{autoRole.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{autoRole.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + + +
+ + + + + + + + +
+ + +
+ + + + + {{'common.no_entries_found' | translate}} + + + + + + +
+
+
diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.scss b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.spec.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.spec.ts new file mode 100644 index 00000000..88577828 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AutoRolesComponent } from './auto-roles.component'; + +describe('AutoRolesComponent', () => { + let component: AutoRolesComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ AutoRolesComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AutoRolesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts new file mode 100644 index 00000000..12b070c0 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/auto-role/components/auto-roles/auto-roles.component.ts @@ -0,0 +1,268 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { User } from "../../../../../../models/data/user.model"; +import { LazyLoadEvent, MenuItem } from "primeng/api"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { Page } from "../../../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; +import { AuthService } from "../../../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { TranslateService } from "@ngx-translate/core"; +import { DataService } from "../../../../../../services/data/data.service"; +import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; +import { ActivatedRoute } from "@angular/router"; +import { AutoRoleQuery, SingleDiscordQuery } from "../../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; +import { Table } from "primeng/table"; +import { AutoRoleMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; +import { Subject, throwError } from "rxjs"; +import { AutoRole, AutoRoleFilter } from "../../../../../../models/data/auto_role.model"; +import { ChannelType, Guild } from "../../../../../../models/data/discord.model"; +import { Server } from "../../../../../../models/data/server.model"; + +@Component({ + selector: "app-auto-roles", + templateUrl: "./auto-roles.component.html", + styleUrls: ["./auto-roles.component.scss"] +}) +export class AutoRolesComponent implements OnInit, OnDestroy { + auto_roles: AutoRole[] = []; + guild: Guild = { channels: [], emojis: [], roles: [] }; + channels: MenuItem[] = []; + loading = true; + + clonedUsers: { [s: string]: User; } = {}; + isEditingNew: boolean = false; + + newAutoRoleTemplate: AutoRole = { + createdAt: "", + modifiedAt: "" + }; + + filterForm!: FormGroup<{ + id: FormControl, + channelId: FormControl, + channelName: FormControl, + messageId: FormControl, + }>; + + filter: AutoRoleFilter = {}; + page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + totalRecords: number = 0; + private unsubscriber = new Subject(); + private server: Server = {}; + + constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private sidebar: SidebarService, + private route: ActivatedRoute + ) { + } + + public ngOnInit(): void { + + this.setFilterForm(); + this.data.getServerFromRoute(this.route).then(server => { + this.server = server; + this.spinner.showSpinner(); + this.data.query(Queries.guildsQuery, { + filter: { + id: server?.discordId + } + } + ).subscribe(data => { + this.guild = data.guilds[0]; + this.channels = this.guild.channels + .filter(x => x.type === ChannelType.text) + .map(x => { + return { label: x.name, value: x }; + }); + this.spinner.hideSpinner(); + }); + this.loadNextPage(); + }); + } + + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + + + public loadNextPage(): void { + this.loading = true; + this.data.query(Queries.autoRolesQuery, { + serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort + }, + (x: { servers: Server[] }) => { + return x.servers[0]; + } + ).subscribe(data => { + this.totalRecords = data.autoRoleCount; + this.auto_roles = data.autoRoles; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + public setFilterForm(): void { + this.filterForm = this.fb.group({ + id: new FormControl(null), + channelId: new FormControl(null), + channelName: new FormControl(null), + messageId: new FormControl(null) + }); + + this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.channelId) { + this.filter.channelId = changes.channelId; + } else { + this.filter.channelId = undefined; + } + + if (changes.channelName) { + this.filter.channelName = changes.channelName; + } else { + this.filter.channelName = undefined; + } + + if (changes.messageId) { + this.filter.messageId = changes.messageId; + } else { + this.filter.messageId = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + public nextPage(event: LazyLoadEvent): void { + this.page.pageSize = event.rows ?? 0; + if (event.first != null && event.rows != null) + this.page.pageIndex = event.first / event.rows; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + + public resetFilters(): void { + this.filterForm.reset(); + } + + public onRowEditInit(table: Table, autoRole: AutoRole, index: number): void { + this.clonedUsers[index] = { ...autoRole }; + } + + public onRowEditSave(table: Table, newAutoRole: AutoRole, index: number): void { + if (this.isEditingNew && JSON.stringify(newAutoRole) === JSON.stringify(this.newAutoRoleTemplate)) { + this.isEditingNew = false; + this.auto_roles.splice(index, 1); + return; + } + + if (!newAutoRole.id || !newAutoRole.channelId && !newAutoRole.messageId) { + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.createAutoRole, { + serverId: this.server.id, + channelId: newAutoRole.channelId, + messageId: newAutoRole.messageId + } + ).pipe(catchError(err => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_create_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_create_failed_d")); + return throwError(err); + })).subscribe(result => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.auto_roles.message.auto_role_created"), this.translate.instant("view.server.auto_roles.message.auto_role_create_d", { id: result.autoRole.createAutoRole?.id })); + this.loadNextPage(); + }); + } + + public onRowEditCancel(index: number): void { + if (this.isEditingNew) { + this.auto_roles.splice(index, 1); + delete this.clonedUsers[index]; + this.isEditingNew = false; + return; + } + + this.auto_roles[index] = this.clonedUsers[index]; + delete this.clonedUsers[index]; + } + + public deleteAutoRole(autoRole: AutoRole): void { + this.confirmDialog.confirmDialog( + this.translate.instant("view.server.auto_roles.message.auto_role_delete"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_q", { id: autoRole.id }), + () => { + this.spinner.showSpinner(); + this.data.mutation(Mutations.deleteAutoRole, { + id: autoRole.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed"), this.translate.instant("view.server.auto_roles.message.auto_role_delete_failed_d", { id: autoRole.id })); + return throwError(err); + })).subscribe(_ => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.auto_roles.message.auto_role_deleted"), this.translate.instant("view.server.auto_roles.message.auto_role_deleted_d", { id: autoRole.id })); + this.loadNextPage(); + }); + }); + + + } + + public addAutoRole(table: Table): void { + const newAutoRole = JSON.parse(JSON.stringify(this.newAutoRoleTemplate)); + newAutoRole.id = Math.max.apply(Math, this.auto_roles.map(u => { + return u.id ?? 0; + })) + 1; + + this.auto_roles.push(newAutoRole); + + table.initRowEdit(newAutoRole); + + const index = this.auto_roles.findIndex(u => u.id == newAutoRole.id); + this.onRowEditInit(table, newAutoRole, index); + + this.isEditingNew = true; + } +} diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html new file mode 100644 index 00000000..83f32aa3 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.html @@ -0,0 +1,215 @@ +

+ {{'view.server.levels.header' | translate}} +

+
+
+ + + +
+
+ {{levels.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.levels.levels' | translate}} +
+ +
+ + +
+
+
+ + + + +
+
{{'common.id' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.name' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.color' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.min_xp' | translate}}
+ +
+ + + +
+
{{'view.server.levels.headers.permissions' | translate}}
+ +
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'common.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + + + + + + + +
+ + + + + + + {{level.id}} + + + {{level.id}} + + + + + + + + + + + {{level.name}} + + + + + + + + + + + {{level.color}} + + + + + + + + + + + {{level.minXp}} + + + + + + + + + + + {{level.permissions}} + + + + + + + + {{level.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{level.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{level.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{level.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + +
+ + + + + + +
+ + +
+ + + + + {{'common.no_entries_found' | translate}} + + + + + + +
+
+
+ diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.scss b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts new file mode 100644 index 00000000..30dc8eca --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LevelsComponent } from './levels.component'; + +describe('LevelsComponent', () => { + let component: LevelsComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ LevelsComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(LevelsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts new file mode 100644 index 00000000..d3a06f84 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/components/levels/levels.component.ts @@ -0,0 +1,276 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { AuthService } from "../../../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { TranslateService } from "@ngx-translate/core"; +import { DataService } from "../../../../../../services/data/data.service"; +import { SidebarService } from "../../../../../../services/sidebar/sidebar.service"; +import { ActivatedRoute } from "@angular/router"; +import { Page } from "../../../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../../../models/graphql/filter/sort.model"; +import { Level, LevelFilter } from "../../../../../../models/data/level.model"; +import { LevelListQuery, Query } from "../../../../../../models/graphql/query.model"; +import { Queries } from "../../../../../../models/graphql/queries.model"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; +import { LazyLoadEvent } from "primeng/api"; +import { Table } from "primeng/table"; +import { User } from "../../../../../../models/data/user.model"; +import { LevelMutationResult, UpdateUserMutationResult } from "../../../../../../models/graphql/result.model"; +import { Mutations } from "../../../../../../models/graphql/mutations.model"; +import { Subject, throwError } from "rxjs"; +import { Server } from "../../../../../../models/data/server.model"; +import { UserDTO } from "../../../../../../models/auth/auth-user.dto"; + +@Component({ + selector: "app-levels", + templateUrl: "./levels.component.html", + styleUrls: ["./levels.component.scss"] +}) +export class LevelsComponent implements OnInit, OnDestroy { + + public levels: Level[] = []; + public loading = true; + + public isEditingNew: boolean = false; + + public filterForm!: FormGroup<{ + id: FormControl, + name: FormControl, + color: FormControl, + min_xp: FormControl, + permissions: FormControl, + }>; + + public filter: LevelFilter = {}; + public page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + public sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + public totalRecords: number = 0; + + public clonedLevels: { [s: string]: Level; } = {}; + + private unsubscriber = new Subject(); + private server: Server = {}; + public user: UserDTO | null = null; + + public constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private sidebar: SidebarService, + private route: ActivatedRoute) { + } + + public ngOnInit(): void { + this.setFilterForm(); + this.data.getServerFromRoute(this.route).then(async server => { + this.server = server; + this.loadNextPage(); + let authUser = await this.authService.getLoggedInUser(); + this.user = authUser?.users?.find(u => u.server == this.server.id) ?? null; + }); + } + + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + + public loadNextPage(): void { + this.loading = true; + this.data.query(Queries.levelQuery, { + serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort + }, + (data: Query) => { + return data.servers[0]; + } + ).subscribe(data => { + this.totalRecords = data.levelCount; + this.levels = data.levels; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + public setFilterForm(): void { + this.filterForm = this.fb.group({ + id: new FormControl(null), + name: new FormControl(null), + color: new FormControl(null), + min_xp: new FormControl(null), + permissions: new FormControl(null) + }); + + this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.name) { + this.filter.name = changes.name; + } else { + this.filter.name = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + public newLevelTemplate: Level = { + id: 0, + createdAt: "", + modifiedAt: "" + }; + + public nextPage(event: LazyLoadEvent): void { + this.page.pageSize = event.rows ?? 0; + if (event.first != null && event.rows != null) + this.page.pageIndex = event.first / event.rows; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + + public resetFilters(): void { + this.filterForm.reset(); + } + + public onRowEditInit(table: Table, user: User, index: number): void { + this.clonedLevels[index] = { ...user }; + } + + public onRowEditSave(table: Table, newLevel: Level, index: number): void { + // const oldUser = this.clonedUsers[index]; + // delete this.clonedUsers[index]; + + // if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) { + // console.log(1, oldUser, newUser, JSON.stringify(oldUser) === JSON.stringify(newUser), !this.isEditingNew); + // return; + // } + + if (this.isEditingNew && JSON.stringify(newLevel) === JSON.stringify(this.newLevelTemplate)) { + this.isEditingNew = false; + this.levels.splice(index, 1); + return; + } + + if (!newLevel.id && !this.isEditingNew || !newLevel.minXp && !newLevel?.name && !newLevel?.permissions) { + return; + } + + if (this.isEditingNew) { + this.spinner.showSpinner(); + this.data.mutation(Mutations.createLevel, { + name: newLevel.name, + color: newLevel.color, + minXp: newLevel.minXp, + permissions: newLevel.permissions, + serverId: this.server.id + } + ).pipe(catchError(err => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.levels.message.level_create_failed"), this.translate.instant("view.server.levels.message.level_create_failed_d")); + return throwError(err); + })).subscribe(result => { + this.isEditingNew = false; + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.levels.message.level_create"), this.translate.instant("view.server.levels.message.level_create_d", { name: result.level.createLevel?.name })); + this.loadNextPage(); + }); + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateLevel, { + id: newLevel.id, + name: newLevel.name, + color: newLevel.color, + minXp: newLevel.minXp, + permissions: newLevel.permissions + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.levels.message.level_update_failed"), this.translate.instant("view.server.levels.message.level_update_failed_d", { name: newLevel.name })); + return throwError(err); + })).subscribe(_ => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.levels.message.level_update"), this.translate.instant("view.server.levels.message.level_update_d", { name: newLevel.name })); + this.loadNextPage(); + }); + + } + + public onRowEditCancel(index: number): void { + if (this.isEditingNew) { + this.levels.splice(index, 1); + delete this.clonedLevels[index]; + this.isEditingNew = false; + return; + } + + this.levels[index] = this.clonedLevels[index]; + delete this.clonedLevels[index]; + } + + public deleteLevel(level: Level): void { + this.confirmDialog.confirmDialog( + this.translate.instant("view.server.levels.message.level_delete"), this.translate.instant("view.server.levels.message.level_delete_q", { name: level.name }), + () => { + this.spinner.showSpinner(); + this.data.mutation(Mutations.deleteLevel, { + id: level.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.levels.message.level_delete_failed"), this.translate.instant("view.server.levels.message.level_delete_failed_d", { name: level.name })); + return throwError(err); + })).subscribe(l => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.levels.message.level_deleted"), this.translate.instant("view.server.levels.message.level_deleted_d", { name: level.name })); + this.loadNextPage(); + }); + }); + } + + public addLevel(table: Table): void { + const newLevel = JSON.parse(JSON.stringify(this.newLevelTemplate)); + newLevel.id = Math.max.apply(Math, this.levels.map(l => { + return l.id ?? 0; + })) + 1; + + this.levels.push(newLevel); + + table.initRowEdit(newLevel); + + const index = this.levels.findIndex(l => l.id == newLevel.id); + this.onRowEditInit(table, newLevel, index); + + this.isEditingNew = true; + } + +} diff --git a/kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts b/kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts new file mode 100644 index 00000000..76c42715 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/levels-routing.module.ts @@ -0,0 +1,16 @@ +import {NgModule} from "@angular/core"; +import {RouterModule, Routes} from "@angular/router"; +import {LevelsComponent} from "./components/levels/levels.component"; + +const routes: Routes = [ + + {path: '', component: LevelsComponent}, +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class LevelsRoutingModule { + +} diff --git a/kdb-web/src/app/modules/view/server/levels/levels.module.ts b/kdb-web/src/app/modules/view/server/levels/levels.module.ts new file mode 100644 index 00000000..a9d0ba8e --- /dev/null +++ b/kdb-web/src/app/modules/view/server/levels/levels.module.ts @@ -0,0 +1,18 @@ +import {NgModule} from '@angular/core'; +import {CommonModule} from '@angular/common'; +import {LevelsComponent} from './components/levels/levels.component' +import {SharedModule} from "../../../shared/shared.module"; +import {LevelsRoutingModule} from "./levels-routing.module"; + +@NgModule({ + declarations: [ + LevelsComponent + ], + imports: [ + CommonModule, + LevelsRoutingModule, + SharedModule + ] +}) +export class LevelsModule { +} diff --git a/kdb-web/src/app/modules/view/server/members/members.component.html b/kdb-web/src/app/modules/view/server/members/members.component.html new file mode 100644 index 00000000..85e1f0f7 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/members/members.component.html @@ -0,0 +1,254 @@ +

+ {{'view.server.members.header' | translate}} +

+
+
+ + + +
+
+ {{members.length}} {{'common.of' | translate}} + {{dt.totalRecords}} + + {{'view.server.members.members' | translate}} +
+ +
+ +
+
+
+ + + + +
+
{{'common.id' | translate}}
+ +
+ + + +
+
{{'common.discord_id' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.name' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.xp' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.ontime' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.left_server' | translate}}
+ +
+ + + +
+
{{'view.server.members.headers.level' | translate}}
+ +
+ + + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ + + +
+
{{'common.actions' | translate}}
+
+ + + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + +
+ +
+ + +
+ +
+ + + + + +
+ + + + + + + {{member.id}} + + + {{member.id}} + + + + + + + {{member.discordId}} + + + {{member.discordId}} + + + + + + + {{member.name}} + + + {{member.name}} + + + + + + + + + + + {{member.xp}} + + + + + + + {{member.ontime}} + + + {{member.ontime}} + + + + + + + {{!member.leftServer | bool}} + + + {{!member.leftServer | bool}} + + + + + + + + + + {{member.level.name}} + + + + + + + {{member.createdAt | date:'dd.MM.yy HH:mm'}} + + + {{member.createdAt | date:'dd.MM.yy HH:mm'}} + + + + + + + {{member.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + {{member.modifiedAt | date:'dd.MM.yy HH:mm'}} + + + + +
+ + + + + + +
+ + +
+ + + + + {{'common.no_entries_found' | translate}} + + + + + + +
+
+
diff --git a/kdb-web/src/app/modules/view/server/members/members.component.scss b/kdb-web/src/app/modules/view/server/members/members.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/members/members.component.spec.ts b/kdb-web/src/app/modules/view/server/members/members.component.spec.ts new file mode 100644 index 00000000..f626726f --- /dev/null +++ b/kdb-web/src/app/modules/view/server/members/members.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MembersComponent } from './members.component'; + +describe('MembersComponent', () => { + let component: MembersComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ MembersComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(MembersComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts new file mode 100644 index 00000000..6c003086 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -0,0 +1,260 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { FormBuilder, FormControl, FormGroup } from "@angular/forms"; +import { AuthService } from "../../../../services/auth/auth.service"; +import { SpinnerService } from "../../../../services/spinner/spinner.service"; +import { ToastService } from "../../../../services/toast/toast.service"; +import { ConfirmationDialogService } from "../../../../services/confirmation-dialog/confirmation-dialog.service"; +import { TranslateService } from "@ngx-translate/core"; +import { catchError, debounceTime, takeUntil } from "rxjs/operators"; +import { LazyLoadEvent, MenuItem } from "primeng/api"; +import { Table } from "primeng/table"; +import { User, UserFilter } from "../../../../models/data/user.model"; +import { Queries } from "../../../../models/graphql/queries.model"; +import { LevelListQuery, Query, UserListQuery } from "../../../../models/graphql/query.model"; +import { DataService } from "../../../../services/data/data.service"; +import { Page } from "../../../../models/graphql/filter/page.model"; +import { Sort, SortDirection } from "../../../../models/graphql/filter/sort.model"; +import { Mutations } from "../../../../models/graphql/mutations.model"; +import { Subject, throwError } from "rxjs"; +import { UpdateUserMutationResult } from "../../../../models/graphql/result.model"; +import { ActivatedRoute } from "@angular/router"; +import { Level } from "../../../../models/data/level.model"; +import { Server } from "../../../../models/data/server.model"; + +@Component({ + selector: "app-members", + templateUrl: "./members.component.html", + styleUrls: ["./members.component.scss"] +}) +export class MembersComponent implements OnInit, OnDestroy { + members!: User[]; + levels!: MenuItem[]; + leftServerOptions = [ + { label: this.translate.instant("common.bool_as_string.true"), value: false }, + { label: this.translate.instant("common.bool_as_string.false"), value: true } + ]; + loading = true; + + clonedUsers: { [s: string]: User; } = {}; + isEditingNew: boolean = false; + + newUserTemplate: User = { + id: 0, + discordId: 0, + name: "", + xp: 0, + ontime: 0, + level: undefined, + server: undefined, + + joinedServerCount: 0, + joinedServers: [], + + joinedVoiceChannelCount: 0, + joinedVoiceChannels: [], + + userJoinedGameServerCount: 0, + userJoinedGameServers: [], + + createdAt: "", + modifiedAt: "" + }; + + filterForm!: FormGroup<{ + id: FormControl, + discordId: FormControl, + name: FormControl, + leftServer: FormControl, + level: FormControl + }>; + + filter: UserFilter = {}; + page: Page = { + pageSize: undefined, + pageIndex: undefined + }; + sort: Sort = { + sortColumn: undefined, + sortDirection: undefined + }; + + totalRecords!: number; + private unsubscriber = new Subject(); + private server: Server = {}; + + constructor( + private authService: AuthService, + private spinner: SpinnerService, + private toastService: ToastService, + private confirmDialog: ConfirmationDialogService, + private fb: FormBuilder, + private translate: TranslateService, + private data: DataService, + private route: ActivatedRoute + ) { + } + + ngOnInit(): void { + this.setFilterForm(); + + this.data.getServerFromRoute(this.route).then(server => { + this.server = server; + this.spinner.showSpinner(); + this.data.query(Queries.levelQuery, { + serverId: server.id + }, + (data: Query) => { + return data.servers[0]; + } + ).subscribe(data => { + this.levels = data.levels.map(level => { + return { label: level.name, value: level }; + }); + }); + this.loadNextPage(); + }); + } + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } + + loadNextPage() { + this.spinner.showSpinner(); + this.loading = true; + this.data.query(Queries.usersQuery, { + serverId: this.server.id, filter: this.filter, page: this.page, sort: this.sort + }, + (x: { servers: Server[] }) => { + return x.servers[0]; + } + ).subscribe(data => { + this.totalRecords = data.userCount; + this.members = data.users; + this.spinner.hideSpinner(); + this.loading = false; + }); + } + + setFilterForm() { + this.filterForm = this.fb.group({ + id: new FormControl(null), + discordId: new FormControl(null), + name: [""], + leftServer: new FormControl(null), + level: new FormControl(null) + }); + + this.filterForm.valueChanges.pipe( + takeUntil(this.unsubscriber), + debounceTime(600) + ).subscribe(changes => { + if (changes.id) { + this.filter.id = changes.id; + } else { + this.filter.id = undefined; + } + + if (changes.discordId) { + this.filter.discordId = changes.discordId; + } else { + this.filter.discordId = undefined; + } + + if (changes.name) { + this.filter.name = changes.name; + } else { + this.filter.name = undefined; + } + + if (changes.leftServer !== undefined && changes.leftServer !== null) { + this.filter.leftServer = changes.leftServer; + } else { + this.filter.leftServer = undefined; + } + + if (changes.level) { + this.filter.level = { + id: changes.level.id + }; + } else { + this.filter.level = undefined; + } + + if (this.page.pageSize) + this.page.pageSize = 10; + + if (this.page.pageIndex) + this.page.pageIndex = 0; + + this.loadNextPage(); + }); + } + + nextPage(event: LazyLoadEvent) { + this.page.pageSize = event.rows ?? 0; + if (event.first != null && event.rows != null) + this.page.pageIndex = event.first / event.rows; + this.sort.sortColumn = event.sortField ?? undefined; + this.sort.sortDirection = event.sortOrder === 1 ? SortDirection.ASC : event.sortOrder === -1 ? SortDirection.DESC : SortDirection.ASC; + + this.loadNextPage(); + } + + resetFilters() { + this.filterForm.reset(); + } + + onRowEditInit(table: Table, user: User, index: number) { + this.clonedUsers[index] = { ...user }; + } + + onRowEditSave(table: Table, newUser: User, index: number) { + // const oldUser = this.clonedUsers[index]; + // delete this.clonedUsers[index]; + + // if (JSON.stringify(oldUser) === JSON.stringify(newUser) && !this.isEditingNew) { + // console.log(1, oldUser, newUser, JSON.stringify(oldUser) === JSON.stringify(newUser), !this.isEditingNew); + // return; + // } + + if (this.isEditingNew && JSON.stringify(newUser) === JSON.stringify(this.newUserTemplate)) { + this.isEditingNew = false; + this.members.splice(index, 1); + return; + } + + if (!newUser.id || !newUser.xp && !newUser.level?.id) { + return; + } + + this.spinner.showSpinner(); + this.data.mutation(Mutations.updateUser, { + id: newUser.id, + xp: newUser.xp, + levelId: newUser.level?.id + } + ).pipe(catchError(err => { + this.spinner.hideSpinner(); + this.toastService.error(this.translate.instant("view.server.members.message.user_change_failed"), this.translate.instant("view.server.members.message.user_change_failed_d", { name: newUser.name })); + return throwError(err); + })).subscribe(_ => { + this.spinner.hideSpinner(); + this.toastService.success(this.translate.instant("view.server.members.message.user_changed"), this.translate.instant("view.server.members.message.user_changed_d", { name: newUser.name })); + this.loadNextPage(); + }); + + } + + onRowEditCancel(index: number) { + if (this.isEditingNew) { + this.members.splice(index, 1); + delete this.clonedUsers[index]; + this.isEditingNew = false; + return; + } + + this.members[index] = this.clonedUsers[index]; + delete this.clonedUsers[index]; + } +} diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.html b/kdb-web/src/app/modules/view/server/profile/profile.component.html new file mode 100644 index 00000000..05d3ccc5 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.html @@ -0,0 +1,149 @@ +

+ {{'view.server.profile.header' | translate}} +

+
+
+

+ {{user.name}} +

+
+ +
+
+
+
{{'common.id' | translate}}:
+
{{user.id}}
+
+
+
{{'common.discord_id' | translate}}:
+
{{user.discordId}}
+
+
+ +
+
+
{{'view.server.profile.name' | translate}}:
+
{{user.name}}
+
+
+ +
+
+
{{'view.server.profile.xp' | translate}}:
+
{{user.xp}}
+
+
+ +
+
+
{{'view.server.profile.ontime' | translate}}:
+
{{user.ontime}}
+
+
+ + + + + + + + +
+
+
{{'view.server.profile.level' | translate}}:
+
{{user.level?.name}}
+
+
+ +
+
+
{{'view.server.profile.left_server' | translate}}:
+
{{user.leftServer | bool}}
+
+
+ +
+
+
{{'common.created_at' | translate}}:
+
{{user.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+ +
+
+
{{'common.modified_at' | translate}}:
+
{{user.modifiedAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+ +
+ + +
+
+
+
{{'view.server.profile.joined_voice_channel.time' | translate}}:
+
{{join.time}} {{'general.hours' | translate}}
+
+ +
+
{{'view.server.profile.joined_voice_channel.channel' | translate}}:
+
{{join.channelName}}
+
+ +
+
{{'common.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'common.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+ +
+ +
+
+
+
{{'view.server.profile.joined_game_server.time' | translate}}:
+
{{join.time}} {{'general.hours' | translate}}
+
+ +
+
{{'view.server.profile.joined_game_server.name' | translate}}:
+
{{join.gameServer}}
+
+ +
+
{{'common.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'common.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+
+ + +
+
+
+
{{'common.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'common.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.scss b/kdb-web/src/app/modules/view/server/profile/profile.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.spec.ts b/kdb-web/src/app/modules/view/server/profile/profile.component.spec.ts new file mode 100644 index 00000000..246039d7 --- /dev/null +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ProfileComponent } from './profile.component'; + +describe('ProfileComponent', () => { + let component: ProfileComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ProfileComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.ts b/kdb-web/src/app/modules/view/server/profile/profile.component.ts new file mode 100644 index 00000000..77531f2d --- /dev/null +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.ts @@ -0,0 +1,82 @@ +import { Component, OnDestroy, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { Queries } from "../../../../models/graphql/queries.model"; +import { UserListQuery } from "../../../../models/graphql/query.model"; +import { SpinnerService } from "../../../../services/spinner/spinner.service"; +import { DataService } from "../../../../services/data/data.service"; +import { User } from "../../../../models/data/user.model"; +import { UserDTO } from "../../../../models/auth/auth-user.dto"; +import { AuthService } from "src/app/services/auth/auth.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { TranslateService } from "@ngx-translate/core"; +import { Server } from "../../../../models/data/server.model"; +import { Subject } from "rxjs"; +import { takeUntil } from "rxjs/operators"; + +@Component({ + selector: "app-profile", + templateUrl: "./profile.component.html", + styleUrls: ["./profile.component.scss"] +}) +export class ProfileComponent implements OnInit, OnDestroy { + + user: User = { createdAt: "", modifiedAt: "" }; + private server: Server = {}; + + private unsubscriber = new Subject(); + + constructor( + private route: ActivatedRoute, + private router: Router, + private spinner: SpinnerService, + private data: DataService, + private auth: AuthService, + private toast: ToastService, + private translate: TranslateService + ) { + } + + public ngOnInit(): void { + this.route.params.pipe(takeUntil(this.unsubscriber)).subscribe(params => { + this.data.getServerFromRoute(this.route).then(async (server) => { + if (!params["memberId"] || params["memberId"] == "undefined") { + await this.router.navigate([`/server/${server.id}`]); + return; + } + this.server = server; + + let authUser = await this.auth.getLoggedInUser(); + this.spinner.showSpinner(); + let user: UserDTO | null = authUser?.users?.find(u => u.server == server.id) ?? null; + if (!user || user?.id != params["memberId"] && !user?.isModerator) { + this.toast.error(this.translate.instant("view.server.profile.permission_denied"), this.translate.instant("view.server.profile.permission_denied_d")); + this.spinner.hideSpinner(); + await this.router.navigate(["/server", server.id]); + return; + } + + this.data.query(Queries.usersQuery, { + serverId: this.server.id, + filter: { + id: params["memberId"] + } + }, + (x: { servers: Server[] }) => { + return x.servers[0]; + } + ).subscribe(users => { + if (!users.users[0]) { + this.router.navigate([`/server/${server.id}`]); + } + this.user = users.users[0]; + this.spinner.hideSpinner(); + }); + }); + }); + } + + public ngOnDestroy(): void { + this.unsubscriber.next(); + this.unsubscriber.complete(); + } +} diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.html b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.html new file mode 100644 index 00000000..11fca14a --- /dev/null +++ b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.html @@ -0,0 +1,34 @@ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.scss b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.spec.ts b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.spec.ts new file mode 100644 index 00000000..3002a16e --- /dev/null +++ b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ClientComponent } from './client.component'; + +describe('ClientComponent', () => { + let component: ClientComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ ClientComponent ] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ClientComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.ts b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.ts new file mode 100644 index 00000000..90462b4b --- /dev/null +++ b/kdb-web/src/app/modules/view/server/server-dashboard/components/client/client.component.ts @@ -0,0 +1,25 @@ +import {Component, Input} from '@angular/core'; +import {Client} from "../../../../../../models/data/client.model"; + +@Component({ + selector: 'app-client', + templateUrl: './client.component.html', + styleUrls: ['./client.component.scss'] +}) +export class ClientComponent { + + @Input() client: Client = { + createdAt: "", modifiedAt: "", + deletedMessageCount: 0, + discordId: "", + id: 0, + movedUsersCount: 0, + name: "", + receivedCommandCount: 0, + receivedMessageCount: 0, + sentMessageCount: 0, + server: undefined + }; + + +} diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.html b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.html index 1fbf61d3..36005f1e 100644 --- a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.html +++ b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.html @@ -1,36 +1,42 @@

- {{'view.dashboard.header' | translate}} + {{'view.server.dashboard.header' | translate}}

-
-

- - {{'view.dashboard.server.header' | translate}} -

-
+
+

+ + {{'view.dashboard.server.header' | translate}} +

+
-
-
-
-
- +
+
+
+
+ -
-

- {{server.name}} -

+
+

+ {{server.name}} +

-
- - {{server.memberCount}} - {{'view.dashboard.server.member_count' | translate}} -
-
- -
+
+ + {{server.userCount}} + {{'view.dashboard.server.member_count' | translate}}
+ +
+ + +
+
+
+
-
\ No newline at end of file +
+
diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts index 158c7711..642e0f7c 100644 --- a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts +++ b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts @@ -1,38 +1,40 @@ -import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; -import { ServerDTO } from 'src/app/models/discord/server.dto'; -import { DataService } from 'src/app/services/data/data.service'; -import { ServerService } from 'src/app/services/data/server.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; +import { Server } from "src/app/models/data/server.model"; +import { DataService } from "src/app/services/data/data.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { SidebarService } from "../../../../services/sidebar/sidebar.service"; @Component({ - selector: 'app-server-dashboard', - templateUrl: './server-dashboard.component.html', - styleUrls: ['./server-dashboard.component.scss'] + selector: "app-server-dashboard", + templateUrl: "./server-dashboard.component.html", + styleUrls: ["./server-dashboard.component.scss"] }) export class ServerDashboardComponent implements OnInit { id!: number; - server!: ServerDTO; + server!: Server; constructor( private route: ActivatedRoute, private router: Router, private data: DataService, private spinner: SpinnerService, - private serverService: ServerService - ) { } + private sidebar: SidebarService + ) { + } ngOnInit(): void { - this.spinner.showSpinner(); - if (!this.serverService.server$.value) { - this.spinner.hideSpinner(); - this.router.navigate(['/dashboard']); - return; - } + this.data.getServerFromRoute(this.route).then(server => { + this.server = server; + }); - this.server = this.serverService.server$.value; - this.spinner.hideSpinner(); + this.sidebar.server$.subscribe(server => { + if (!server) { + return; + } + this.server = server; + }); } } diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts index d7e96c59..147c40ea 100644 --- a/kdb-web/src/app/modules/view/server/server-routing.module.ts +++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts @@ -1,13 +1,20 @@ import { NgModule } from "@angular/core"; import { RouterModule, Routes } from "@angular/router"; import { ServerDashboardComponent } from "./server-dashboard/server-dashboard.component"; +import { ProfileComponent } from "./profile/profile.component"; +import { MembersComponent } from "./members/members.component"; const routes: Routes = [ - { path: '', component: ServerDashboardComponent }, + { path: "", component: ServerDashboardComponent }, + { path: "members", component: MembersComponent }, + { path: "members/:memberId", component: ProfileComponent }, + { path: "auto-roles", loadChildren: () => import("./auto-role/auto-role.module").then(m => m.AutoRoleModule) }, + { path: "levels", loadChildren: () => import("./levels/levels.module").then(m => m.LevelsModule) } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) -export class ServerRoutingModule { } +export class ServerRoutingModule { +} diff --git a/kdb-web/src/app/modules/view/server/server.module.ts b/kdb-web/src/app/modules/view/server/server.module.ts index 824e2412..1e4b2a8a 100644 --- a/kdb-web/src/app/modules/view/server/server.module.ts +++ b/kdb-web/src/app/modules/view/server/server.module.ts @@ -3,12 +3,18 @@ import { CommonModule } from '@angular/common'; import { ServerDashboardComponent } from './server-dashboard/server-dashboard.component'; import { ServerRoutingModule } from './server-routing.module'; import { SharedModule } from '../../shared/shared.module'; +import { ProfileComponent } from './profile/profile.component'; +import { MembersComponent } from './members/members.component'; +import { ClientComponent } from './server-dashboard/components/client/client.component'; @NgModule({ declarations: [ - ServerDashboardComponent + ServerDashboardComponent, + ProfileComponent, + MembersComponent, + ClientComponent ], imports: [ CommonModule, diff --git a/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.html b/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.html index 716df73c..95220ca4 100644 --- a/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.html +++ b/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.html @@ -17,10 +17,10 @@
-
-
{{'view.user_settings.e_mail_already_exists' | translate}}
+
{{'view.user_settings.email_already_exists' | translate}}
@@ -38,4 +38,4 @@
- \ No newline at end of file + diff --git a/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.ts b/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.ts index b4e8d633..40523863 100644 --- a/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.ts +++ b/kdb-web/src/app/modules/view/user-settings/components/user-settings/user-settings.component.ts @@ -1,22 +1,23 @@ -import { Component, OnInit } from '@angular/core'; -import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; -import { Router } from '@angular/router'; -import { TranslateService } from '@ngx-translate/core'; -import { catchError } from 'rxjs/operators'; -import { AuthErrorMessages } from 'src/app/models/auth/auth-error-messages.enum'; -import { AuthUserDTO } from 'src/app/models/auth/auth-user.dto'; -import { UpdateUserDTO } from 'src/app/models/auth/update-user.dto'; -import { ErrorDTO } from 'src/app/models/error/error-dto'; -import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; -import { AuthService } from 'src/app/services/auth/auth.service'; -import { SpinnerService } from 'src/app/services/spinner/spinner.service'; -import { ThemeService } from 'src/app/services/theme/theme.service'; -import { ToastService } from 'src/app/services/toast/toast.service'; +import { Component, OnInit } from "@angular/core"; +import { FormBuilder, FormControl, FormGroup, Validators } from "@angular/forms"; +import { Router } from "@angular/router"; +import { TranslateService } from "@ngx-translate/core"; +import { catchError } from "rxjs/operators"; +import { AuthErrorMessages } from "src/app/models/auth/auth-error-messages.enum"; +import { AuthUserDTO } from "src/app/models/auth/auth-user.dto"; +import { UpdateUserDTO } from "src/app/models/auth/update-user.dto"; +import { ErrorDTO } from "src/app/models/error/error-dto"; +import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; +import { AuthService } from "src/app/services/auth/auth.service"; +import { SpinnerService } from "src/app/services/spinner/spinner.service"; +import { ThemeService } from "src/app/services/theme/theme.service"; +import { ToastService } from "src/app/services/toast/toast.service"; +import { throwError } from "rxjs"; @Component({ - selector: 'app-user-settings', - templateUrl: './user-settings.component.html', - styleUrls: ['./user-settings.component.scss'] + selector: "app-user-settings", + templateUrl: "./user-settings.component.html", + styleUrls: ["./user-settings.component.scss"] }) export class UserSettingsComponent implements OnInit { settingsForm!: FormGroup<{ @@ -42,7 +43,8 @@ export class UserSettingsComponent implements OnInit { private toastService: ToastService, private themeService: ThemeService, private translaste: TranslateService - ) { } + ) { + } ngOnInit(): void { this.initForms(); @@ -51,10 +53,10 @@ export class UserSettingsComponent implements OnInit { initForms(): void { this.settingsForm = this.formBuilder.group({ - firstName: ['', [Validators.required]], - lastName: ['', [Validators.required]], - email: ['', [Validators.required, Validators.email]], - password: ['', [Validators.required, Validators.minLength(8)]] + firstName: ["", [Validators.required]], + lastName: ["", [Validators.required]], + email: ["", [Validators.required, Validators.email]], + password: ["", [Validators.required, Validators.minLength(8)]] }); } @@ -73,14 +75,14 @@ export class UserSettingsComponent implements OnInit { } this.authService.findUserByEMail(mail) - .pipe(catchError(err => { - this.toastService.error(this.translaste.instant('view.user_settings.message.user_not_found'), this.translaste.instant('view.user_settings.message.user_not_found_d')); + .pipe(catchError(error => { + this.toastService.error(this.translaste.instant("view.user_settings.message.user_not_found"), this.translaste.instant("view.user_settings.message.user_not_found_d")); this.authService.logout(); - throw err; + return throwError(() => error); })) .subscribe(user => { if (!user) { - this.toastService.error(this.translaste.instant('view.user_settings.message.user_not_found'), this.translaste.instant('view.user_settings.message.user_not_found_d')); + this.toastService.error(this.translaste.instant("view.user_settings.message.user_not_found"), this.translaste.instant("view.user_settings.message.user_not_found_d")); this.authService.logout(); } this.authUser = user; @@ -122,27 +124,27 @@ export class UserSettingsComponent implements OnInit { } } this.spinnerService.hideSpinner(); - this.toastService.error(this.translaste.instant('view.user_settings.message.error'), this.translaste.instant('view.user_settings.message.could_not_change_settings')); - throw error; + this.toastService.error(this.translaste.instant("view.user_settings.message.error"), this.translaste.instant("view.user_settings.message.could_not_change_settings")); + return throwError(() => error); })) .subscribe(resp => { updateUserDTO.newAuthUserDTO.password = updateUserDTO.authUserDTO.password; this.authService.login(updateUserDTO.newAuthUserDTO) - .pipe(catchError(err => { - this.router.navigate(['/auth/login']); - throw err; + .pipe(catchError(error => { + this.router.navigate(["/auth/login"]); + return throwError(() => error); })) .subscribe(token => { this.spinnerService.hideSpinner(); if (token) { - this.toastService.success(this.translaste.instant('view.user_settings.message.success'), this.translaste.instant('view.user_settings.message.changed_settings')); + this.toastService.success(this.translaste.instant("view.user_settings.message.success"), this.translaste.instant("view.user_settings.message.changed_settings")); this.authService.saveToken(token); this.themeService.loadTheme(); this.themeService.loadMenu(); this.load(); return true; } - this.router.navigate(['/auth/login']); + this.router.navigate(["/auth/login"]); return false; }); }); diff --git a/kdb-web/src/app/services/auth/auth.service.ts b/kdb-web/src/app/services/auth/auth.service.ts index a1174ea5..f51db323 100644 --- a/kdb-web/src/app/services/auth/auth.service.ts +++ b/kdb-web/src/app/services/auth/auth.service.ts @@ -2,7 +2,7 @@ import { HttpClient, HttpHeaders } from "@angular/common/http"; import { Injectable } from "@angular/core"; import { Router } from "@angular/router"; import { JwtHelperService } from "@auth0/angular-jwt"; -import { firstValueFrom, Observable, Subject, Subscription } from "rxjs"; +import { BehaviorSubject, firstValueFrom, Observable, Subject, Subscription, throwError } from "rxjs"; import { catchError } from "rxjs/operators"; import { AdminUpdateUserDTO } from "src/app/models/auth/admin-update-user.dto"; import { AuthRoles } from "src/app/models/auth/auth-roles.enum"; @@ -19,12 +19,11 @@ import { DiscordAuthURL } from "../../models/auth/discord-auth-url.dto"; import { OAuthDTO } from "../../models/auth/oauth.dto"; @Injectable({ - providedIn: 'root' + providedIn: "root" }) export class AuthService { - private isLoggedIn!: boolean; - isLoggedIn$ = new Subject(); + isLoggedIn$ = new BehaviorSubject(false); constructor( private appsettings: SettingsService, @@ -33,23 +32,21 @@ export class AuthService { private jwtHelper: JwtHelperService, private spinnerService: SpinnerService ) { - this.isLoggedIn$.subscribe(value => { - this.isLoggedIn = value; - }); } /* data requests */ getAllUsers(): Observable> { return this.http.get>(`${this.appsettings.getApiURL()}/api/auth/users`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } + getFilteredUsers(selectCriterions: AuthUserSelectCriterion): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/users/get/filtered`, selectCriterions, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -57,7 +54,7 @@ export class AuthService { getUserByEMail(email: string): Observable { return this.http.get(`${this.appsettings.getApiURL()}/api/auth/users/get/${email}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -65,7 +62,7 @@ export class AuthService { findUserByEMail(email: string): Observable { return this.http.get(`${this.appsettings.getApiURL()}/api/auth/users/find/${email}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -74,7 +71,7 @@ export class AuthService { register(user: AuthUserDTO): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/register`, user, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -82,7 +79,7 @@ export class AuthService { confirmEMail(id: string): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/register-by-id/${id}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -90,7 +87,7 @@ export class AuthService { login(user: AuthUserDTO): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/login`, user, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -98,7 +95,7 @@ export class AuthService { verifyLogin(): Observable { return this.http.get(`${this.appsettings.getApiURL()}/api/auth/verify-login`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -106,7 +103,7 @@ export class AuthService { forgotPassword(email: string): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/forgot-password/${email}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -114,7 +111,7 @@ export class AuthService { getEMailFromforgotPasswordId(id: string): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/confirm-forgot-password/${id}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -122,7 +119,7 @@ export class AuthService { resetPassword(resetPasswordDTO: ResetPasswordDTO): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/reset-password`, resetPasswordDTO, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -130,7 +127,7 @@ export class AuthService { updateUser(updateUserDTO: UpdateUserDTO): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/update-user`, updateUserDTO, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -138,7 +135,7 @@ export class AuthService { updateUserAsAdmin(updateUserDTO: AdminUpdateUserDTO): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/update-user-as-admin`, updateUserDTO, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -146,7 +143,7 @@ export class AuthService { refresh(token: TokenDTO): Observable { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/refresh`, token, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -154,7 +151,7 @@ export class AuthService { deleteUserByMail(mail: string) { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/delete-user-by-mail/${mail}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -163,15 +160,7 @@ export class AuthService { getDiscordAuthURL() { return this.http.get(`${this.appsettings.getApiURL()}/api/auth/discord/get-url`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' - }) - }); - } - - discordCreateUser(code: string, state: string) { - return this.http.get(`${this.appsettings.getApiURL()}/api/auth/discord/create-user?code=${code}&state=${state}`, { - headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -179,7 +168,7 @@ export class AuthService { discordLogin(code: string, state: string): Observable { return this.http.get(`${this.appsettings.getApiURL()}/api/auth/discord/login?code=${code}&state=${state}`, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -188,7 +177,7 @@ export class AuthService { discordRegister(oAuthDTO: OAuthDTO) { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/discord/register`, oAuthDTO, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }); } @@ -203,21 +192,25 @@ export class AuthService { /* utils */ saveToken(token: TokenDTO): void { - localStorage.setItem('jwt', token.token); - localStorage.setItem('rjwt', token.refreshToken); - if (this.router.url.startsWith('/auth')) { - this.router.navigate(['/dashboard']); + localStorage.setItem("jwt", token.token); + localStorage.setItem("rjwt", token.refreshToken); + if (this.router.url.startsWith("/auth")) { + this.router.navigate(["/dashboard"]); } } getToken(): TokenDTO { return { - token: localStorage.getItem('jwt') ?? '', - refreshToken: localStorage.getItem('rjwt') ?? '' + token: localStorage.getItem("jwt") ?? "", + refreshToken: localStorage.getItem("rjwt") ?? "" }; } - getDecodedToken(): { [key: string]: any } { + getDecodedToken(token: TokenDTO | undefined = undefined): { [key: string]: any } | null { + if (token) { + return this.jwtHelper.decodeToken(token.token); + } + return this.jwtHelper.decodeToken(this.getToken().token); } @@ -227,26 +220,40 @@ export class AuthService { if (token && token.token && token.refreshToken) { return this.http.post(`${this.appsettings.getApiURL()}/api/auth/revoke`, token, { headers: new HttpHeaders({ - 'Content-Type': 'application/json' + "Content-Type": "application/json" }) }).pipe(catchError((error: any) => { error.error = null; this.isLoggedIn$.next(false); - localStorage.removeItem('rjwt'); - this.router.navigate(['/auth/login']); - throw error; + localStorage.removeItem("rjwt"); + this.router.navigate(["/auth/login"]); + return throwError(() => error); })).subscribe(() => { this.isLoggedIn$.next(false); - localStorage.removeItem('jwt'); - localStorage.removeItem('rjwt'); - this.router.navigate(['/auth/login']); + localStorage.removeItem("jwt"); + localStorage.removeItem("rjwt"); + this.router.navigate(["/auth/login"]); }); } this.isLoggedIn$.next(false); - localStorage.removeItem('rjwt'); - this.router.navigate(['/auth/login']); + localStorage.removeItem("rjwt"); + this.router.navigate(["/auth/login"]); - return null + return null; + } + + async getLoggedInUser(): Promise { + if (!await this.isUserLoggedInAsync()) { + return null; + } + const token = this.getDecodedToken(); + if (!token) return null; + + try { + return await firstValueFrom(this.findUserByEMail(token["email"])); + } catch (error: unknown) { + return null; + } } async isUserLoggedInAsync(): Promise { @@ -268,16 +275,12 @@ export class AuthService { return false; } - if (this.isLoggedIn) { - this.spinnerService.showSpinner(); - - const resfreshedToken = await firstValueFrom(await this.refresh(token)); - - this.spinnerService.hideSpinner(); - if (resfreshedToken) { - this.saveToken(resfreshedToken); - return true; - } + this.spinnerService.showSpinner(); + const resfreshedToken = await firstValueFrom(await this.refresh(token)); + this.spinnerService.hideSpinner(); + if (resfreshedToken) { + this.saveToken(resfreshedToken); + return true; } return false; @@ -288,13 +291,14 @@ export class AuthService { return false; } const token = this.getDecodedToken(); - return AuthRoles[token['role']] === AuthRoles[role]; + if (!token) return false; + return AuthRoles[token["role"]] === AuthRoles[role]; } - getEMailFromDecodedToken(token: { [key: string]: any }): string | null { + getEMailFromDecodedToken(token: { [key: string]: any } | null): string | null { if (!token) { return null; } - return token['email']; + return token["email"]; } } diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts index 6b1a0f76..54d13057 100644 --- a/kdb-web/src/app/services/data/data.service.ts +++ b/kdb-web/src/app/services/data/data.service.ts @@ -1,53 +1,82 @@ -import { HttpClient, HttpHeaders } from '@angular/common/http'; -import { Injectable } from '@angular/core'; -import { Observable } from 'rxjs'; -import { ServerDTO } from 'src/app/models/discord/server.dto'; -import { GetFilteredServersResultDTO } from 'src/app/models/selection/server/get-filtered-servers-result.dto'; -import { ServerSelectCriterion } from 'src/app/models/selection/server/server-select-criterion.dto'; -import { SettingsService } from '../settings/settings.service'; +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { SettingsService } from "../settings/settings.service"; +import { map, Observable } from "rxjs"; +import { Variables } from "../../models/graphql/variables.model"; +import { ActivatedRoute, Router } from "@angular/router"; +import { Server } from "../../models/data/server.model"; +import { Queries } from "../../models/graphql/queries.model"; +import { Query } from "../../models/graphql/query.model"; +import { SidebarService } from "../sidebar/sidebar.service"; +import { SpinnerService } from "../spinner/spinner.service"; +import { GraphQLResult } from "../../models/graphql/result.model"; @Injectable({ - providedIn: 'root' + providedIn: "root" }) export class DataService { constructor( private appsettings: SettingsService, private http: HttpClient, - ) { } - - - - /* data requests */ - getAllServers(): Observable> { - return this.http.get>(`${this.appsettings.getApiURL()}/api/discord/server/servers`, { - headers: new HttpHeaders({ - 'Content-Type': 'application/json' - }) - }); - } - - getAllServersByUser(): Observable> { - return this.http.get>(`${this.appsettings.getApiURL()}/api/discord/server/servers-by-user`, { - headers: new HttpHeaders({ - 'Content-Type': 'application/json' - }) - }); + private sidebar: SidebarService, + private spinner: SpinnerService, + private router: Router + ) { } - getFilteredServers(selectCriterions: ServerSelectCriterion): Observable { - return this.http.post(`${this.appsettings.getApiURL()}/api/discord/server/get/filtered`, selectCriterions, { - headers: new HttpHeaders({ - 'Content-Type': 'application/json' - }) + public getServerFromRoute(route: ActivatedRoute): Promise { + return new Promise((resolve, reject) => { + this.spinner.showSpinner(); + if (!route.snapshot.params["serverId"] || route.snapshot.params["serverId"] == "undefined") { + this.spinner.hideSpinner(); + this.router.navigate(["/dashboard"]); + reject(); + } + + this.query(Queries.serversQuery, { + filter: { id: route.snapshot.params["serverId"] } + }, + function(data: Query) { + return data.servers.length > 0 ? data.servers[0] : null; + } + ).subscribe(server => { + this.sidebar.setServer(server); + this.spinner.hideSpinner(); + resolve(server); + }); }); + } - - getServerByID(id: number): Observable { - return this.http.get(`${this.appsettings.getApiURL()}/api/discord/server/get/${id}`, { - headers: new HttpHeaders({ - 'Content-Type': 'application/json' + + public query(query: string, variables?: Variables, f?: Function): Observable { + return this.http + .post(`${this.appsettings.getApiURL()}/api/graphql`, { + query: query, + variables: variables }) - }); + .pipe(map(d => { + if (d.errors && d.errors.length > 0) { + throw new Error(d.errors.map((x: { message: String }) => x.message).toString()); + } + return d.data; + })) + .pipe(map((d) => f ? f(d) : d)); } + + public mutation(query: string, variables?: object, f?: Function): Observable { + return this.http + .post(`${this.appsettings.getApiURL()}/api/graphql`, { + query: query, + variables: variables + }) + .pipe(map(d => { + if (d.errors && d.errors.length > 0) { + throw new Error(d.errors.toString()); + } + return d.data; + })) + .pipe(map((d) => f ? f(d) : d)); + } + } diff --git a/kdb-web/src/app/services/data/server.service.ts b/kdb-web/src/app/services/data/server.service.ts deleted file mode 100644 index 05d8673d..00000000 --- a/kdb-web/src/app/services/data/server.service.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject, Subject } from 'rxjs'; -import { ServerDTO } from 'src/app/models/discord/server.dto'; - -@Injectable({ - providedIn: 'root' -}) -export class ServerService { - - private server!: ServerDTO; - server$ = new BehaviorSubject(null); - - constructor() { - this.server$.subscribe(server => { - if (!server) { - return; - } - this.server = server; - }); - } - - -} diff --git a/kdb-web/src/app/services/error-handler/error-handler.service.ts b/kdb-web/src/app/services/error-handler/error-handler.service.ts index b2ed4f6d..89786ef2 100644 --- a/kdb-web/src/app/services/error-handler/error-handler.service.ts +++ b/kdb-web/src/app/services/error-handler/error-handler.service.ts @@ -1,16 +1,17 @@ -import { HttpErrorResponse } from '@angular/common/http'; -import { ErrorHandler, Injectable, Injector } from '@angular/core'; -import { Observable, throwError } from 'rxjs'; -import { ErrorDTO } from 'src/app/models/error/error-dto'; -import { ServiceErrorCode } from 'src/app/models/error/service-error-code.enum'; -import { AuthService } from '../auth/auth.service'; -import { ToastService } from '../toast/toast.service'; +import { HttpErrorResponse } from "@angular/common/http"; +import { ErrorHandler, Injectable } from "@angular/core"; +import { Observable, throwError } from "rxjs"; +import { ErrorDTO } from "src/app/models/error/error-dto"; +import { ServiceErrorCode } from "src/app/models/error/service-error-code.enum"; +import { AuthService } from "../auth/auth.service"; +import { ToastService } from "../toast/toast.service"; @Injectable() export class ErrorHandlerService implements ErrorHandler { constructor( - private injector: Injector + private auth: AuthService, + private toast: ToastService, ) { } handleError(error: HttpErrorResponse): Observable { @@ -20,7 +21,7 @@ export class ErrorHandlerService implements ErrorHandler { const errorDto: ErrorDTO = error.error; if (errorDto.errorCode === ServiceErrorCode.Unauthorized) { - this.injector.get(AuthService).logout(); + this.auth.logout(); return throwError(() => error); } @@ -34,11 +35,13 @@ export class ErrorHandlerService implements ErrorHandler { message = error.message; } - this.injector.get(ToastService).error(header, message); + this.toast.error(header, message); + } else { + console.error(error.message); } if (error.status === 401) { - this.injector.get(AuthService).logout(); + this.auth.logout(); } return throwError(() => error); } diff --git a/kdb-web/src/app/services/settings/settings.service.ts b/kdb-web/src/app/services/settings/settings.service.ts index f594861c..81afc135 100644 --- a/kdb-web/src/app/services/settings/settings.service.ts +++ b/kdb-web/src/app/services/settings/settings.service.ts @@ -5,7 +5,6 @@ import { catchError } from "rxjs/operators"; import { Appsettings } from "src/app/models/config/appsettings"; import { SoftwareVersion } from "src/app/models/config/software-version"; import { Theme } from "src/app/models/view/theme"; -import { environment } from "../../../environments/environment"; @Injectable({ providedIn: 'root' @@ -31,11 +30,27 @@ export class SettingsService { } public getApiURL(): string { - if (!environment || !environment.apiURL) { - console.error('ApiURL is not set!'); - return ''; + if (!this.appsettings || !this.appsettings.ApiURL) { + console.error('ApiUrl is not set!'); + return ""; } - return environment.apiURL; + return this.appsettings.ApiURL; + } + + public getPrivacyURL(): string { + if (!this.appsettings || !this.appsettings.PrivacyURL) { + console.error('PrivacyURL is not set!'); + return ""; + } + return this.appsettings.PrivacyURL; + } + + public getImprintURL(): string { + if (!this.appsettings || !this.appsettings.ImprintURL) { + console.error('ImprintURL is not set!'); + return ""; + } + return this.appsettings.ImprintURL; } public getWebVersion(): SoftwareVersion | null { diff --git a/kdb-web/src/app/services/data/server.service.spec.ts b/kdb-web/src/app/services/sidebar/sidebar.service.spec.ts similarity index 54% rename from kdb-web/src/app/services/data/server.service.spec.ts rename to kdb-web/src/app/services/sidebar/sidebar.service.spec.ts index 906c1601..63b8b69f 100644 --- a/kdb-web/src/app/services/data/server.service.spec.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.spec.ts @@ -1,13 +1,13 @@ import { TestBed } from '@angular/core/testing'; -import { ServerService } from './server.service'; +import { SidebarService } from './sidebar.service'; -describe('ServerService', () => { - let service: ServerService; +describe('SidebarService', () => { + let service: SidebarService; beforeEach(() => { TestBed.configureTestingModule({}); - service = TestBed.inject(ServerService); + service = TestBed.inject(SidebarService); }); it('should be created', () => { diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts new file mode 100644 index 00000000..91da7e92 --- /dev/null +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -0,0 +1,157 @@ +import { Injectable } from "@angular/core"; +import { MenuItem } from "primeng/api"; +import { BehaviorSubject } from "rxjs"; +import { AuthRoles } from "../../models/auth/auth-roles.enum"; +import { AuthService } from "../auth/auth.service"; +import { LangChangeEvent, TranslateService } from "@ngx-translate/core"; +import { NavigationEnd, Router } from "@angular/router"; +import { ThemeService } from "../theme/theme.service"; +import { Server } from "../../models/data/server.model"; +import { UserDTO } from "../../models/auth/auth-user.dto"; + +@Injectable({ + providedIn: "root" +}) +export class SidebarService { + + isSidebarOpen: boolean = true; + menuItems$ = new BehaviorSubject(new Array()); + server$ = new BehaviorSubject(null); + + dashboard: MenuItem = {}; + serverDashboard: MenuItem = {}; + serverProfile: MenuItem = {}; + serverMembers: MenuItem = {}; + serverAutoRoles: MenuItem = {}; + serverLevels: MenuItem = {}; + serverMenu: MenuItem = {}; + adminConfig: MenuItem = {}; + adminUsers: MenuItem = {}; + adminMenu: MenuItem = {}; + + constructor( + private themeService: ThemeService, + private authService: AuthService, + private translateService: TranslateService, + private router: Router + ) { + this.themeService.isSidebarOpen$.subscribe(value => { + this.isSidebarOpen = value; + this.setMenu(); + }); + + this.translateService.onLangChange.subscribe(_ => { + this.setMenu(true); + }); + + this.router.events.subscribe(event => { + if (!(event instanceof NavigationEnd)) { + return; + } + if (!event.url.startsWith("/server/") && this.server$.value) { + this.setServer(null); + } + }); + } + + setServer(server: Server | null) { + if (server?.id != this.server$.value?.id) { + this.server$.next(server); + if (server) { + this.setMenu(true); + } else { + this.setMenu(false); + } + } + } + + async buildMenu(user: UserDTO | null, hasPermission: boolean) { + this.dashboard = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", + icon: "pi pi-th-large", + routerLink: "dashboard" + }; + this.serverDashboard = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.dashboard") : "", + icon: "pi pi-th-large", + routerLink: `server/${this.server$.value?.id}` + }; + this.serverProfile = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.profile") : "", + icon: "pi pi-id-card", + routerLink: `server/${this.server$.value?.id}/members/${user?.id}` + }; + this.serverMembers = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.members") : "", + icon: "pi pi-users", + visible: true, + routerLink: `server/${this.server$.value?.id}/members` + }; + + this.serverAutoRoles = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.auto_roles") : "", + icon: "pi pi-sitemap", + visible: true, + routerLink: `server/${this.server$.value?.id}/auto-roles` + }; + + this.serverLevels = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.levels") : "", + icon: "pi pi-book", + visible: true, + routerLink: `server/${this.server$.value?.id}/levels` + }; + + this.serverMenu = { + label: this.isSidebarOpen ? this.server$.value?.name : "", + icon: "pi pi-server", + visible: false, + expanded: true, + items: [this.serverDashboard, this.serverProfile, this.serverMembers, this.serverAutoRoles, this.serverLevels] + }; + this.adminConfig = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.config") : "", + icon: "pi pi-cog", + routerLink: "/admin/settings" + }; + this.adminUsers = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.auth_user_list") : "", + icon: "pi pi-user-edit", + routerLink: "/admin/users" + }; + this.adminMenu = { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.administration") : "", + icon: "pi pi-cog", + visible: hasPermission, + expanded: true, + items: [this.adminConfig, this.adminUsers] + }; + } + + setMenu(build: boolean = false) { + this.authService.hasUserPermission(AuthRoles.Admin).then(async hasPermission => { + let authUser = await this.authService.getLoggedInUser(); + let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server$.value?.id) ?? null; + + if (build || this.menuItems$.value.length == 0) { + await this.buildMenu(user, hasPermission); + } + + if (this.server$.value) { + this.serverMenu.visible = true; + this.serverMembers.visible = !!user?.isModerator; + this.serverAutoRoles.visible = !!user?.isModerator; + this.serverLevels.visible = !!user?.isModerator; + } else { + this.serverMenu.visible = false; + } + + let menuItems: MenuItem[] = [ + this.dashboard, + this.serverMenu, + this.adminMenu + ]; + this.menuItems$.next(menuItems); + }); + } +} diff --git a/kdb-web/src/app/services/spinner/spinner.service.ts b/kdb-web/src/app/services/spinner/spinner.service.ts index 0d3aab97..0582688c 100644 --- a/kdb-web/src/app/services/spinner/spinner.service.ts +++ b/kdb-web/src/app/services/spinner/spinner.service.ts @@ -1,22 +1,23 @@ import { Injectable } from '@angular/core'; +import { BehaviorSubject } from "rxjs"; @Injectable({ providedIn: 'root' }) export class SpinnerService { - showSpinnerState = false; + showSpinnerState$ = new BehaviorSubject(false); constructor() { } showSpinner() { - this.showSpinnerState = true; + this.showSpinnerState$.next(true); } hideSpinner() { - this.showSpinnerState = false; + this.showSpinnerState$.next(false); } toggleSpinner() { - this.showSpinnerState = !this.showSpinnerState; + this.showSpinnerState$.next(!this.showSpinnerState$.value); } } diff --git a/kdb-web/src/app/services/theme/theme.service.ts b/kdb-web/src/app/services/theme/theme.service.ts index 6abe0955..dacfce99 100644 --- a/kdb-web/src/app/services/theme/theme.service.ts +++ b/kdb-web/src/app/services/theme/theme.service.ts @@ -1,23 +1,21 @@ -import { Injectable } from '@angular/core'; -import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; -import { Subject } from 'rxjs'; -import { Themes } from 'src/app/models/view/themes.enum'; -import { AuthService } from '../auth/auth.service'; +import { Injectable } from "@angular/core"; +import { BehaviorSubject } from "rxjs"; +import { Themes } from "src/app/models/view/themes.enum"; +import { AuthService } from "../auth/auth.service"; @Injectable({ - providedIn: 'root' + providedIn: "root" }) export class ThemeService { themeName: string = Themes.Default; - sidebarWidth = '150px'; + sidebarWidth = "150px"; isSidebarOpen = false; - hasLangChanged = false; - themeName$ = new Subject(); - isSidebarOpen$ = new Subject(); - sidebarWidth$ = new Subject(); + themeName$ = new BehaviorSubject(Themes.Default); + isSidebarOpen$ = new BehaviorSubject(true); + sidebarWidth$ = new BehaviorSubject("175px"); constructor( private authService: AuthService @@ -27,7 +25,7 @@ export class ThemeService { }); this.isSidebarOpen$.subscribe(isSidebarOpen => { this.isSidebarOpen = isSidebarOpen; - this.sidebarWidth$.next(isSidebarOpen ? '175px' : '75px'); + this.sidebarWidth$.next(isSidebarOpen ? "175px" : "75px"); }); this.sidebarWidth$.subscribe(sidebarWidth => { this.sidebarWidth = sidebarWidth; @@ -65,20 +63,18 @@ export class ThemeService { return; } - this.authService.isUserLoggedInAsync().then(result => { - if (!result) { - localStorage.setItem(`default_themeName`, Themes.Default); - this.themeName$.next(Themes.Default); - } + if (!this.authService.isLoggedIn$.value) { + localStorage.setItem(`default_themeName`, Themes.Default); + this.themeName$.next(Themes.Default); + } - const token = this.authService.getDecodedToken(); - const mail = this.authService.getEMailFromDecodedToken(token); - if (mail) { - localStorage.setItem(`${mail}_themeName`, name); - } - localStorage.setItem(`default_themeName`, name); - this.themeName$.next(name); - }); + const token = this.authService.getDecodedToken(); + const mail = this.authService.getEMailFromDecodedToken(token); + if (mail) { + localStorage.setItem(`${mail}_themeName`, name); + } + localStorage.setItem(`default_themeName`, name); + this.themeName$.next(name); } loadMenu() { diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index 905b2d2f..d03fbe65 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -1,8 +1,10 @@ { - "ApiURL": "http://localhost:5000", + "ApiURL": "http://localhost:8044", + "PrivacyURL": "https://www.sh-edraft.de/Datenschutz", + "ImprintURL": "https://www.sh-edraft.de/Impressum", "WebVersion": { - "Major": "0", - "Minor": "3", + "Major": "1", + "Minor": "0", "Micro": "0" }, "Themes": [ diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index 14025cf5..7a1cdf40 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -1,242 +1,193 @@ { - "header": { - "change_password": "Passwort ändern", - "settings": "Einstellungen", - "logout": "Ausloggen", - "header": "Krümmelmonster WI" - }, - "sidebar": { - "dashboard": "Dashboard", - "server": "Server", - "server_empty": "Kein Server ausgewählt", - "settings": "Einstellungen", - "members": "Mitglieder", - "administration": "Administration", - "config": "Konfiguration", - "auth_user_list": "Benutzer" - }, "admin": { - "settings": { - "header": "Konfiguration", - "website": { - "header": "Webseite", - "frontend_version": "Webseite Version", - "backend_version": "Server Version", - "config_path": "Konfigurations-Dateipfad", - "frontend_base_url": "Webseite Basis-URL", - "backend_base_url": "Server Basis-URL", - "token_expire_time": "Token Ablaufzeit", - "refresh_token_expire_time": "Refresh Token Ablaufzeit" - }, - "e_mail": { - "header": "E-Mail", - "user": "Benutzer", - "host": "Host", - "port": "Port", - "transceiver": "Absender", - "e_mail_address": "E-Mail Adresse", - "e_mail": "E-Mail", - "send_e_mail": "E-Mail senden" - }, - "message": { - "error": "Fehler", - "could_not_send_mail": "E-Mail konte nicht gesendet werden!", - "connection_failed": "Verbindung fehlgeschlagen", - "connection_to_mail_failed": "Die Verbindung zum Mailserver konnte nicht hergestellt werden!", - "mail_login_failed": "Die Anmeldung am Mailserver ist fehlgeschlagen!", - "send_failed": "Senden fehlgeschlagen", - "test_mail_not_send": "Die Test E-Mail konnte nicht gesendet werden!", - "success": "Erfolg", - "send_mail": "E-Mail wurde erfolgreich gesendet" - } - }, "auth_users": { "header": "Benutzer", - "of": "von", - "add": "Hinzufügen", - "reset_filters": "Filter zurücksetzen", - "users": "Benutzer", "headers": { - "users": "Benutzer", + "active": "Aktiv", + "auth_role": "Rolle", "first_name": "Vorname", "last_name": "Nachname", - "e_mail": "E-Mail", - "active": "Aktiv", - "role": "Rolle", "password": "Passwort", - "actions": "Aktionen" + "role": "Rolle", + "users": "Benutzer" }, - "no_entries_found": "Keine Einträge gefunden", "message": { + "cannot_delete_user": "Benutzer kann nicht gelöscht werden", "invalid_email": "Ungültige E-Mail", "invalid_email_d": "Die E-Mail {{email}} ist nicht gültig!", - "user_already_exists": "Benutzer existiert bereits", - "user_already_exists_d": "Der Benutzer {{email}} existiert bereits!", + "logon_with_another_user": "Loggen Sie sich mit einem anderen Benutzer ein, um diesen Benutzer zu löschen!", "user_added": "Benutzer hinzugefügt", "user_added_d": "Benutzer {{email}} erfolgreich hinzugefügt", - "user_change_failed": "Benutzer änderung fehlgeschlagen", + "user_already_exists": "Benutzer existiert bereits", + "user_already_exists_d": "Der Benutzer {{email}} existiert bereits!", + "user_change_failed": "Benutzeränderung fehlgeschlagen", "user_change_failed_d": "Benutzer {{email}} konnte nicht geändert werden!", "user_changed": "Benutzer geändert", "user_changed_d": "Benutzer {{email}} erfolgreich geändert", - "cannot_delete_user": "Benutzer kann nicht gelöscht werden", - "logon_with_another_user": "Loggen Sie sich mit einem anderen Benutzer ein, um diesen Benutzer zu löschen!", "user_delete": "Benutzer löschen", "user_delete_q": "Sind Sie sich sicher, dass Sie {{email}} löschen möchten?", "user_deleted": "Benutzer gelöscht", "user_deleted_d": "Benutzer {{email}} erfolgreich gelöscht" + }, + "users": "Benutzer" + }, + "settings": { + "email": { + "email_address": "E-Mail-Adresse", + "header": "E-Mail", + "host": "Host", + "port": "Port", + "send_email": "E-Mail senden", + "transceiver": "Absender", + "user": "Benutzer" + }, + "header": "Konfiguration", + "message": { + "connection_failed": "Verbindung fehlgeschlagen", + "connection_to_mail_failed": "Die Verbindung zum Mailserver konnte nicht hergestellt werden!", + "could_not_send_mail": "E-Mail konte nicht gesendet werden!", + "error": "Fehler", + "mail_login_failed": "Die Anmeldung am Mailserver ist fehlgeschlagen!", + "send_failed": "Senden fehlgeschlagen", + "send_mail": "E-Mail wurde erfolgreich gesendet", + "success": "Erfolg", + "test_mail_not_send": "Die Test E-Mail konnte nicht gesendet werden!" + }, + "website": { + "backend_base_url": "Server Basis-URL", + "backend_version": "Server Version", + "config_path": "Konfigurations-Dateipfad", + "frontend_base_url": "Webseite Basis-URL", + "frontend_version": "Webseite Version", + "header": "Webseite", + "refresh_token_expire_time": "Refresh Token Ablaufzeit", + "token_expire_time": "Token Ablaufzeit" } } }, "auth": { - "header": "Krümmelmonster WI", - "login": { - "e_mail": "E-Mail", - "password": "Passwort", - "login": "Einloggen", - "login_with_discord": "Mit Discord Einloggen", - "register": "Registrieren", - "forgot_password": "Passwort vergessen?", - "e_mail_required": "E-Mail benötigt", - "user_not_found": "Benutzer nicht gefunden", - "e_mail_not_confirmed": "E-Mail nicht bestätigt", - "password_required": "Passwort benötigt", - "wrong_password": "Falsches passwort" - }, - "register": { - "first_name": "Vorname", - "last_name": "Nachname", - "e_mail": "E-Mail", - "repeat_e_mail": "E-mail wiederholen", - "password": "Password", - "repeat_password": "Password wiederholen", - "register": "Registrieren", - "register_with_discord": "Mit Discord Registrieren", - "login": "Einloggen", - "user_already_exists": "Benutzer existiert bereits", - "passwords_not_match": "Passwörter sitmmen nicht überein", - "e_mails_not_match": "E-Mails sitmmen nicht überein", - "first_name_required": "Vorname benötigt", - "last_name_required": "Nachname benötigt", - "e_mail_required": "E-Mail benötigt", - "password_required": "Passwort benötigt", - "first_name_invalid": "Vorname ungültig", - "last_name_invalid": "Nachname ungültig" - }, "forgot_password": { - "e_mail": "E-Mail", - "send_confirmation_url": "Falls ein Benutzer mit der E-Mail gefunden wurde, wurde Betstätigungslink versendet", - "reset_password": "Passwort zurücksetzen", "login": "Anmelden", - "register": "Registrieren", - "repeat_password": "Passwort wiederholen", - "passwords_do_not_match": "Die Passwörter stimmen nicht überein", - "password": "Passwort", "message": { "reset_password": "Passwort zurückgesetzt", - "reset_password_d": "Dein Passwort wurde zurückgesetzt" - } - } - }, - "view": { - "dashboard": { - "header": "Dashboard", - "of": "von", - "servers": "Server", - "server": { - "header": "Server", - "member_count": "Mitglid(er)" + "reset_password_d": "Ihr Passwort wurde zurückgesetzt" }, - "filter": { - "name": "Name" - } - }, - "server": { - "header": "Server" - }, - "user-list": {}, - "change-password": { - "header": "Passwort ändern", - "wrong_password": "Falsches Passwort", + "password": "Passwort", "passwords_do_not_match": "Die Passwörter stimmen nicht überein", - "password": "Passwort", - "active_password": "Aktuelles Passwort", - "new_password": "Neues Passwort", - "repeat_new_password": "Neues Passwort wiederholen", - "save": "Speichern", - "message": { - "error": "Fehler", - "password_cannot_be_changed": "Dein Passwort konnte nicht geändert werden!", - "change_password": "Passwort geändert", - "changed_password": "Dein Passwort wurde geändert" - } + "register": "Registrieren", + "repeat_password": "Passwort wiederholen", + "reset_password": "Passwort zurücksetzen", + "send_confirmation_url": "Eine Bestätigungsmail wird versendet, wenn ein Benutzer mit der E-Mail vorhanden ist" }, - "user_settings": { - "header": "Einstellungen", - "first_name": "Vorname", - "last_name": "Nachname", - "e_mail": "E-Mail", - "password": "Passwort", - "e_mail_already_exists": "Die E-Mail wurde bereits vergeben", - "wrong_password": "Falsches Passwort", - "save": "Speichern", + "header": "Krümelmonster WI", + "login": { + "email_not_confirmed": "E-Mail nicht bestätigt", + "email_required": "E-Mail benötigt", + "forgot_password": "Passwort vergessen?", + "login": "Einloggen", + "login_with_discord": "Mit Discord einloggen", "message": { - "user_not_found": "Benutzer nicht gefunden", - "user_not_found_d": "Der Benutzer konnte nicht gefunden werden!", - "error": "Fehler", - "could_not_change_settings": "Die Einstellungen konnten nicht geändert werden!", - "changed_settings": "Die Einstellungen wurden geändert", - "success": "Erfolg" - } + "confirm_email": "E-Mail Bestätigen", + "confirm_email_d": "Sie müssen die E-Mail {{email}} Bestätigen, in dem Sie den Link öffnen, welchen wir Ihnen zugesendet haben." + }, + "password": "Passwort", + "password_required": "Passwort benötigt", + "register": "Registrieren", + "user_not_found": "Benutzer nicht gefunden", + "wrong_password": "Falsches Passwort" + }, + "register": { + "email_required": "E-Mail benötigt", + "emails_not_match": "E-Mails stimmen nicht überein", + "first_name": "Vorname", + "first_name_invalid": "Vorname ungültig", + "first_name_required": "Vorname benötigt", + "last_name": "Nachname", + "last_name_invalid": "Nachname ungültig", + "last_name_required": "Nachname benötigt", + "login": "Einloggen", + "password": "Passwort", + "password_required": "Passwort benötigt", + "passwords_not_match": "Passwörter stimmen nicht überein", + "register": "Registrieren", + "register_with_discord": "Mit Discord Registrieren", + "repeat_email": "E-Mail wiederholen", + "repeat_password": "Passwort wiederholen", + "user_already_exists": "Benutzer existiert bereits", + "confirm_privacy": "Ich erkläre mich mit der Datenschutzerklärung einverstanden." } }, - "footer": { - "imprint": "Impressum", - "backend": "Webseite", - "frontend": "API" + "common": { + "404": "404 - Der Eintrag konnte nicht gefunden werden", + "actions": "Aktionen", + "add": "Hinzufügen", + "bool_as_string": { + "false": "Nein", + "true": "Ja" + }, + "created_at": "Erstellt am", + "discord_id": "Discord Id", + "email": "E-Mail", + "error": "Fehler", + "history": { + "autoRole": "Auto Rolle", + "channelId": "Kanal Id", + "color": "Farbe", + "dateFrom": "Von", + "dateTo": "Bis", + "deleted": "Gelöscht", + "discordId": "Discord Id", + "emojiName": "Emoji", + "header": "Historie", + "id": "Id", + "leftServer": "Server verlassen", + "messageId": "Nachricht Id", + "minXp": "Min. XP", + "name": "Name", + "permissions": "Berechtigung", + "roleId": "Rolle", + "server": "Server", + "xp": "XP" + }, + "id": "Id", + "joined_at": "Beigetreten am", + "leaved_at": "Verlassen am", + "modified_at": "Bearbeitet am", + "no_entries_found": "Keine Einträge gefunden", + "of": "von", + "reset_filters": "Filter zurücksetzen" }, "dialog": { - "confirm": "Bestätigen", - "abort": "Abbrechen" + "abort": "Abbrechen", + "confirm": "Bestätigen" + }, + "footer": { + "backend": "API", + "frontend": "Webseite", + "imprint": "Impressum", + "privacy": "Datenschutz" }, "general": { "days": "Tage", + "hours": "Stunden", "minutes": "Minuten" }, - "common": { - "bool_as_string": { - "true": "Ja", - "false": "Nein" - }, - "error": "Fehler", - "404": "404 - Der Eintrag konnte nicht gefunden werden" + "header": { + "change_password": "Passwort ändern", + "header": "Krümelmonster WI", + "logout": "Ausloggen", + "settings": "Einstellungen" }, "primeng": { - "startsWith": "Startet mit", - "contains": "Enthält", - "notContains": "Enthält nicht", - "endsWith": "Ended mit", - "equals": "Gleich", - "notEquals": "Nicht gleich", - "noFilter": "Kein Filter", - "lt": "Weniger als", - "lte": "Weniger als oder gleich", - "gt": "Größer als", - "gte": "Größer als doer gleich", - "is": "Ist", - "isNot": "Ist nicht", - "before": "Vorher", - "after": "Nachher", - "clear": "Zurücksetzen", - "apply": "Anwenden", - "matchAll": "Passend zu allem", - "matchAny": "Passend zu jedem", - "addRule": "Regel hinzufügen", - "removeRule": "Regel entfernen", "accept": "Ja", - "reject": "Nein", - "choose": "Wählen", - "upload": "Hochladen", + "addRule": "Regel hinzufügen", + "after": "Nachher", + "apply": "Anwenden", + "before": "Vorher", "cancel": "Abbrechen", + "choose": "Wählen", + "clear": "Zurücksetzen", + "contains": "Enthält", "dayNames": [ "Sonntag", "Montag", @@ -246,15 +197,6 @@ "Freitag", "Samstag" ], - "dayNamesShort": [ - "Son", - "Mon", - "Die", - "Mit", - "Don", - "Fre", - "Sam" - ], "dayNamesMin": [ "So", "Mo", @@ -264,6 +206,28 @@ "Fr", "Sa" ], + "dayNamesShort": [ + "Son", + "Mon", + "Die", + "Mit", + "Don", + "Fre", + "Sam" + ], + "emptyFilterMessage": "Keine Ergebnisse gefunden", + "emptyMessage": "Keine Ergebnisse gefunden", + "endsWith": "Ended mit", + "equals": "Gleich", + "gt": "Größer als", + "gte": "Größer als oder gleich", + "is": "Ist", + "isNot": "Ist nicht", + "lt": "Kleiner als", + "lte": "Kleiner als oder gleich", + "matchAll": "Passend zu allem", + "matchAny": "Passend zu jedem", + "medium": "Mittel", "monthNames": [ "Januar", "Februar", @@ -292,13 +256,206 @@ "Nov", "Dez" ], - "today": "Heute", - "weekHeader": "Wk", - "weak": "Woche", - "medium": "Mittel", - "strong": "Stark", + "noFilter": "Kein Filter", + "notContains": "Enthält nicht", + "notEquals": "Ungleich", "passwordPrompt": "Passwort eingeben", - "emptyMessage": "Keine Ergebnisse gefunden", - "emptyFilterMessage": "Keine Ergebnisse gefunden" + "reject": "Nein", + "removeRule": "Regel entfernen", + "startsWith": "Beginnt mit", + "strong": "Stark", + "today": "Heute", + "upload": "Hochladen", + "weak": "Woche", + "weekHeader": "Wk" + }, + "sidebar": { + "administration": "Administration", + "auth_user_list": "Benutzer", + "config": "Konfiguration", + "dashboard": "Dashboard", + "members": "Mitglieder", + "server": { + "auto_roles": "Auto Rollen", + "dashboard": "Dashboard", + "levels": "Level", + "members": "Mitglieder", + "profile": "Dein Profil" + }, + "server_empty": "Kein Server ausgewählt", + "settings": "Einstellungen", + "user_list": "Benutzer" + }, + "view": { + "change-password": { + "active_password": "Aktuelles Passwort", + "header": "Passwort ändern", + "message": { + "change_password": "Passwort geändert", + "changed_password": "Ihr Passwort wurde geändert", + "error": "Fehler", + "password_cannot_be_changed": "Ihr Passwort konnte nicht geändert werden!" + }, + "new_password": "Neues Passwort", + "password": "Passwort", + "passwords_do_not_match": "Die Passwörter stimmen nicht überein", + "repeat_new_password": "Neues Passwort wiederholen", + "save": "Speichern", + "wrong_password": "Falsches Passwort" + }, + "dashboard": { + "filter": { + "name": "Name" + }, + "header": "Dashboard", + "server": { + "header": "Server", + "member_count": "Mitglied(er)" + }, + "servers": "Server" + }, + "server": { + "auto_roles": { + "auto_roles": "Auto Rollen", + "header": "Auto Rollen", + "headers": { + "channel_id": "Kanal Id", + "channel_name": "Kanal", + "message_id": "Nachricht Id", + "role_count": "Regeln" + }, + "message": { + "auto_role_create": "Auto Rolle erstellt", + "auto_role_create_d": "Auto Rolle {{id}} erfolgreich erstellt", + "auto_role_create_failed": "Auto Rolle Erstellung fehlgeschlagen", + "auto_role_create_failed_d": "Die Erstellung der Auto Rolle ist fehlgeschlagen!", + "auto_role_delete": "Auto Rolle löschen", + "auto_role_delete_failed": "Auto Rolle Löschung fehlgeschlagen", + "auto_role_delete_failed_d": "Die Löschung der Auto Rolle {{id}} ist fehlgeschlagen!", + "auto_role_delete_q": "Sind Sie sich sicher, dass Sie die Auto Rolle {{id}} löschen möchten?", + "auto_role_deleted": "Auto Rolle gelöscht", + "auto_role_deleted_d": "Auto Rolle {{id}} erfolgreich gelöscht" + }, + "rules": { + "auto_roles": "Auto Rollen Regeln", + "header": "Auto Rollen Regeln", + "headers": { + "emoji": "Emoji", + "role": "Rolle" + }, + "message": { + "auto_role_rule_create": "Auto Rollen Regel erstellt", + "auto_role_rule_create_d": "Auto Rollen Regel {{id}} erfolgreich erstellt", + "auto_role_rule_create_failed": "Auto Rollen Regel Erstellung fehlgeschlagen", + "auto_role_rule_create_failed_d": "Die Erstellung der Auto Rollen Regel ist fehlgeschlagen!", + "auto_role_rule_delete": "Auto Rollen Regel löschen", + "auto_role_rule_delete_failed": "Auto Rollen Regel Löschung fehlgeschlagen", + "auto_role_rule_delete_failed_d": "Die Löschung der Auto Rollen Regel {{id}} ist fehlgeschlagen!", + "auto_role_rule_delete_q": "Sind Sie sich sicher, dass Sie die Auto Rollen Regel {{id}} löschen möchten?", + "auto_role_rule_deleted": "Auto Rollen Regel gelöscht", + "auto_role_rule_deleted_d": "Auto Rollen Regel {{id}} erfolgreich gelöscht", + "auto_role_rule_update": "Auto Rollen Regel bearbeitet", + "auto_role_rule_update_d": "Auto Rollen Regel {{id}} erfolgreich bearbeitet", + "auto_role_rule_update_failed": "Auto Rollen Regel Bearbeitung fehlgeschlagen", + "auto_role_rule_update_failed_d": "Die Bearbeitung der Auto Rollen Regel ist fehlgeschlagen!" + } + } + }, + "dashboard": { + "deleted_message_count": "Gelöschte Nachrichten", + "header": "Server dashboard", + "moved_users_count": "Verschobene Benutzer", + "name": "Name", + "received_command_count": "Empfangene Befehle", + "received_message_count": "Empfangene Nachrichten", + "sent_message_count": "Gesendete Nachrichten" + }, + "header": "Server", + "levels": { + "header": "Level", + "headers": { + "color": "Farbe", + "min_xp": "Min. XP", + "name": "Name", + "permissions": "Rechte" + }, + "levels": "Level", + "message": { + "level_create": "Level erstellt", + "level_create_d": "Level {{name}} erfolgreich erstellt", + "level_create_failed": "Level Erstellung fehlgeschlagen", + "level_create_failed_d": "Die Erstellung des Levels ist fehlgeschlagen!", + "level_delete": "Level löschen", + "level_delete_failed": "Level Löschung fehlgeschlagen", + "level_delete_failed_d": "Die Löschung des Levels {{name}} ist fehlgeschlagen!", + "level_delete_q": "Sind Sie sich sicher, dass Sie das Level {{name}} löschen möchten?", + "level_deleted": "Level gelöscht", + "level_deleted_d": "Level {{name}} erfolgreich gelöscht", + "level_update": "Level bearbeitet", + "level_update_d": "Level {{name}} erfolgreich bearbeitet", + "level_update_failed": "Level Bearbeitung fehlgeschlagen", + "level_update_failed_d": "Die Bearbeitung des Levels ist fehlgeschlagen!" + } + }, + "members": { + "header": "Mitglieder", + "headers": { + "left_server": "Aktiv", + "level": "Level", + "name": "Name", + "ontime": "Ontime", + "xp": "XP" + }, + "members": "Mitgliedern", + "message": { + "user_change_failed": "Benutzeränderung fehlgeschlagen", + "user_change_failed_d": "Benutzer {{name}} konnte nicht geändert werden!", + "user_changed": "Benutzer geändert", + "user_changed_d": "Benutzer {{name}} erfolgreich geändert" + } + }, + "profile": { + "header": "Dein Profil", + "joined_game_server": { + "header": "Gameserver-beitritte", + "name": "Gameserver", + "time": "Spielzeit" + }, + "joined_server": { + "header": "Server-beitritte", + "time": "Zeit" + }, + "joined_voice_channel": { + "channel": "Sprachkanal", + "header": "Sprachkanal-beitritte", + "time": "Zeit" + }, + "left_server": "Hat Server verlassen", + "level": "Level", + "minecraft_id": "Minecraft Id", + "name": "Name", + "ontime": "Ontime", + "permission_denied": "Zugriff verweigert!", + "permission_denied_d": "Du musst Moderator sein, um andere Profile sehen zu können!", + "xp": "XP" + } + }, + "user_settings": { + "email_already_exists": "Die E-Mail wurde bereits vergeben", + "first_name": "Vorname", + "header": "Einstellungen", + "last_name": "Nachname", + "message": { + "changed_settings": "Die Einstellungen wurden geändert", + "could_not_change_settings": "Die Einstellungen konnten nicht geändert werden!", + "error": "Fehler", + "success": "Erfolg", + "user_not_found": "Benutzer nicht gefunden", + "user_not_found_d": "Der Benutzer konnte nicht gefunden werden!" + }, + "password": "Passwort", + "save": "Speichern", + "wrong_password": "Falsches Passwort" + } } } diff --git a/kdb-web/src/assets/i18n/en.json b/kdb-web/src/assets/i18n/en.json index 0851c3e4..62a3f623 100644 --- a/kdb-web/src/assets/i18n/en.json +++ b/kdb-web/src/assets/i18n/en.json @@ -1,322 +1,461 @@ { - "header": { - "change_password": "Change Password", - "settings": "Settings", - "logout": "Logout" + "admin": { + "auth_users": { + "header": "User", + "headers": { + "active": "Active", + "auth_role": "Role", + "first_name": "First name", + "last_name": "Last name", + "password": "Password", + "role": "Role", + "users": "User" + }, + "message": { + "cannot_delete_user": "User cannot be deleted", + "invalid_email": "Invalid E-Mail", + "invalid_email_d": "E-Mail {{email}} is not valid!", + "logon_with_another_user": "Change to another account to delete this user!", + "user_added": "User added", + "user_added_d": "User {{email}} successfully added", + "user_already_exists": "User already exists", + "user_already_exists_d": "User {{email}} already exists!", + "user_change_failed": "User change failed", + "user_change_failed_d": "User {{email}} could not be changed!", + "user_changed": "User changed", + "user_changed_d": "User {{email}} changed successfully", + "user_delete": "Delete user", + "user_delete_q": "Are you sure you want to delete {{email}}?", + "user_deleted": "User deleted", + "user_deleted_d": "User {{email}} successfully deleted" + }, + "users": "User" }, - "sidebar": { - "dashboard": "Dashboard", - "domain_list": "Domains", - "host_list": "Hosts", - "user_list": "Users", - "login_list": "Logins", - "config": "Configuration", - "auth_user_list": "User" - }, - "admin": { - "settings": { - "header": "Configuration", - "website": { - "header": "Website", - "frontend_version": "Website version", - "backend_version": "Server version", - "config_path": "Configuration-Path", - "frontend_base_url": "Website Base-URL", - "backend_base_url": "Server Base-URL", - "token_expire_time": "Token expire time", - "refresh_token_expire_time": "Refresh Token expire time" - }, - "e_mail": { - "header": "E-Mail", - "user": "User", - "host": "Host", - "port": "Port", - "transceiver": "Sender", - "e_mail_address": "E-Mail address", - "e_mail": "E-Mail", - "send_e_mail": "Send E-Mail" - }, - "message": { - "error": "Error", - "could_not_send_mail": "E-mail could not be sent!", - "connection_failed": "Connection Failed", - "connection_to_mail_failed": "The connection to the mail server could not be established!", - "mail_login_failed": "The registration at the mail server failed!", - "send_failed": "Sending failed", - "test_mail_not_send": "The test email could not be sent!", - "success": "Success", - "send_mail": "Email was sent successfully" - } - }, - "auth_users": { - "header": "User", - "of": "of", - "add": "Add", - "reset_filters": "Reset filters", - "users": "User", - "headers": { - "users": "User", - "first_name": "Forename", - "last_name": "Surname", - "e_mail": "E-Mail", - "active": "Active", - "role": "Role", - "password": "Password", - "actions": "Actions" - }, - "no_entries_found": "No entries found", - "message": { - "invalid_email": "Invalid E-Mail", - "invalid_email_d": "The e-mail {{email}} is not valid!", - "user_already_exists": "User already exists", - "user_already_exists_d": "The user {{email}} already exists!", - "user_added": "User added", - "user_added_d": "User {{email}} successfully added", - "user_change_failed": "User change failed", - "user_change_failed_d": "User {{email}} could not be changed!", - "user_changed": "User changed", - "user_changed_d": "User {{email}} changed successfully", - "cannot_delete_user": "User cannot be deleted", - "logon_with_another_user": "Log in with another user to delete this user!", - "user_delete": "Delete user", - "user_delete_q": "Are you sure you want to delete {{email}}?", - "user_deleted": "User deleted", - "user_deleted_d": "User {{email}} successfully deleted" - } - } - }, - "auth": { - "header": "Login counter", - "login": { - "e_mail": "E-Mail", - "password": "Password", - "login": "Login", - "register": "Register", - "forgot_password": "Forgot password?", - "e_mail_required": "E-Mail required", - "user_not_found": "User not found", - "e_mail_not_confirmed": "Email was not confirmed", - "password_required": "Passwort required", - "wrong_password": "Wrong password" - }, - "register": { - "first_name": "Forename", - "last_name": "Surname", - "e_mail": "E-Mail", - "repeat_e_mail": "Repeat E-mail", - "password": "Password", - "repeat_password": "Repeat password", - "register": "Register", - "login": "Login", - "user_already_exists": "User already exists", - "passwords_not_match": "The passwords do not match", - "e_mails_not_match": "The emails do not match", - "first_name_required": "Forename required", - "last_name_required": "Surname required", - "e_mail_required": "E-Mail required", - "password_required": "Password required", - "first_name_invalid": "Forename invalid", - "last_name_invalid": "Surname invalid" - }, - "forgot_password": { - "e_mail": "E-Mail", - "send_confirmation_url": "If a user was found with the email, a confirmation link was sent", - "reset_password": "Reset password", - "login": "Login", - "register": "Register", - "repeat_password": "Repeat password", - "passwords_do_not_match": "The passwords do not match", - "password": "Password", - "message": { - "reset_password": "Password reset", - "reset_password_d": "Your password has been reset" - } - } - }, - "view": { - "dashboard": {}, - "user-list": {}, - "change-password": { - "header": "Change Password", - "wrong_password": "Wrong password", - "passwords_do_not_match": "The passwords do not match", - "password": "Password", - "active_password": "Current Password", - "new_password": "New password", - "repeat_new_password": "Repeat new password", - "save": "Save", - "message": { - "error": "Error", - "password_cannot_be_changed": "Your password could not be changed!", - "change_password": "Changed password", - "changed_password": "Your password has been changed" - } - }, - "user_settings": { - "header": "Settings", - "first_name": "Forename", - "last_name": "Surname", - "e_mail": "E-Mail", - "password": "Password", - "e_mail_already_exists": "The email has already been taken", - "wrong_password": "Wrong password", - "save": "Save", - "message": { - "user_not_found": "User not found", - "user_not_found_d": "The user could not be found!", - "error": "Error", - "could_not_change_settings": "The settings could not be changed!", - "changed_settings": "Settings changed", - "success": "Success" - } - } - }, - "footer": { - "imprint": "Imprint", - "backend": "Website", - "frontend": "API" - }, - "dialog": { - "confirm": "Confirm", - "abort": "Abort" - }, - "general": { - "days": "Days", - "minutes": "Minutes" - }, - "login_models": { - "domain": { - "header": "Domain", - "name": "Name", - "users": "User", - "hosts": "Hosts", - "notify_when_login": "Notification after login", - "not_found": "Domain not found!" - }, - "host": { - "header": "Host", - "name": "Name", - "ip_address": "IP Address", - "users": "User", - "domain": "Domain", - "os": "Operating system", - "notify_when_login": "Notification after login", - "not_found": "Host not found!" - }, - "user": { - "header": "User", - "name": "Name", - "host": "Host", - "domain": "Domain", - "notify_when_login": "Notification after login", - "not_found": "User not found!" - }, - "login": { - "header": "Login", - "time": "Time", - "user": "User", - "host": "Host", - "notify_when_login": "Notification after login", - "not_found": "Login not found!" - } - }, - "common": { - "bool_as_string": { - "true": "Yes", - "false": "No" - }, + "settings": { + "email": { + "email_address": "E-Mail address", + "header": "E-Mail", + "host": "Host", + "port": "Port", + "send_email": "Send E-Mail", + "transceiver": "Sender", + "user": "User" + }, + "header": "Configuration", + "message": { + "connection_failed": "Connection Failed", + "connection_to_mail_failed": "The connection to the mail server could not be established!", + "could_not_send_mail": "E-mail could not be sent!", "error": "Error", - "404": "404 - Entry not found!" - }, - "primeng": { - "startsWith": "Starts with", - "contains": "Contains", - "notContains": "Not contains", - "endsWith": "Ends with", - "equals": "Equals", - "notEquals": "Not equals", - "noFilter": "No Filter", - "lt": "Less than", - "lte": "Less than or equal to", - "gt": "Greater than", - "gte": "Great then or equals", - "is": "Is", - "isNot": "Is not", - "before": "Before", - "after": "After", - "clear": "Clear", - "apply": "Apply", - "matchAll": "Match All", - "matchAny": "Match Any", - "addRule": "Add Rule", - "removeRule": "Remove Rule", - "accept": "Yes", - "reject": "No", - "choose": "Choose", - "upload": "Upload", - "cancel": "Cancel", - "dayNames": [ - "Sunday", - "Monday", - "Tuesday", - "Wednesday", - "Thursday", - "Friday", - "Saturday" - ], - "dayNamesShort": [ - "Sun", - "Mon", - "Tue", - "Wed", - "Thu", - "Fri", - "Sat" - ], - "dayNamesMin": [ - "Su", - "Mo", - "Tu", - "We", - "Th", - "Fr", - "Sa" - ], - "monthNames": [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December" - ], - "monthNamesShort": [ - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec" - ], - "today": "Today", - "weekHeader": "Wk", - "weak": "Weak", - "medium": "Medium", - "strong": "Strong", - "passwordPrompt": "Enter a password", - "emptyMessage": "No results found", - "emptyFilterMessage": "No results found" + "mail_login_failed": "Registration at the mail server failed!", + "send_failed": "Sending failed", + "send_mail": "Email was sent successfully", + "success": "Success", + "test_mail_not_send": "Test email could not be sent!" + }, + "website": { + "backend_base_url": "Server Base-URL", + "backend_version": "Server version", + "config_path": "Configuration-Path", + "frontend_base_url": "Website Base-URL", + "frontend_version": "Website version", + "header": "Website", + "refresh_token_expire_time": "Refresh Token expire time", + "token_expire_time": "Token expire time" + } } -} \ No newline at end of file + }, + "auth": { + "forgot_password": { + "login": "Login", + "message": { + "reset_password": "Password reset", + "reset_password_d": "Your password has been reseted" + }, + "password": "Password", + "passwords_do_not_match": "Passwords do not match", + "register": "Register", + "repeat_password": "Repeat password", + "reset_password": "Reset password", + "send_confirmation_url": "A confirmation email will be sent if a user match with the email address" + }, + "header": "Cookie Monster WI", + "login": { + "email_not_confirmed": "Email was not confirmed", + "email_required": "E-Mail required", + "forgot_password": "Forgot password?", + "login": "Login", + "login_with_discord": "Login with discord", + "message": { + "confirm_email": "Confirm E-Mail", + "confirm_email_d": "You have to confirm your email {{email}} Please confirm your account through the link in the email." + }, + "password": "Password", + "password_required": "Passwort required", + "register": "Register", + "user_not_found": "User not found", + "wrong_password": "Wrong password" + }, + "register": { + "email_required": "E-Mail required", + "emails_not_match": "E-Mails do not match", + "first_name": "First name", + "first_name_invalid": "First name invalid", + "first_name_required": "First name required", + "last_name": "Last name", + "last_name_invalid": "Last name invalid", + "last_name_required": "Last name required", + "login": "Login", + "password": "Password", + "password_required": "Password required", + "passwords_not_match": "Passwords do not match", + "register": "Register", + "register_with_discord": "Register with discord", + "repeat_email": "Repeat E-mail", + "repeat_password": "Repeat password", + "user_already_exists": "User already exists", + "confirm_privacy": "I agree to the Privacy Policy." + } + }, + "common": { + "404": "404 - Entry not found!", + "actions": "Actions", + "add": "Add", + "bool_as_string": { + "false": "No", + "true": "Yes" + }, + "created_at": "Created at", + "discord_id": "Discord Id", + "email": "E-Mail", + "error": "Error", + "history": { + "autoRole": "Auto role", + "channelId": "Channel Id", + "color": "Color", + "dateFrom": "From", + "dateTo": "To", + "deleted": "Deleted", + "discordId": "Discord Id", + "emojiName": "Emoji", + "header": "History", + "id": "Id", + "leftServer": "Left server", + "messageId": "Message Id", + "minXp": "Min. XP", + "name": "Name", + "permissions": "Permissions", + "roleId": "Role", + "server": "Server", + "xp": "XP" + }, + "id": "Id", + "joined_at": "Joined at", + "leaved_at": "Leaved at", + "modified_at": "Modified at", + "no_entries_found": "No entries found", + "of": "of", + "reset_filters": "Reset filters" + }, + "dialog": { + "abort": "Abort", + "confirm": "Confirm" + }, + "footer": { + "backend": "Website", + "frontend": "API", + "imprint": "Imprint", + "privacy": "Privacy" + }, + "general": { + "days": "Days", + "hours": "Hours", + "minutes": "Minutes" + }, + "header": { + "change_password": "Change Password", + "header": "Cookie Monster WI", + "logout": "Logout", + "settings": "Settings" + }, + "primeng": { + "accept": "Yes", + "addRule": "Add Rule", + "after": "After", + "apply": "Apply", + "before": "Before", + "cancel": "Cancel", + "choose": "Choose", + "clear": "Clear", + "contains": "Contains", + "dayNames": [ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + ], + "dayNamesMin": [ + "Su", + "Mo", + "Tu", + "We", + "Th", + "Fr", + "Sa" + ], + "dayNamesShort": [ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" + ], + "emptyFilterMessage": "No results found", + "emptyMessage": "No results found", + "endsWith": "Ends with", + "equals": "Equals", + "gt": "Greater than", + "gte": "Great then or equals", + "is": "Is", + "isNot": "Is not", + "lt": "Less than", + "lte": "Less than or equal to", + "matchAll": "Match All", + "matchAny": "Match Any", + "medium": "Medium", + "monthNames": [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" + ], + "monthNamesShort": [ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec" + ], + "noFilter": "No Filter", + "notContains": "Not contains", + "notEquals": "Not equals", + "passwordPrompt": "Enter a password", + "reject": "No", + "removeRule": "Remove Rule", + "startsWith": "Starts with", + "strong": "Strong", + "today": "Today", + "upload": "Upload", + "weak": "Weak", + "weekHeader": "Wk" + }, + "sidebar": { + "administration": "Administration", + "auth_user_list": "User", + "config": "Configuration", + "dashboard": "Dashboard", + "members": "Members", + "server": { + "auto_roles": "Auto role", + "dashboard": "Dashboard", + "levels": "Level", + "members": "Members", + "profile": "Your profile" + }, + "server_empty": "No server selected", + "settings": "Settings", + "user_list": "Users" + }, + "view": { + "change-password": { + "active_password": "Current Password", + "header": "Change Password", + "message": { + "change_password": "Changed password", + "changed_password": "Your password has been changed", + "error": "Error", + "password_cannot_be_changed": "Your password could not be changed!" + }, + "new_password": "New password", + "password": "Password", + "passwords_do_not_match": "Passwords do not match", + "repeat_new_password": "Repeat new password", + "save": "Save", + "wrong_password": "Wrong password" + }, + "dashboard": { + "filter": { + "name": "Name" + }, + "header": "Dashboard", + "server": { + "header": "Server", + "member_count": "Member(s)" + }, + "servers": "Server" + }, + "server": { + "auto_roles": { + "auto_roles": "Auto roles", + "header": "Auto roles", + "headers": { + "channel_id": "Channel Id", + "channel_name": "Channel", + "message_id": "Message Id", + "role_count": "Rules" + }, + "message": { + "auto_role_create": "Auto role created", + "auto_role_create_d": "Auto role {{id}} created successfully", + "auto_role_create_failed": "Auto role creation failed", + "auto_role_create_failed_d": "Creation of the Auto Role has failed!", + "auto_role_delete": "Delete auto role", + "auto_role_delete_failed": "Auto role deletion failed", + "auto_role_delete_failed_d": "Deletion of the car role {{id}} failed!", + "auto_role_delete_q": "Are you sure you want to delete the {{id}} car role?", + "auto_role_deleted": "Auto role deleted", + "auto_role_deleted_d": "Auto role {{id}} deleted successfully" + }, + "rules": { + "auto_roles": "Auto role rules", + "header": "Auto role rules", + "headers": { + "emoji": "Emoji", + "role": "Role" + }, + "message": { + "auto_role_rule_create": "Auto role rules created", + "auto_role_rule_create_d": "Auto role rule {{id}} successfully created", + "auto_role_rule_create_failed": "Auto role rule creation failed", + "auto_role_rule_create_failed_d": "Creation of the Auto role rule failed!", + "auto_role_rule_delete": "Auto role rule delete", + "auto_role_rule_delete_failed": "Auto role rule deletion failed", + "auto_role_rule_delete_failed_d": "Deletion of the auto role rule {{id}} failed!", + "auto_role_rule_delete_q": "Are you sure you want to delete the auto role rule {{id}}?", + "auto_role_rule_deleted": "Auto role rule deleted", + "auto_role_rule_deleted_d": "Auto role rule {{id}} successfully deleted", + "auto_role_rule_update": "Auto role rule edited", + "auto_role_rule_update_d": "Auto role rule {{id}} successfully processed", + "auto_role_rule_update_failed": "Auto role rule processing failed", + "auto_role_rule_update_failed_d": "Processing of auto role rule has failed!" + } + } + }, + "dashboard": { + "deleted_message_count": "Deleted messages", + "header": "Server dashboard", + "moved_users_count": "Moved users", + "name": "Name", + "received_command_count": "Received commands", + "received_message_count": "Received messages", + "sent_message_count": "Sent messages" + }, + "header": "Server", + "levels": { + "header": "Level", + "headers": { + "color": "Color", + "min_xp": "Min. XP", + "name": "Name", + "permissions": "Permissions" + }, + "levels": "Level", + "message": { + "level_create": "Level created", + "level_create_d": "Level {{name}} successfully created", + "level_create_failed": "Level creation failed", + "level_create_failed_d": "Creation of level failed!", + "level_delete": "Delete level", + "level_delete_failed": "Level deletion failed", + "level_delete_failed_d": "Deletion of level {{name}} failed!", + "level_delete_q": "Are you sure you want to delete the {{name}} level?", + "level_deleted": "Level deleted", + "level_deleted_d": "Level {{name}} successfully deleted\t", + "level_update": "Level edited", + "level_update_d": "Level {{name}} edited successfully", + "level_update_failed": "Level editing failed", + "level_update_failed_d": "Level editing failed!" + } + }, + "members": { + "header": "Members", + "headers": { + "left_server": "Active", + "level": "Level", + "name": "Name", + "ontime": "Ontime", + "xp": "XP" + }, + "members": "Members", + "message": { + "user_change_failed": "User change failed", + "user_change_failed_d": "User {{name}} could not be changed!", + "user_changed": "User changed", + "user_changed_d": "User {{name}} changed successfully" + } + }, + "profile": { + "header": "Profile", + "joined_game_server": { + "header": "Game server accessions", + "name": "Game server", + "time": "Game time" + }, + "joined_server": { + "header": "Server joins", + "time": "Time" + }, + "joined_voice_channel": { + "channel": "Voice channel", + "header": "Voice channel joins", + "time": "Time" + }, + "left_server": "Leaved server", + "level": "Level", + "minecraft_id": "Minecraft Id", + "name": "Name", + "ontime": "Ontime", + "permission_denied": "Access denied!", + "permission_denied_d": "You have to be moderator to see other profiles!", + "xp": "Xp" + } + }, + "user_settings": { + "email_already_exists": "This email is already been taken", + "first_name": "First name", + "header": "Settings", + "last_name": "Last name", + "message": { + "changed_settings": "Settings changed", + "could_not_change_settings": "Settings could not be changed!", + "error": "Error", + "success": "Success", + "user_not_found": "User not found", + "user_not_found_d": "This user cannot be found!" + }, + "password": "Password", + "save": "Save", + "wrong_password": "Wrong password" + } + } +} diff --git a/kdb-web/src/environments/environment.development.ts b/kdb-web/src/environments/environment.development.ts index f5bb9730..66998ae9 100644 --- a/kdb-web/src/environments/environment.development.ts +++ b/kdb-web/src/environments/environment.development.ts @@ -4,7 +4,6 @@ export const environment = { production: false, - apiURL: "http://localhost:8044", }; /* diff --git a/kdb-web/src/environments/environment.prod.ts b/kdb-web/src/environments/environment.prod.ts index ffb05978..c9669790 100644 --- a/kdb-web/src/environments/environment.prod.ts +++ b/kdb-web/src/environments/environment.prod.ts @@ -1,4 +1,3 @@ export const environment = { production: true, - apiURL: "https://kdb.keksdose-gaming.de", }; diff --git a/kdb-web/src/environments/environment.staging.ts b/kdb-web/src/environments/environment.staging.ts index a0504876..c9669790 100644 --- a/kdb-web/src/environments/environment.staging.ts +++ b/kdb-web/src/environments/environment.staging.ts @@ -1,4 +1,3 @@ export const environment = { production: true, - apiURL: "https://kdb-test.keksdose-gaming.de", }; diff --git a/kdb-web/src/environments/environment.ts b/kdb-web/src/environments/environment.ts index 1b1a28e3..f56ff470 100644 --- a/kdb-web/src/environments/environment.ts +++ b/kdb-web/src/environments/environment.ts @@ -3,8 +3,7 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false, - apiURL: "http://localhost:5000", + production: false }; /* diff --git a/kdb-web/src/favicon.ico b/kdb-web/src/favicon.ico index 997406ad..30024329 100644 Binary files a/kdb-web/src/favicon.ico and b/kdb-web/src/favicon.ico differ diff --git a/kdb-web/src/styles.scss b/kdb-web/src/styles.scss index 9d6c4649..b9318b03 100644 --- a/kdb-web/src/styles.scss +++ b/kdb-web/src/styles.scss @@ -5,463 +5,592 @@ @import "./styles/primeng-fixes.scss"; @import "./styles/constants.scss"; + html, body { - height: 100%; - padding: 0; - margin: 0; + height: 100vh; + padding: 0; + margin: 0; - font-size: 1rem; + font-size: 1rem; + + $scrollbarColor: #272727; + $scrollbarBackgroundColor: #888; + + /* width */ + ::-webkit-scrollbar { + width: 10px; + } + + /* Track */ + ::-webkit-scrollbar-track { + background-color: $scrollbarBackgroundColor; + } + + /* Handle */ + ::-webkit-scrollbar-thumb { + background: $scrollbarColor; + border: 3px solid $scrollbarBackgroundColor; + border-radius: 10px; + } + + /* Handle on hover */ + ::-webkit-scrollbar-thumb:hover { + background: $scrollbarColor; + } } main { - display: flex; - flex-direction: column; - min-height: 100vh; + display: flex; + flex-direction: column; + min-height: 100vh; } h1 { - margin: 0; - font-size: 1.75rem; + margin: 0; + font-size: 1.75rem; } h2 { - margin: 0; - font-size: 1.5rem; + margin: 0; + font-size: 1.5rem; } h3 { - margin: 0; - font-size: 1.25rem; + margin: 0; + font-size: 1.25rem; } header { - height: $headerHeight; + height: $headerHeight; + display: flex; + flex-direction: row; + + .logo-button-wrapper { display: flex; - flex-direction: row; + align-items: center; + justify-content: center; - .logo-button-wrapper { - display: flex; - align-items: center; - justify-content: center; - - .p-button.p-button-text { - border: none; - } + .p-button.p-button-text { + border: none; } + } - .logo { - display: flex; - align-items: center; - justify-content: center; - } + .logo { + display: flex; + align-items: center; + justify-content: center; + } - .header-menu { - text-align: right; - flex: 1; - justify-content: flex-end; - margin: 0px 5px 0px 0px; - } + .header-menu { + text-align: right; + flex: 1; + justify-content: flex-end; + margin: 0 5px 0 0; + } - .p-menu-overlay { - width: 180px !important; - } + .p-menu-overlay { + width: 180px !important; + } } .auth-header { - .p-menu-overlay { - width: 180px !important; - } + .p-menu-overlay { + width: 180px !important; + } +} + +.auth-footer { } .app { + height: 100%; + display: flex; + flex: 1; + + .sidebar { height: 100%; - display: flex; - flex: 1; + } - .sidebar { - height: 100%; - } + h1 { + // table views with filters are scrollable with 10 items, when 30px margin + margin-bottom: 20px; + } - h1 { - // table views with filters are scrollable with 10 items, when 30px margin - margin-bottom: 20px; - } + .component-wrapper { + width: 100%; - .component-wrapper { - width: 100%; + .component { + width: 100%; + height: 100%; + padding: 15px; - .component { + .content-wrapper { + margin-bottom: 30px; + border-radius: 5px; + + .content-header { + padding: 10px; + + h2 { + font-size: 20px; + } + } + + .content { + width: 100%; + display: flex; + flex-direction: column; + padding: 15px; + + form { + input { + width: 100%; + } + } + + .content-row { + display: flex; + flex-direction: row; + flex: 1; + margin: 5px 0; + } + + .content-column { + display: flex; + flex: 1; + } + + .content-data-name { + display: flex; + flex: 1; + align-items: center; + + font-size: 18px; + } + + .content-data-value { + display: flex; + flex: 1; + align-items: center; + + font-size: 18px; + } + + .content-divider { + margin: 5px 0; + } + + p-panel { + margin: 5px 0; + } + + .dropdown-icon-label-wrapper { + display: flex; + flex-direction: row; + gap: 10px; + } + + .content-input-field { + width: 50% !important; + margin: 0 !important; + } + + .input-field { width: 100%; - height: 100%; - padding: 15px; - .content-wrapper { - margin-bottom: 30px; - border-radius: 5px; + input, + .p-password { + width: 100%; + } + } - .content-header { - padding: 10px; + .input-field-info-text { + margin: 15px 0; + width: 100%; + } - h2 { - font-size: 20px; - } + .login-form-submit { + .login-form-submit-btn { + width: 100%; + } + } + + .login-form-sub-button-wrapper { + display: flex; + flex-direction: column; + + .login-form-sub-btn { + margin-top: 15px; + width: 100%; + } + + .login-form-sub-btn-wrapper { + width: 100%; + } + } + + .table-caption { + display: flex; + + .table-caption-text { + flex: 1; + font-weight: 400; + } + + .table-caption-search { + } + } + + .table-header-label { + display: flex; + + .table-header-text { + flex: 1; + } + + .table-header-icon { + } + } + + .table-header-small { + width: 75px; + } + + .table-header-medium { + width: 150px; + } + + .table-header-actions { + width: 100px; + } + + .table-header-small-dropdown { + width: 150px; + } + + .server-list-wrapper { + display: flex; + flex-direction: column; + gap: 10px; + + .server-filter { + } + + .server-count { + } + + .server-list { + display: flex; + flex-direction: column; + + gap: 15px; + + .server { + display: flex; + gap: 15px; + + padding: 20px; + + .logo { + + img { + width: 4rem; + height: 4rem; + object-fit: contain; + } } - .content { - width: 100%; + .info { + display: flex; + flex-direction: column; + width: 100%; + gap: 10px; + + .name { + margin: 0; + + justify-content: center; + align-items: center; + } + + .data { + } + + .client-data { display: flex; - flex-direction: column; - padding: 15px; + flex-direction: row; + width: 100%; - form { - width: 100%; - } + .client-component { - .content-row { + width: 100%; + + .client { display: flex; flex-direction: row; - flex: 1; - margin: 1.5px 0px; - } - - .content-column { - display: flex; - flex: 1; - } - - .content-data-name { - display: flex; - flex: 1; - align-items: center; - - font-size: 18px; - } - - .content-data-value { - display: flex; - flex: 1; - align-items: center; - - font-size: 18px; - } - - .content-divider { - margin: 5px 0px; - } - - .content-input-field { - width: 50% !important; - margin: 0 !important; - } - - .input-field { - width: 100%; - - input, - .p-password { - width: 100%; - } - } - - .input-field-info-text { - margin: 15px 0px; - width: 100%; - } - - .login-form-submit { - .login-form-submit-btn { - width: 100%; - } - } - - .login-form-sub-button-wrapper { - display: flex; - flex-direction: column; - - .login-form-sub-btn { - margin-top: 15px; - width: 100%; - } - - .login-form-sub-btn-wrapper { - width: 100%; - } - } - - .table-caption { - display: flex; - - .table-caption-text { - flex: 1; - font-weight: 400; - } - - .table-caption-search { - } - } - - .table-header-label { - display: flex; - - .table-header-text { - flex: 1; - } - - .table-header-icon { - } - } - - .table-header-actions { - width: 100px; - } - - .table-header-small-dropdown { - width: 150px; - } - - .server-list-wrapper { - display: flex; - flex-direction: column; + align-content: stretch !important; + flex-wrap: wrap; gap: 10px; - .server-filter { - } - - .server-count { - } - - .server-list { - display: flex; - flex-direction: column; - - gap: 15px; - - .server { - display: flex; - gap: 15px; - - padding: 20px; - - .logo { - overflow: hidden; - - img { - width: 4rem; - height: 4rem; - object-fit: contain; - } - } - - .info { - display: flex; - flex-direction: column; - - gap: 10px; - - .name { - margin: 0px; - - justify-content: center; - align-items: center; - } - - .data { - } - } - } + .client-info { + display: flex; + flex-direction: column; + margin-left: 2%; + + .client-info-header { + margin-bottom: 5px; + white-space: nowrap; + font-weight: bold + } + + .client-info-value { + white-space: nowrap; + } } + } } + } } + } } + } } + } } + } +} + +.history { + width: 300px; + + .entry-list { + display: flex; + flex-direction: column; + + gap: 15px; + + .entry { + padding-bottom: 10px; + + display: flex; + flex-direction: column; + + gap: 5px; + + .attribute { + display: flex; + gap: 5px; + + .key { + width: 30%; + } + + .seperator { + width: 10%; + } + + .value { + width: 60%; + } + } + } + } } .p-dialog-header { - padding: 20px 20px 20px 20px !important; + padding: 20px 20px 20px 20px !important; } .p-dialog-content { - padding: 20px !important; + padding: 20px !important; } .p-dialog-footer { - padding: 0px 20px 20px 20px !important; + padding: 0 20px 20px 20px !important; } .p-dialog-content { - .content-row { - display: flex; - flex-direction: row; - flex: 1; - margin: 1.5px 0px; - } + .content-row { + display: flex; + flex-direction: row; + flex: 1; + margin: 1.5px 0; + } - .content-column { - display: flex; - flex: 1; - } + .content-column { + display: flex; + flex: 1; + } - .content-data-name { - display: flex; - flex: 1; - align-items: center; + .content-data-name { + display: flex; + flex: 1; + align-items: center; - font-size: 18px; - } + font-size: 18px; + } - .content-data-value { - display: flex; - flex: 1; - align-items: center; + .content-data-value { + display: flex; + flex: 1; + align-items: center; - font-size: 18px; - } + font-size: 18px; + } - .content-divider { - margin: 5px 0px; - } + .content-divider { + margin: 5px 0; + } - .content-input-field { - width: 50% !important; - margin: 0 !important; - } + .content-input-field { + width: 50% !important; + margin: 0 !important; + } } footer { - width: 100%; - height: $footerHeight; - padding: 0px 10px; + width: 100%; + height: $footerHeight; + padding: 0 10px; + + display: flex; + align-items: center; + justify-content: center; + + .left { + width: 50%; display: flex; - align-items: center; - justify-content: center; - .left { - width: 50%; + // .frontend-version { + // } - display: flex; - - // .frontend-version { - // } - - .version-divider { - margin: 0px 5px; - } - - // .backend-version { - // } + .version-divider { + margin: 0 5px; } - .right { - width: 50%; - text-align: right; + // .backend-version { + // } + } + + .right { + width: 50%; + text-align: right; + .p-button-label { + font-weight: unset !important; } + } } .login-wrapper { - width: 100vw; - height: 100vh; + width: 100vw; + height: 100vh; + + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + gap: 15px; + + .login-form-wrapper, + .auth-header, + .auth-footer { + width: 350px; + height: 450px; display: flex; justify-content: center; align-items: center; - flex-direction: column; - gap: 15px; - .login-form-wrapper, - .auth-header { - width: 350px; - height: 450px; + border-radius: 25px; - display: flex; - justify-content: center; - align-items: center; + .login-form { + width: 80%; + height: 80%; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; - border-radius: 25px; + h1 { + text-align: center; + } - .login-form { - width: 80%; - height: 80%; - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + .input-field-info-text { + margin: 15px 0; + width: 100%; + } - h1 { - text-align: center; - } - - .input-field-info-text { - margin: 15px 0px; - width: 100%; - } - - .login-form-submit { - .login-form-submit-btn { - width: 100%; - } - } - - .login-form-sub-button-wrapper { - display: flex; - flex-direction: column; - - .login-form-sub-btn { - margin-top: 15px; - width: 100%; - } - - .login-form-sub-btn-wrapper { - width: 100%; - } - } + .login-form-submit { + .login-form-submit-btn { + width: 100%; } - } + } - .register-form-wrapper { - height: 600px; - } + .login-form-sub-button-wrapper { + display: flex; + flex-direction: column; - .register-confirm-form-wrapper { - height: 250px; - } + .login-form-sub-btn { + margin-top: 15px; + width: 100%; + } - .auth-header { - width: 350px; - height: 75px; + .login-form-sub-btn-wrapper { + width: 100%; + } + } } + } + + .register-form-wrapper { + height: 600px; + } + + .register-confirm-form-wrapper { + height: 250px; + } + + .auth-header { + width: 350px; + height: 75px; + } + + .auth-footer { + width: 350px; + height: 75px; + } } .input-field { - margin: 15px 0px; + margin: 15px 0; - input, - .p-password { - height: 40px; - width: 100%; - font-size: 18px; - } + input, + .p-password { + height: 40px; + width: 100%; + font-size: 18px; + } } .btn { - border: 0; + border: 0; } .spinner-component-wrapper { - position: absolute; - top: 0; - width: 100vw; - height: 100vh; + position: absolute; + top: 0; + width: 100vw; + height: 100vh; + display: flex; + flex-direction: row; + justify-content: center; + + .spinner-wrapper { display: flex; - flex-direction: row; justify-content: center; - - .spinner-wrapper { - display: flex; - justify-content: center; - align-items: center; - } + align-items: center; + } } diff --git a/kdb-web/src/styles/primeng-fixes.scss b/kdb-web/src/styles/primeng-fixes.scss index c6b246f4..506f1fee 100644 --- a/kdb-web/src/styles/primeng-fixes.scss +++ b/kdb-web/src/styles/primeng-fixes.scss @@ -1,102 +1,115 @@ @import "./constants.scss"; .btn { - &:focus { - box-shadow: none !important; - } + &:focus { + box-shadow: none !important; + } } .p-menu, .p-panelmenu { - background: none !important; - border: none !important; - width: auto !important; - border-radius: 0px !important; - padding: 0 !important; + background: none !important; + border: none !important; + width: auto !important; + border-radius: 0 !important; + padding: 0 !important; - .p-menuitem-link, - .p-panelmenu-header > a, - .p-panelmenu-content .p-menuitem .p-menuitem-link { - $distance: 10px; - padding: $distance 0px $distance $distance !important; - margin: 4px 0px 4px 6px !important; - } + .p-menuitem-link, + .p-panelmenu-header > a, + .p-panelmenu-content .p-menuitem .p-menuitem-link { + $distance: 10px; + padding: $distance 0 $distance $distance !important; + margin: 4px 0 4px 6px !important; + } } header, .app { - .p-menu-overlay { - top: $headerHeight !important; - } + .p-menu-overlay { + top: $headerHeight !important; + } } .p-panelmenu { - .p-panelmenu-icon { - order: 1; // to be the first item on right side. - } - .p-menuitem-text { - flex-grow: 1; // to fill the whole space and push the icon to the end - } + .p-panelmenu-icon { + order: 1; // to be the first item on right side. + } - .p-panelmenu-header > a { - border: none !important; - border-radius: none !important; - font-weight: none !important; - transition: none !important; - } + .p-menuitem-text { + flex-grow: 1; // to fill the whole space and push the icon to the end + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } - .p-panelmenu-content { - border: none !important; - background: none !important; - } + .p-panelmenu-header > a { + border: none !important; + border-radius: unset !important; + font-weight: unset !important; + transition: none !important; + } - .p-menuitem-text { - line-height: normal !important; - } + .p-panelmenu-content { + border: none !important; + background: none !important; + } + + .p-menuitem-text { + line-height: normal !important; + } } ui-menu .ui-menu-parent .ui-menu-child { - width: 400px; /* exagerated !! */ + width: 400px; /* exagerated !! */ } .p-toast-detail { - white-space: pre-line; + white-space: pre-line; } .p-datatable .p-sortable-column:focus { - box-shadow: none !important; + box-shadow: none !important; +} + +.p-datatable > .p-datatable-wrapper { + overflow: visible !important; } .p-password { - padding: 0px !important; + padding: 0 !important; } .p-paginator { - background-color: transparent !important; - border: none !important; + background-color: transparent !important; + border: none !important; } p-table { - .p-datatable .p-datatable-header { - border: none !important; - } + .p-datatable .p-datatable-header { + border: none !important; + } - .p-datatable .p-datatable-header, - .p-datatable .p-datatable-tbody > tr, - .p-datatable .p-datatable-thead > tr > th { - background-color: transparent !important; - color: inherit !important; - } + .p-datatable .p-datatable-header, + .p-datatable .p-datatable-tbody > tr, + .p-datatable .p-datatable-thead > tr > th { + background-color: transparent !important; + color: inherit !important; + } +} + +.p-dropdown, +.p-inputnumber { + width: 100% !important; } .pi-sort-alt:before { - content: "\e915" !important; + content: "\e915" !important; } .pi-sort-amount-up-alt:before { - content: "\e914" !important; + content: "\e914" !important; } .pi-sort-amount-down:before { - content: "\e913" !important; + content: "\e913" !important; } diff --git a/kdb-web/src/styles/themes/default-dark-theme.scss b/kdb-web/src/styles/themes/default-dark-theme.scss index 9f0e2f6e..2e6cac2c 100644 --- a/kdb-web/src/styles/themes/default-dark-theme.scss +++ b/kdb-web/src/styles/themes/default-dark-theme.scss @@ -1,558 +1,610 @@ .default-dark-theme { - $primaryTextColor: #fff; - $secondayTextColor: #000; - $secondayTextColor2: #1e88e5; + $primaryTextColor: #fff; + $secondayTextColor: #000; + $secondayTextColor2: #1e88e5; - $primaryHeaderColor: #1e88e5; - $secondaryHeaderColor: #6ab7ff; - $secondaryHeaderColor2: #005cb2; + $primaryHeaderColor: #1e88e5; + $secondaryHeaderColor: #6ab7ff; + $secondaryHeaderColor2: #005cb2; - $primaryBackgroundColor: #272727; - $secondaryBackgroundColor: #4f4f4f; - $secondaryBackgroundColor2: #fff; - $secondaryBackgroundColor3: #cccccc; + $primaryBackgroundColor: #272727; + $secondaryBackgroundColor: #4f4f4f; + $secondaryBackgroundColor2: #fff; + $secondaryBackgroundColor3: #cccccc; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor3; + $default-border: 2px solid $secondaryBackgroundColor3; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $secondaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $secondaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $secondaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $secondaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { color: $primaryHeaderColor; - } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } + .p-panel-header { + background-color: $primaryBackgroundColor; - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $secondaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } + .p-panel-header-icon { + color: $primaryHeaderColor; } + } } + + .p-panel-content { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + border-top: none !important; + } + } } + } } + } - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; + .history { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .table-caption { - .table-caption-text { - } - - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } + .entry-list { + .entry { + border-bottom: 1px solid $primaryHeaderColor; + } } + } - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } + .p-dialog-content { + .content-data-name, + .content-data-value { + color: $primaryTextColor; - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } } + } - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .p-dialog { - background-color: $secondaryBackgroundColor !important; - - .p-dialog-header { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } + a { + color: $primaryTextColor; } + } + .invalid-feedback { + color: $primaryErrorColor; + } + + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { input, - .p-password input { - border-radius: 10px; - border: $default-border; + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } - &:focus { - box-shadow: none !important; + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header, + .auth-footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .login-form { + .input-field { + input, + .p-password { + } } - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; + .login-form-submit { + .login-form-submit-btn { + } } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .btn-wrapper { - display: flex !important; - align-items: center !important; + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .btn { - background-color: $primaryHeaderColor; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; + + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { + color: $primaryHeaderColor !important; + } + } + + .p-panelmenu-content { + margin: 5px 0 5px 10px; + } + } + + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { color: $primaryTextColor; - border: 0; + } - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - } - } + .p-dropdown-panel { + background-color: $secondaryBackgroundColor !important; - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .pi { - font-size: 1.275rem !important; - } - } - - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; - - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } - } - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .icon-btn { - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } + } + } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } } - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .table-edit-input { + width: 100% !important; + } + } - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; } - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; } - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; } - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - } + .p-dialog { + background-color: $secondaryBackgroundColor !important; - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; - color: $primaryHeaderColor !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + .p-dialog-header { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } + + .input-number { + span { + .p-button { + background-color: $primaryHeaderColor !important; + border: 1px solid $primaryHeaderColor !important; + + &:hover { + background-color: $secondaryHeaderColor !important; + border: 1px solid $secondaryHeaderColor !important; + } + } + } + } } diff --git a/kdb-web/src/styles/themes/default-light-theme.scss b/kdb-web/src/styles/themes/default-light-theme.scss index 69a1b97d..b8cd5b06 100644 --- a/kdb-web/src/styles/themes/default-light-theme.scss +++ b/kdb-web/src/styles/themes/default-light-theme.scss @@ -1,558 +1,610 @@ .default-light-theme { - $primaryTextColor: #272727; - $secondayTextColor: #fff; - $secondayTextColor2: #1e88e5; + $primaryTextColor: #272727; + $secondayTextColor: #fff; + $secondayTextColor2: #1e88e5; - $primaryHeaderColor: #1e88e5; - $secondaryHeaderColor: #6ab7ff; - $secondaryHeaderColor2: #005cb2; + $primaryHeaderColor: #1e88e5; + $secondaryHeaderColor: #6ab7ff; + $secondaryHeaderColor2: #005cb2; - $primaryBackgroundColor: #fff; - $secondaryBackgroundColor: #cccccc; - $secondaryBackgroundColor2: #4f4f4f; - $secondaryBackgroundColor3: #272727; + $primaryBackgroundColor: #fff; + $secondaryBackgroundColor: #cccccc; + $secondaryBackgroundColor2: #4f4f4f; + $secondaryBackgroundColor3: #272727; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor; + $default-border: 2px solid $secondaryBackgroundColor; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $primaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $primaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $primaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $primaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { color: $primaryHeaderColor; - } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } + .p-panel-header { + background-color: $primaryBackgroundColor; - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $primaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } + .p-panel-header-icon { + color: $primaryHeaderColor; } + } } + + .p-panel-content { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + border-top: none !important; + } + } } + } } + } - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; + .history { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .table-caption { - .table-caption-text { - } - - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } + .entry-list { + .entry { + border-bottom: 1px solid $primaryHeaderColor; + } } + } - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } + .p-dialog-content { + .content-data-name, + .content-data-value { + color: $primaryTextColor; - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } } + } - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .p-dialog { - background-color: $primaryBackgroundColor !important; - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } + a { + color: $primaryTextColor; } + } + .invalid-feedback { + color: $primaryErrorColor; + } + + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { input, - .p-password input { - border-radius: 10px; - border: $default-border; + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } - &:focus { - box-shadow: none !important; + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header, + .auth-footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .login-form { + .input-field { + input, + .p-password { + } } - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; + .login-form-submit { + .login-form-submit-btn { + } } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .btn-wrapper { - display: flex !important; - align-items: center !important; + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .btn { - background-color: $primaryHeaderColor; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; + + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { + color: $primaryHeaderColor !important; + } + } + + .p-panelmenu-content { + margin: 5px 0 5px 10px; + } + } + + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { color: $primaryTextColor; - border: 0; + } - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - } - } - - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - .pi { - font-size: 1.275rem !important; - } - } - - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; - - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } - - .icon-btn { - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { - color: $primaryHeaderColor !important; - } - - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; - color: $primaryHeaderColor !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + .p-dropdown-panel { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + } } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } + } + + .table-edit-input { + width: 100% !important; + } + } + + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + } + + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; + } + + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; + } + + .p-dialog { + background-color: $primaryBackgroundColor !important; + + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + } + } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } + + .input-number { + span { + .p-button { + background-color: $primaryHeaderColor !important; + border: 1px solid $primaryHeaderColor !important; + + &:hover { + background-color: $secondaryHeaderColor !important; + border: 1px solid $secondaryHeaderColor !important; + } + } + } + } } diff --git a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss index cef76707..a116773e 100644 --- a/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-dark-theme.scss @@ -1,560 +1,618 @@ .sh-edraft-dark-theme { - $primaryTextColor: #fff; - $secondayTextColor: #000; - $secondayTextColor2: #ef9d0d; + $primaryTextColor: #fff; + $secondayTextColor: #000; + $secondayTextColor2: #ef9d0d; - $primaryHeaderColor: #ef9d0d; - $secondaryHeaderColor: #ffce4c; - $secondaryHeaderColor2: #b76f00; + $primaryHeaderColor: #ef9d0d; + $secondaryHeaderColor: #ffce4c; + $secondaryHeaderColor2: #b76f00; - $primaryBackgroundColor: #272727; - $secondaryBackgroundColor: #4f4f4f; - $secondaryBackgroundColor2: #fff; - $secondaryBackgroundColor3: #cccccc; + $primaryBackgroundColor: #272727; + $secondaryBackgroundColor: #4f4f4f; + $secondaryBackgroundColor2: #fff; + $secondaryBackgroundColor3: #cccccc; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor3; + $default-border: 2px solid $secondaryBackgroundColor3; + background-color: $primaryBackgroundColor; + + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $secondaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $secondaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $secondaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $secondaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - background-color: $secondaryBackgroundColor !important; - - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { color: $primaryHeaderColor; - } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } + .p-panel-header { + background-color: $primaryBackgroundColor; - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $secondaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $secondaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } + .p-panel-header-icon { + color: $primaryHeaderColor; } + } } + + .p-panel-content { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + border-top: none !important; + } + } } + } } + } - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; + .history { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .table-caption { - .table-caption-text { - } - - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } + .entry-list { + .entry { + border-bottom: 1px solid $primaryHeaderColor; + } } + } - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } + .p-dialog-header { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + } - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } + .p-dialog-content { + background-color: $secondaryBackgroundColor !important; - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; + .content-data-name, + .content-data-value { + color: $primaryTextColor; - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } } + } - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; - .p-dialog { - background-color: $secondaryBackgroundColor !important; - - .p-dialog-header { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } + a { + color: $primaryTextColor; } + } + .invalid-feedback { + color: $primaryErrorColor; + } + + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { input, - .p-password input { - border-radius: 10px; - border: $default-border; + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } - &:focus { - box-shadow: none !important; + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header, + .auth-footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .login-form { + .input-field { + input, + .p-password { + } } - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; + .login-form-submit { + .login-form-submit-btn { + } } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .btn-wrapper { - display: flex !important; - align-items: center !important; + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .btn { - background-color: $primaryHeaderColor; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; + + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { + color: $primaryHeaderColor !important; + } + } + + .p-panelmenu-content { + margin: 5px 0 5px 10px; + } + } + + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { color: $primaryTextColor; - border: 0; + } - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - } - } + .p-dropdown-panel { + background-color: $secondaryBackgroundColor !important; - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .pi { - font-size: 1.275rem !important; - } - } - - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; - - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } - } - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $secondaryBackgroundColor !important; + color: $primaryHeaderColor !important; - .icon-btn { - &:hover { - background-color: transparent !important; + span { color: $primaryHeaderColor !important; - border: 0; + } } + } + } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } } - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; + .table-edit-input { + width: 100% !important; + } + } - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; } - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; } - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; } - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - } + .p-dialog { + background-color: $secondaryBackgroundColor !important; - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; - color: $primaryHeaderColor !important; - } - - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + .p-dialog-header { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + .p-button-label { + transition-duration: unset !important; + } + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } + + .input-number { + span { + .p-button { + background-color: $primaryHeaderColor !important; + border: 1px solid $primaryHeaderColor !important; + + &:hover { + background-color: $secondaryHeaderColor !important; + border: 1px solid $secondaryHeaderColor !important; + } + } + } + } } diff --git a/kdb-web/src/styles/themes/sh-edraft-light-theme.scss b/kdb-web/src/styles/themes/sh-edraft-light-theme.scss index 8ae5f724..ab335ab3 100644 --- a/kdb-web/src/styles/themes/sh-edraft-light-theme.scss +++ b/kdb-web/src/styles/themes/sh-edraft-light-theme.scss @@ -1,558 +1,610 @@ .sh-edraft-light-theme { - $primaryTextColor: #272727; - $secondayTextColor: #fff; - $secondayTextColor2: #ef9d0d; + $primaryTextColor: #272727; + $secondayTextColor: #fff; + $secondayTextColor2: #ef9d0d; - $primaryHeaderColor: #ef9d0d; - $secondaryHeaderColor: #ffce4c; - $secondaryHeaderColor2: #b76f00; + $primaryHeaderColor: #ef9d0d; + $secondaryHeaderColor: #ffce4c; + $secondaryHeaderColor2: #b76f00; - $primaryBackgroundColor: #fff; - $secondaryBackgroundColor: #cccccc; - $secondaryBackgroundColor2: #4f4f4f; - $secondaryBackgroundColor3: #272727; + $primaryBackgroundColor: #fff; + $secondaryBackgroundColor: #cccccc; + $secondaryBackgroundColor2: #4f4f4f; + $secondaryBackgroundColor3: #272727; - $primaryErrorColor: #b00020; - $secondaryErrorColor: #e94948; + $primaryErrorColor: #b00020; + $secondaryErrorColor: #e94948; - $default-border: 2px solid $secondaryBackgroundColor; + $default-border: 2px solid $secondaryBackgroundColor; + background-color: $primaryBackgroundColor; + + h1, + h2 { + color: $primaryHeaderColor; + } + + input, + p { + color: $primaryTextColor; + } + + input { + background-color: $primaryBackgroundColor !important; + } + + .input-field-info-text { + color: $primaryTextColor; + } + + /* Change Autocomplete styles in Chrome*/ + input:-webkit-autofill, + input:-webkit-autofill:hover, + input:-webkit-autofill:focus, + textarea:-webkit-autofill, + textarea:-webkit-autofill:hover, + textarea:-webkit-autofill:focus, + select:-webkit-autofill, + select:-webkit-autofill:hover, + select:-webkit-autofill:focus { + border: 1px solid $primaryHeaderColor; + -webkit-text-fill-color: $primaryTextColor; + -webkit-box-shadow: 0 0 0 1000px $primaryBackgroundColor inset; + transition: background-color 5000s ease-in-out 0s; + } + + header { background-color: $primaryBackgroundColor; - h1, - h2 { - color: $primaryHeaderColor; - } - - input, - p { - color: $primaryTextColor; - } - - input { - background-color: $primaryBackgroundColor !important; - } - - .input-field-info-text { - color: $primaryTextColor; - } - - /* Change Autocomplete styles in Chrome*/ - input:-webkit-autofill, - input:-webkit-autofill:hover, - input:-webkit-autofill:focus, - textarea:-webkit-autofill, - textarea:-webkit-autofill:hover, - textarea:-webkit-autofill:focus, - select:-webkit-autofill, - select:-webkit-autofill:hover, - select:-webkit-autofill:focus { - border: 1px solid $primaryHeaderColor; - -webkit-text-fill-color: $primaryTextColor; - -webkit-box-shadow: 0 0 0px 1000px $primaryBackgroundColor inset; - transition: background-color 5000s ease-in-out 0s; - } - - header { - background-color: $primaryBackgroundColor; - - .logo-button-wrapper { - .p-button.p-button-text { - color: $primaryTextColor; - - &:hover { - color: $primaryTextColor; - background-color: $primaryBackgroundColor; - } - } - } - - .logo { - color: $primaryHeaderColor; - } - } - - h1 { - color: $primaryHeaderColor; - } - - .app { - .sidebar { - background-color: $primaryBackgroundColor; - - .menu { - color: $primaryTextColor; - } - } - - .component-wrapper { - color: $primaryTextColor; - - .component { - background-color: $secondaryBackgroundColor; - - .content-wrapper { - background-color: $primaryBackgroundColor; - border-top: 2px solid $primaryHeaderColor; - - .content-header { - border-bottom: $default-border; - } - - .content { - .content-row { - } - - .content-column { - } - - .content-data-name { - } - - .content-data-value { - } - - .content-divider { - border-bottom: $default-border; - } - } - - .server-list-wrapper { - .server-filter { - } - - .server-count { - } - - .server-list { - .server { - border: $default-border; - border-radius: 15px; - - .logo { - img { - border-radius: 100%; - } - } - - .name { - color: $primaryHeaderColor; - } - - &:hover { - border-color: $primaryHeaderColor !important; - } - } - } - } - } - } - } - } - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content { - .content-data-name, - .content-data-value { - color: $primaryTextColor; - - .text-btn { - font-size: 18px !important; - font-weight: 400 !important; - } - } - } - - footer { - background-color: $primaryBackgroundColor; + .logo-button-wrapper { + .p-button.p-button-text { color: $primaryTextColor; - a { - color: $primaryTextColor; + &:hover { + color: $primaryTextColor; + background-color: $primaryBackgroundColor; } + } } - .invalid-feedback { - color: $primaryErrorColor; + .logo { + color: $primaryHeaderColor; + } + } + + h1 { + color: $primaryHeaderColor; + } + + .app { + .sidebar { + background-color: $primaryBackgroundColor; + + .menu { + color: $primaryTextColor; + } } - .invalid-feedback-input, - .invalid-feedback-input:focus, - .invalid-feedback-input:hover { - input, - input:enabled:focus { - outline: 1px solid $primaryErrorColor !important; - border: 1px solid $primaryErrorColor !important; - border-color: $primaryErrorColor !important; - } - } + .component-wrapper { + color: $primaryTextColor; - .login-wrapper { + .component { background-color: $secondaryBackgroundColor; - .login-form-wrapper, - .auth-header { - background-color: $primaryBackgroundColor; + .content-wrapper { + background-color: $primaryBackgroundColor; + border-top: 2px solid $primaryHeaderColor; - .login-form { - .input-field { - input, - .p-password { - } - } + .content-header { + border-bottom: $default-border; + } - .login-form-submit { - .login-form-submit-btn { - } - } - - .login-form-sub-button-wrapper { - .login-form-sub-btn { - background-color: $primaryBackgroundColor; - color: $secondayTextColor2; - border: 2px solid $secondayTextColor2; - - &:hover { - background-color: $primaryHeaderColor !important; - color: $primaryTextColor !important; - } - } - - .login-form-sub-login-btn { - border: none; - } - } + .content { + .content-row { } - } - } - .spinner-component-wrapper { - background-color: rgba($secondaryBackgroundColor, 0.5); + .content-column { + } - .spinner-wrapper { - .custom-spinner .p-progress-spinner-circle { + .content-data-name { + } + + .content-data-value { + } + + .content-divider { + border-bottom: $default-border; + } + } + + p-panel { + .p-panel-header, + .p-panel-content { + border: $default-border; + } + + .p-panel-title { + color: $primaryHeaderColor; + } + + .p-panel-header { + background-color: $primaryBackgroundColor; + + .p-panel-header-icon { color: $primaryHeaderColor; + } } - } - } + } - .wrapper-right { - justify-content: flex-end !important; - } - - /* - PrimeNG Fixes - */ - .p-progress-spinner-circle { - stroke: $primaryHeaderColor !important; - } - - .p-menu, - .p-panelmenu { - color: $primaryTextColor !important; - - .p-menuitem-link .p-menuitem-text, - .p-menuitem-link .p-menuitem-icon, - .p-panelmenu-header > a { - color: $primaryTextColor !important; - background: transparent !important; - font-size: 1rem !important; - font-weight: normal !important; - } - - .p-menuitem-link:focus, - .p-panelmenu-header > a:focus, - .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { - box-shadow: none !important; - } - - .p-menuitem-link:hover, - .p-panelmenu-header > a:hover, - .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { - background-color: $secondaryBackgroundColor !important; - $border-radius: 20px; - border-radius: $border-radius 0px 0px $border-radius; - - .p-menuitem-text, - .p-menuitem-icon, - .p-menuitem-text, - .p-panelmenu-icon { - color: $primaryHeaderColor !important; - } - } - - .p-panelmenu-content { - margin: 5px 0px 5px 10px; - } - } - - .p-menu-overlay { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - border-top: 2px solid $primaryHeaderColor !important; - - .p-menuitem-link:hover { - background-color: $primaryBackgroundColor !important; - .p-menuitem-text, - .p-menuitem-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dropdown { - .p-dropdown { - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - color: $primaryTextColor !important; - - span { - color: $primaryTextColor; - } - - .p-dropdown-panel { - background-color: $primaryBackgroundColor !important; - - .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - - .p-dropdown-items .p-dropdown-item.p-highlight { - background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; - - span { - color: $primaryHeaderColor !important; - } - } - } - } - } - - p-table { - background-color: $primaryBackgroundColor; - color: $primaryTextColor !important; - - .table-caption { - .table-caption-text { - } - - .table-caption-search-wrapper { - .table-caption-search { - height: 30px !important; - - .table-caption-search-icon { - } - - .table-caption-search-input { - height: 100% !important; - - &:focus { - outline-color: $primaryHeaderColor; - } - } - } - } - - .table-caption-btn-wrapper { - height: 30px !important; - } - } - - .table-edit-input { - width: 100% !important; - } - } - - p-checkbox { - .p-checkbox .p-checkbox-box { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - } - - .p-checkbox .p-checkbox-box.p-highlight { - background: $primaryBackgroundColor !important; - background-color: $primaryBackgroundColor !important; - border-color: $primaryTextColor !important; - box-shadow: none !important; - } - - .p-checkbox .p-checkbox-box .p-checkbox-icon { - color: $primaryTextColor !important; - } - - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, - .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; - - .p-checkbox-icon { - color: $primaryHeaderColor !important; - } - } - } - - p-dialog, - p-confirmdialog, - p-dynamicdialog { - .p-dialog.p-confirm-dialog .p-confirm-dialog-message { - margin-left: 0px !important; - } - - .p-dialog { - background-color: $primaryBackgroundColor !important; - - .p-dialog-header { - background-color: $secondaryBackgroundColor !important; - color: $primaryTextColor !important; - } - - .p-dialog-content, - .p-dialog-footer { - background-color: $primaryBackgroundColor !important; - color: $primaryTextColor !important; - } - } - } - - input, - .p-password input { - border-radius: 10px; - border: $default-border; - - &:focus { - box-shadow: none !important; - } - - &:hover, - &:active, - &:enabled:focus { - border-color: $primaryHeaderColor !important; - } - } - - .btn-wrapper { - display: flex !important; - align-items: center !important; - } - - .btn { - background-color: $primaryHeaderColor; - color: $primaryTextColor; - border: 0; - - &:hover, - &:enabled:hover { - background-color: $primaryHeaderColor; + .p-panel-content { + background-color: $primaryBackgroundColor; color: $primaryTextColor; - border: 0; + border-top: none !important; + } + + .server-list-wrapper { + .server-filter { + } + + .server-count { + } + + .server-list { + .server { + border: $default-border; + border-radius: 15px; + + .logo { + img { + border-radius: 100%; + } + } + + .name { + color: $primaryHeaderColor; + } + + &:hover { + border-color: $primaryHeaderColor !important; + } + } + } + } } + } + } + } + + .history { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + + .entry-list { + .entry { + border-bottom: 1px solid $primaryHeaderColor; + } + } + } + + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content { + .content-data-name, + .content-data-value { + color: $primaryTextColor; + + .text-btn { + font-size: 18px !important; + font-weight: 400 !important; + } + } + } + + footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor; + + a { + color: $primaryTextColor; + } + } + + .invalid-feedback { + color: $primaryErrorColor; + } + + .invalid-feedback-input, + .invalid-feedback-input:focus, + .invalid-feedback-input:hover { + input, + input:enabled:focus { + outline: 1px solid $primaryErrorColor !important; + border: 1px solid $primaryErrorColor !important; + border-color: $primaryErrorColor !important; + } + } + + .login-wrapper { + background-color: $secondaryBackgroundColor; + + .login-form-wrapper, + .auth-header, + .auth-footer { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .login-form { + .input-field { + input, + .p-password { + } + } + + .login-form-submit { + .login-form-submit-btn { + } + } + + .login-form-sub-button-wrapper { + .login-form-sub-btn { + background-color: $primaryBackgroundColor; + color: $secondayTextColor2; + border: 2px solid $secondayTextColor2; + + &:hover { + background-color: $primaryHeaderColor !important; + color: $primaryTextColor !important; + } + } + + .login-form-sub-login-btn { + border: none; + } + } + } + } + } + + .spinner-component-wrapper { + background-color: rgba($secondaryBackgroundColor, 0.5); + + .spinner-wrapper { + .custom-spinner .p-progress-spinner-circle { + color: $primaryHeaderColor; + } + } + } + + .wrapper-right { + justify-content: flex-end !important; + } + + /* + PrimeNG Fixes + */ + .p-progress-spinner-circle { + stroke: $primaryHeaderColor !important; + } + + .p-menu, + .p-panelmenu { + color: $primaryTextColor !important; + + .p-menuitem-link .p-menuitem-text, + .p-menuitem-link .p-menuitem-icon, + .p-panelmenu-header > a { + color: $primaryTextColor !important; + background: transparent !important; + font-size: 1rem !important; + font-weight: normal !important; } - .icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - .pi { - font-size: 1.275rem !important; - } + .p-menuitem-link:focus, + .p-panelmenu-header > a:focus, + .p-panelmenu-content .p-menuitem .p-menuitem-link:focus { + box-shadow: none !important; } - .text-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - padding: 0px !important; + .p-menuitem-link:hover, + .p-panelmenu-header > a:hover, + .p-panelmenu-content .p-menuitem .p-menuitem-link:hover { + background-color: $secondaryBackgroundColor !important; + $border-radius: 20px; + border-radius: $border-radius 0 0 $border-radius; - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .icon-btn-without-hover { - &:hover { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - } - } - - .icon-btn { - &:hover { - background-color: transparent !important; - color: $primaryHeaderColor !important; - border: 0; - } - } - - .danger-icon-btn { - background-color: transparent !important; - color: $primaryTextColor !important; - border: 0 !important; - - &:hover { - background-color: transparent !important; - color: $primaryErrorColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .danger-btn { - background-color: $primaryErrorColor !important; - color: $primaryErrorColor !important; - border: 0 !important; - - &:hover { - background-color: $primaryErrorColor !important; - color: $primaryTextColor !important; - border: 0; - } - - .pi { - font-size: 1.275rem !important; - } - } - - .p-datatable .p-sortable-column.p-highlight, - .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + .p-menuitem-text, + .p-menuitem-icon, + .p-menuitem-text, + .p-panelmenu-icon { color: $primaryHeaderColor !important; + } } - .p-dropdown:not(.p-disabled):hover, - .p-dropdown:not(.p-disabled).p-focus, - .p-link:focus { - border-color: $primaryHeaderColor !important; - box-shadow: none !important; + .p-panelmenu-content { + margin: 5px 0 5px 10px; } + } - .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { - background: transparent !important; - background-color: transparent !important; + .p-menu-overlay { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + border-top: 2px solid $primaryHeaderColor !important; + + .p-menuitem-link:hover { + background-color: $primaryBackgroundColor !important; + + .p-menuitem-text, + .p-menuitem-icon { color: $primaryHeaderColor !important; + } } + } - .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, - .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, - .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + p-dropdown { + .p-dropdown { + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + color: $primaryTextColor !important; + + span { + color: $primaryTextColor; + } + + .p-dropdown-panel { background-color: $primaryBackgroundColor !important; - color: $primaryHeaderColor !important; + + .p-dropdown-items .p-dropdown-item:not(.p-highlight):not(.p-disabled):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + + .p-dropdown-items .p-dropdown-item.p-highlight { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + + span { + color: $primaryHeaderColor !important; + } + } + } } + } + + p-table { + background-color: $primaryBackgroundColor; + color: $primaryTextColor !important; + + .table-caption { + .table-caption-text { + } + + .table-caption-search-wrapper { + .table-caption-search { + height: 30px !important; + + .table-caption-search-icon { + } + + .table-caption-search-input { + height: 100% !important; + + &:focus { + outline-color: $primaryHeaderColor; + } + } + } + } + + .table-caption-btn-wrapper { + height: 30px !important; + } + } + + .table-edit-input { + width: 100% !important; + } + } + + p-checkbox { + .p-checkbox .p-checkbox-box { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + } + + .p-checkbox .p-checkbox-box.p-highlight { + background: $primaryBackgroundColor !important; + background-color: $primaryBackgroundColor !important; + border-color: $primaryTextColor !important; + box-shadow: none !important; + } + + .p-checkbox .p-checkbox-box .p-checkbox-icon { + color: $primaryTextColor !important; + } + + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box.p-focus, + .p-checkbox:not(.p-checkbox-disabled) .p-checkbox-box:hover { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + + .p-checkbox-icon { + color: $primaryHeaderColor !important; + } + } + } + + p-dialog, + p-confirmdialog, + p-dynamicdialog { + .p-dialog.p-confirm-dialog .p-confirm-dialog-message { + margin-left: 0 !important; + } + + .p-dialog { + background-color: $primaryBackgroundColor !important; + + .p-dialog-header { + background-color: $secondaryBackgroundColor !important; + color: $primaryTextColor !important; + } + + .p-dialog-content, + .p-dialog-footer { + background-color: $primaryBackgroundColor !important; + color: $primaryTextColor !important; + } + } + } + + input, + .p-password input { + border-radius: 10px; + border: $default-border; + + &:focus { + box-shadow: none !important; + } + + &:hover, + &:active, + &:enabled:focus { + border-color: $primaryHeaderColor !important; + } + } + + .btn-wrapper { + display: flex !important; + align-items: center !important; + } + + .btn { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + + &:hover, + &:enabled:hover { + background-color: $primaryHeaderColor; + color: $primaryTextColor; + border: 0; + } + } + + .icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + .pi { + font-size: 1.275rem !important; + } + } + + .text-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + padding: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .icon-btn-without-hover { + &:hover { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + } + } + + .icon-btn { + &:hover { + background-color: transparent !important; + color: $primaryHeaderColor !important; + border: 0; + } + } + + .danger-icon-btn { + background-color: transparent !important; + color: $primaryTextColor !important; + border: 0 !important; + + &:hover { + background-color: transparent !important; + color: $primaryErrorColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .danger-btn { + background-color: $primaryErrorColor !important; + color: $primaryErrorColor !important; + border: 0 !important; + + &:hover { + background-color: $primaryErrorColor !important; + color: $primaryTextColor !important; + border: 0; + } + + .pi { + font-size: 1.275rem !important; + } + } + + .p-datatable .p-sortable-column.p-highlight, + .p-datatable .p-sortable-column.p-highlight .p-sortable-column-icon { + color: $primaryHeaderColor !important; + } + + .p-dropdown:not(.p-disabled):hover, + .p-dropdown:not(.p-disabled).p-focus, + .p-link:focus { + border-color: $primaryHeaderColor !important; + box-shadow: none !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page.p-highlight { + background: transparent !important; + color: $primaryHeaderColor !important; + } + + .p-paginator .p-paginator-pages .p-paginator-page:not(.p-highlight):hover, + .p-paginator .p-paginator-first:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-prev:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-next:not(.p-disabled):not(.p-highlight):hover, + .p-paginator .p-paginator-last:not(.p-disabled):not(.p-highlight):hover { + background-color: $primaryBackgroundColor !important; + color: $primaryHeaderColor !important; + } + + .input-number { + span { + .p-button { + background-color: $primaryHeaderColor !important; + border: 1px solid $primaryHeaderColor !important; + + &:hover { + background-color: $secondaryHeaderColor !important; + border: 1px solid $secondaryHeaderColor !important; + } + } + } + } } diff --git a/kdb-web/src/test.ts b/kdb-web/src/test.ts index c04c8760..51bb0206 100644 --- a/kdb-web/src/test.ts +++ b/kdb-web/src/test.ts @@ -7,20 +7,8 @@ import { platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; -declare const require: { - context(path: string, deep?: boolean, filter?: RegExp): { - (id: string): T; - keys(): string[]; - }; -}; - // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting(), ); - -// Then we find all the tests. -const context = require.context('./', true, /\.spec\.ts$/); -// And load the modules. -context.keys().forEach(context); diff --git a/kdb-web/tsconfig.json b/kdb-web/tsconfig.json index e541544c..f53324f8 100644 --- a/kdb-web/tsconfig.json +++ b/kdb-web/tsconfig.json @@ -1,4 +1,3 @@ -/* To learn more about this file see: https://angular.io/config/tsconfig. */ { "ts-node": { "compilerOptions": { @@ -21,12 +20,15 @@ "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, - "target": "es2020", + "target": "ES2022", "module": "es2020", "lib": [ "es2020", - "dom" - ] + "dom", + "esnext.asynciterable" + ], + "allowSyntheticDefaultImports": true, + "useDefineForClassFields": false }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, @@ -34,4 +36,4 @@ "strictInputAccessModifiers": true, "strictTemplates": true } -} +} \ No newline at end of file diff --git a/kdb-web/update-version.ts b/kdb-web/update-version.ts index ba147f1d..e81b3376 100644 --- a/kdb-web/update-version.ts +++ b/kdb-web/update-version.ts @@ -33,7 +33,7 @@ async function getVersion(): Promise { } if (versions.length > 2) { - micro = versions[2]; + micro = versions.slice(2).toString().replace(',', '.'); } } else if (branch.startsWith("#")) { const fs = require("fs"); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..9f4677cd --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "kd_discord_bot", + "lockfileVersion": 3, + "requires": true, + "packages": {} +}